先把结论放在前面:这套环境配置本身不难,难的是很多人把“驱动、CUDA Toolkit、CUDNN、NVENC”这四层东西混在一起,导致出了问题根本不知道该查哪一层。这篇文章我会从头到尾走一遍 Ubuntu 20.04 下的部署流程,覆盖 NVIDIA 显卡驱动安装、CUDA 与 CUDNN 的安装验证、NVENC 并发限制的突破,以及多版本 CUDA 切换这四件事。适合做深度学习、SLAM、视频转码、直播推流的同学直接抄作业,也能帮刚入坑 Linux 的读者把这些概念真正理清楚。
我会把自己踩过的坑和排查路径一并写在里面,尤其是“装完驱动后 nvcc 找不到”“cuda_xxx.run 解压报 gzip invalid compressed data”“NVENC 打补丁后驱动升级失效”这类高频问题,按我的经验,提前知道这些能省下大半天时间。
1. 方案选型与整体架构
1.1 先想清楚:你需要的到底是哪一层
很多教程喜欢把“显卡驱动、CUDA、CUDNN”放在一起装,但它们在系统中的位置完全不一样。
NVIDIA 驱动是唯一和硬件直接打交道的内核态部分,它负责让操作系统识别 GPU,也负责提供编解码硬件的接口。CUDA Toolkit 是在驱动之上运行的开发套件,包含编译器 nvcc、运行时库 libcudart、数学库 cuBLAS/cuFFT 等。CUDNN 则是针对深度神经网络的加速库,它依赖 CUDA 运行时,但不和驱动直接通信。NVENC 则是显卡上的硬件编码器,驱动装好后基本就能用,只是消费级显卡在 SDK 层面有并发会话数限制,后面我会细讲。
用一个不太严谨但好理解的说法:驱动是“路”,CUDA 是“车”,CUDNN 是“货物”,NVENC 是“装卸港口”。路不通,后面全白搭;车不对版,货物也运不出去。
实操中我见过最多的问题就是:驱动装完了,nvidia-smi能正常显示,但nvcc -V报 command not found。这是因为驱动只代表底层跑通了,CUDA Toolkit 还没有装。反过来,也有人把 CUDA Toolkit 装了好几遍,但驱动版本太老,导致程序一启动就报CUDA driver version is insufficient。这两种情况都说明,理解各层的关系比盲目复制命令重要得多。
1.2 环境确认与准备工作
开始之前,先用下面几条命令把机器摸清楚:
# 查看显卡型号 lspci | grep -i nvidia # 查看内核版本 uname -a # 查看系统版本 lsb_release -a # 检查是否已安装 nvidia 相关包 dpkg -l | grep -i nvidia如果是双系统或者新组装的机器,建议先检查 BIOS 里 Secure Boot 是否关闭。Secure Boot 开启状态下,第三方内核模块如果没有签名,重启后驱动会加载失败。这个问题在 Ubuntu 20.04 上特别常见,很多人的驱动装完看起来成功了,重启后nvidia-smi却提示couldn't communicate with the NVIDIA driver,多数就是 Secure Boot 在作怪。
另外,如果你的机器之前曾经装过 NVIDIA 驱动,强烈建议先彻底卸载再装新的:
sudo apt purge nvidia-* libnvidia-* -y sudo apt autoremove -y这是因为 apt 和 runfile 两种方式安装的驱动会互相覆盖,混着装很容易出现nvidia-smi符号链接指向错误、驱动模块版本不匹配等诡异问题。卸载完成后重启一次,确保系统回到干净状态再继续。
2. NVIDIA 驱动安装:推荐 apt 方案,附 runfile 兜底
2.1 用 apt 安装,省心且好维护
Ubuntu 20.04 自带 NVIDIA 驱动的软件源,使用起来非常简单:
# 可以先看系统推荐哪个版本 sudo ubuntu-drivers devices这个命令会列出当前可用的驱动版本,并标注 recommended,一般照着推荐版本装就行。比如显示推荐nvidia-driver-535,那就直接装它:
sudo apt install nvidia-driver-535装完重启:
sudo reboot重启后执行:
nvidia-smi如果能看到类似下面这样的表格,说明驱动已经正常工作:
+---------------------------------------------------------------------------------------+ | NVIDIA-SMI 535.154.05 Driver Version: 535.154.05 CUDA Version: 12.2 | +---------------------------------------------------------------------------------------+这里有个常见误区,我要特别说明一下:nvidia-smi右上角显示的CUDA Version,并不是你已经安装了 CUDA Toolkit 的版本,而是当前驱动最多能支持到哪个 CUDA 版本。比如驱动 535 最高支持 CUDA 12.2,即便你现在没装任何 CUDA Toolkit,它也会显示 12.2。所以网上有帖子用这个数字判断“我是不是已经装好 CUDA 了”,是不准确的。
apt 方式最大的优势是:内核升级后,DKMS 会自动把 NVIDIA 内核模块重新编译一遍,不需要你手动干预。这对于长期使用、经常滚内核更新的用户来说非常省心。缺点是版本更新相对保守,如果你需要最新驱动特性,可能还得等一等。
2.2 runfile 方式与 apt 方式的取舍
有些场景下 apt 装不了,比如用着特殊内核、需要特定版本驱动,或者需要在无网环境离线安装,这时我会改用 runfile 方式。去 NVIDIA 官方驱动下载页找到对应型号和系统的.run文件,然后:
chmod +x NVIDIA-Linux-x86_64-535.154.05.run sudo ./NVIDIA-Linux-x86_64-535.154.05.run但 runfile 方式有几个明显痛点。第一,安装过程中通常会要求你先禁用 nouveau 开源驱动,否则会直接中断;第二,内核升级后需要手动重新执行nvidia-smi或重新运行 runfile,否则驱动可能失效;第三,如果中断或者反复安装,容易留下残留文件。
所以我的建议很直接:能用 apt 就优先 apt。runfile 只作为离线环境或者特殊需求下的兜底方案,不建议在主力机器上频繁使用。如果你是在内网环境离线装驱动,就先去另一台能联网的机器下好.run文件,拷进内网后按上面流程操作,同时把系统里的 nouveau 禁掉:
sudo bash -c "echo 'blacklist nouveau' >> /etc/modprobe.d/blacklist-nouveau.conf" sudo bash -c "echo 'options nouveau modeset=0' >> /etc/modprobe.d/blacklist-nouveau.conf" sudo update-initramfs -u需要注意,禁用 nouveau 后需要重启生效,重启完显卡会进入低分辨率模式,这是正常现象,不用担心。
3. CUDA 安装与版本选择
3.1 选 CUDA 版本,不要盲目追新
很多刚入门的朋友以为 CUDA 越新越好,这是一个相当大的误解。CUDA 版本要和你的应用生态匹配,尤其是 PyTorch、TensorFlow、TensorRT 这些框架,它们不是立刻支持最新 CUDA 的。装了一个过于新的 CUDA,很可能出现:
- PyTorch 官方 wheel 里预编译的 CUDA 运行时版本低于系统 CUDA,跑起来没任何问题,但编译扩展时却报版本不匹配;
- 某些老项目(比如基于 CUDA 10.1 编译的代码)在新版 CUDA 下链接失败;
- 第三方库没有提前适配,互相冲突。
比较稳妥的思路是:先看项目需要的 CUDA 版本,再倒推需要装哪个驱动版本。因为新版驱动一般都向下兼容旧 CUDA,但旧驱动不一定支持新 CUDA。
这里放一张我常用的对应关系表(基于长期实践整理,供参考):
| 驱动系列 | 最高支持 CUDA | 适用场景 |
|---|---|---|
| 470.x | CUDA 11.4 | 老项目、CUDA 10.x/11.x 配套驱动 |
| 515.x | CUDA 11.7 | PyTorch 1.13 时代常用 |
| 525.x | CUDA 12.0 | 过渡期 |
| 535.x | CUDA 12.2 | 目前深度学习环境的主流稳定选择 |
| 550.x | CUDA 12.4 | 新卡、新框架、需要较新特性时使用 |
如果你用的是 RTX 40 系显卡,建议驱动至少 535 起步,这样对 CUDA 12.x 的支持比较完整。如果只是普通使用,安装 CUDA 11.8 配驱动 525 或 535 也完全可以,PyTorch 对这个组合的兼容性最好。
3.2 下载与校验:gzip invalid compressed data 的处理
在 NVIDIA 官网选择 Linux -> x86_64 -> Ubuntu -> 20.04 -> runfile (local),下载得到cuda_11.8.0_520.61.05_linux.run这样的文件。这一步很容易出问题,特别是热词里提到的gzip: stdin: invalid compressed>md5sum cuda_11.8.0_520.61.05_linux.run
把输出和官网提供的 MD5 值对比,不一致就重新下载。比较稳妥的方式是用镜像站下载,或者在浏览器里开断点续传,不要用迅雷等下载工具改文件格式。另外我提醒一句:如果你把.run文件放在 NTFS 分区(比如 Windows 和 Ubuntu 共用的数据盘)上,执行时也可能因为权限问题解压失败,建议先拷到 Linux 原生文件系统(比如~/Downloads)再执行。
3.3 runfile 静默安装与符号链接
确认文件完整后,执行安装。这里不建议用图形交互界面,很容易在最后一步操作符搞乱,直接用一行静默安装命令:
sudo sh cuda_11.8.0_520.61.05_linux.run --toolkit --silent --override解释一下参数:--toolkit表示只装 CUDA Toolkit 而不装驱动,因为我们前面已经通过 apt 装好驱动了,避免 runfile 自带的旧驱动覆盖掉 apt 版本;--silent是静默安装,不再弹对话框;--override是为了绕过“系统中已有更高版本驱动”的检查提示。
安装完成后,默认会装到/usr/local/cuda-11.8,并在/usr/local/cuda建一个符号链接指向它。确认一下:
ls -l /usr/local/cuda如果这个软链接不存在,需要手动设置。接下来把 CUDA 的 bin 目录和 lib 目录加入用户环境变量,让nvcc命令和程序运行时能找到。我习惯写进/etc/profile.d/cuda.sh,这样所有用户都能用:
sudo bash -c "cat > /etc/profile.d/cuda.sh << 'EOF' export PATH=/usr/local/cuda/bin:\$PATH export LD_LIBRARY_PATH=/usr/local/cuda/lib64:\$LD_LIBRARY_PATH EOF"然后重新加载:
source /etc/profile.d/cuda.sh nvcc -V看到类似Cuda compilation tools, release 11.8, V11.8.89的输出,说明 CUDA Toolkit 安装成功。
有朋友可能会问:nvidia-smi显示 CUDA 12.2,但我装的是 CUDA 11.8,会不会冲突?不会,因为驱动最高支持 12.2,向下兼容 11.8。nvcc -V是 Toolkit 的实际版本,nvidia-smi是驱动的能力上限,两者不一致是正常现象,并不代表安装出错了。
4. CUDNN 安装与版本验证
4.1 deb 包安装,最稳的一种方式
CUDNN 在 NVIDIA 官网需要注册账号才能下载。选好和你的 CUDA 版本匹配的 CUDNN 版本,这里我以 CUDA 11.8 配 CUDNN 8.9.x 为例。下载页面会提供几种格式,推荐优先选择 deb 包,因为它会自动把头文件、库文件放到对应 CUDA 目录,并处理好符号链接,比 tar 包省心不少。
deb 包安装通常需要三个包,按顺序装:
sudo dpkg -i libcudnn8_8.9.5.29-1+cuda11.8_amd64.deb sudo dpkg -i libcudnn8-dev_8.9.5.29-1+cuda11.8_amd64.deb sudo dpkg -i libcudnn8-samples_8.9.5.29-1+cuda11.8_amd64.deblibcudnn8是运行库,跑程序必需;libcudnn8-dev是头文件和软链接,编译程序必需;libcudnn8-samples是官方样例,用来验证是否正确。如果提示依赖错误,就执行:
sudo apt --fix-broken install -y然后重新执行 dpkg 安装。
4.2 tar 包安装,适合多版本共存
tar 包形式的 CUDNN 更适合做多版本管理。下载下来的 tar 包解压后是一个cuda目录,里面包含include和lib64。需要手动把文件拷贝到 CUDA 安装目录:
tar -xzvf cudnn-linux-x86_64-8.9.5.29_cuda11-archive.tar.xz cd cudnn-linux-x86_64-8.9.5.29_cuda11-archive sudo cp -P include/cudnn*.h /usr/local/cuda-11.8/include/ sudo cp -P lib/libcudnn* /usr/local/cuda-11.8/lib64/ sudo chmod a+r /usr/local/cuda-11.8/include/cudnn*.h注意cp -P是为了保留符号链接,如果不加,后续程序运行时会报 libcudnn.so 找不到,因为软链接断了。
deb 和 tar 两种方式怎么选?我的经验是:如果只装一个 CUDA 版本,直接用 deb 最省事;如果后面打算做多版本 CUDA 切换,则更建议 tar 包,因为库文件都放在各自的 CUDA 目录下,切换版本时不会互相串。
4.3 CUDNN 版本验证
很多教程告诉你用nvcc -V验证 CUDA 就行了,但 CUDNN 的验证往往被忽略。这里提供两个可靠的方法。
方法一,查看头文件版本号:
cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2输出类似:
#define CUDNN_MAJOR 8 #define CUDNN_MINOR 9 #define CUDNN_PATCHLEVEL 5方法二,编译运行官方样例:
cp -r /usr/src/cudnn_samples_v8 ~/cudnn_samples_v8 cd ~/cudnn_samples_v8/mnistCUDNN sudo apt install libfreeimage3 libfreeimage-dev -y make clean && make ./mnistCUDNN如果看到最后一行输出Test passed!,说明 CUDNN 安装完全正常。这个测试会真实地调用 GPU 跑一遍卷积网络推理,比单纯看文件是否存在靠谱得多。
5. NVENC 并发限制突破
5.1 限制到底卡在哪
NVENC 是 NVIDIA 显卡的硬件编码器,在直播推流、视频转码、游戏录制等场景里非常有用。但 NVIDIA 在消费级显卡上做了限制:同一时间最多只能有 3 个 NVENC 编码会话。对于个人用户来说,同时开 OBS 推流、录屏、转码,可能就会撞到这个上限。
这个限制不是硬件做不到,而是 NVIDIA 在驱动和 SDK 层刻意设置的。专业级显卡(如 Quadro、RTX A 系列)没有这个限制,收费标准还不便宜。于是社区里就有了比较成熟的解决方案,核心思路是修改驱动自带的编码器接口库文件,把 3 路会话数的检查逻辑绕过,让它不再限制会话个数。
下面先确认一下当前卡的 NVENC 会话限制。可以用 NVIDIA 官方提供的nvidia-smi查看编码器会话:
nvidia-smi -q -d ENCODER_STATS如果显示Session Count一直卡在 3,且你已经确认没有别的进程在编码,那就是被限制了。
5.2 用 nvidia-patch 解除会话数限制
目前社区里最常用的是 GitHub 上的 keylase/nvidia-patch 项目。它提供了一键脚本,能自动替换驱动中libnvcuvid.so和libnvencodeapi.so相关的限制逻辑。使用步骤比较简单:
- 先看一下自己驱动版本,去 patch 仓库确认是否支持;
- 下载对应版本分支的脚本;
- 执行脚本自动打补丁;
- 重启系统让补丁生效。
具体操作大致如下:
# 进入驱动补丁项目目录 git clone https://github.com/keylase/nvidia-patch.git cd nvidia-patch # 查看驱动版本 nvidia-smi # 执行针对当前版本的 patch 脚本 ./patch.sh执行完后,可以运行 ffmpeg 并发推几个编码任务来验证:
ffmpeg -re -i input.mp4 -c:v h264_nvenc -b:v 5M -f mpegts udp://127.0.0.1:10001 & ffmpeg -re -i input2.mp4 -c:v h264_nvenc -b:v 5M -f mpegts udp://127.0.0.1:10002 & ffmpeg -re -i input3.mp4 -c:v h264_nvenc -b:v 5M -f mpegts udp://127.0.0.1:10003 & ffmpeg -re -i input4.mp4 -c:v h264_nvenc -b:v 5M -f mpegts udp://127.0.0.1:10004 &再用nvidia-smi查看会话数,正常情况下能看到超过 3 个编码会话。
这块有几个实操中容易踩的坑,我要重点提醒:
- 驱动一旦升级,补丁就会失效,需要重新执行 patch 脚本。所以如果你是通过 apt 定期升级驱动,升级后记得验证一下补丁状态。
- 不同驱动版本对应的补丁位置可能有差异,老的 patch 分支不一定兼容新驱动,先确认再打。
- 这个修改本质上是绕过了驱动层限制,如果你的使用场景涉及商业分发、云服务、直播平台,一定要事前评估合规风险,不要给项目埋雷。
我自己在实际业务中一般只在本地采集、离线转码这种内网场景使用,线上服务还是优先购买原生支持高并发编码的卡或者云厂商的转码服务,省得维护成本失控。
6. 多版本 CUDA 切换实战
6.1 为什么要装多个 CUDA
深度学习圈子比较常见的情况是:新项目用 PyTorch 2.x,需要 CUDA 11.8 或 12.1;老项目还埋在 CUDA 10.2 时代;做视频处理的一套工具链又要求 CUDA 11.3。这些项目不能互相迁就,所以在一台机器上共存多个 CUDA 版本就非常必要。
PyTorch 这类框架自带 CUDA 运行时,它的版本不太受系统 CUDA 影响。真正受影响的是你需要从源码编译的项目,比如 ORB-SLAM3、TensorRT、OpenCV with CUDA 等,编译时如果指定了错误版本的 CUDA,链接阶段会报一堆奇奇怪怪的错误。
6.2 简单粗暴的切换方式:符号链接 + 环境变量
最直观的思路是:让/usr/local/cuda这个软链接指向不同版本的 CUDA 目录,再配合环境变量,让当前 shell 使用正确版本的 nvcc 和运行时库。
比如想切换成 CUDA 11.8:
sudo rm -f /usr/local/cuda sudo ln -s /usr/local/cuda-11.8 /usr/local/cuda因为前面我们在/etc/profile.d/cuda.sh里写的是export PATH=/usr/local/cuda/bin:...,所以只要切换软链接,重新打开终端,nvcc -V就会显示新的版本。
但这种方式的缺点是全局的,所有终端和用户都会跟着切到同一版本,灵活性不够。
6.3 用 update-alternatives 做正式管理
我用的比较多的是把多个 CUDA 版本注册进 Debian 系自带的update-alternatives机制,这样切换只需要一条命令,而且终端会提示当前是哪个版本,不容易搞混。
先注册两个版本的 bin 目录、lib64 目录和 include 目录:
sudo update-alternatives --install /usr/local/cuda/bin/nvcc nvcc /usr/local/cuda-11.8/bin/nvcc 118 \ --slave /usr/local/cuda/lib64 libcudart_static /usr/local/cuda-11.8/lib64/libcudart_static.a sudo update-alternatives --install /usr/local/cuda/bin/nvcc nvcc /usr/local/cuda-12.1/bin/nvcc 121 \ --slave /usr/local/cuda/lib64 libcudart_static /usr/local/cuda-12.1/lib64/libcudart_static.a注册完成后,切换版本:
sudo update-alternatives --config nvcc系统会列出:
There are 2 choices for the alternative nvcc (providing /usr/local/cuda/bin/nvcc). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/local/cuda-12.1/bin/nvcc 121 auto mode 1 /usr/local/cuda-11.8/bin/nvcc 118 manual mode 2 /usr/local/cuda-12.1/bin/nvcc 121 manual mode输入对应数字回车,再执行nvcc -V确认就完成了。
这里还要提醒一个容易忽略的问题:LD_LIBRARY_PATH这个环境变量对运行时有影响,但对编译链接阶段影响不大。真正的软链接路径在/usr/local/cuda/lib64/libcudart.so上,所以如果程序在运行时提示找不到 libcudart.so.11,多半是链接指向的版本和你预期不一致。用下面的命令排查:
readlink -f /usr/local/cuda/lib64/libcudart.so确认它指向的是不是当前想要的那个版本。这是多版本切换之后很常见的坑,编译过了、运行时报错,往往就是这个软链接没有改对。
7. 常见问题与排查技巧实录
我把实际过程中遇到的典型问题整理成一个速查表,方便遇到问题时对着查:
| 现象 | 直接原因 | 处理方式 |
|---|---|---|
gzip: stdin: invalid compressed data | .run文件下载不完整或拷贝损坏 | 比对 md5 校验值,重新下载后放到 Linux 原生分区执行 |
nvidia-smi: command not found | 驱动没装,或者 PATH 没包含 nvidia-smi 路径 | 重新安装驱动,nvidia-smi一般在/usr/bin/nvidia-smi |
nvidia-smi显示错误或驱动加载失败 | Secure Boot 拦截了内核模块签名 | 进 BIOS 关闭 Secure Boot,或将驱动模块签名加入 MOK |
nvcc -V找不到命令 | CUDA Toolkit 未安装,或 PATH 没配置 | 安装 CUDA Toolkit,配置/etc/profile.d/cuda.sh |
nvidia-smi和nvcc -V版本不一致 | 一个是驱动能力上限,一个是 Toolkit 实际版本 | 只要驱动兼容 Toolkit,就没有问题 |
| CUDA samples 编译找不到头文件 | 没装完整 Toolkit,或路径指定错误 | 确认/usr/local/cuda/include存在,编译时用-I/usr/local/cuda/include显式指定 |
libcudnn.so.8: cannot open shared object file | CUDNN 软链接断裂,或库目录不在 LD_LIBRARY_PATH | ldconfig或手动修复软链接,确认lib64目录在LD_LIBRARY_PATH中 |
| 多版本切换后程序运行报 libcudart 错误 | 库软链接仍指向旧版本 | readlink -f /usr/local/cuda/lib64/libcudart.so检查,必要时重建软链接 |
| 虚拟机里 Ubuntu 20.04 无法联网 | VMware/VirtualBox 网络适配器未正确配置 | 检查虚拟网络模式,一般 NAT 模式最省事 |
除了这个表,再补充几个我自己的排查技巧。
第一个技巧是“分环境变量看”:如果同一台机器上不同终端里nvcc -V结果不一样,先看看是不是/etc/profile.d/里有多个脚本重复写入了 PATH,或者在~/.bashrc里加了自定义导出。查的时候用:
echo $PATH which nvcc看 nvcc 的绝对路径到底来自哪个目录,问题基本就定位了。
第二个技巧是“重新加载环境变量”:写完/etc/profile.d/cuda.sh后,如果不想重启系统,别只source ~/.bashrc,直接把脚本 source 一次,或者新开一个终端窗口也行,因为新终端会自动读取这个脚本。
第三个技巧是“卸载要干净”:想卸载 CUDA Toolkit 时,不要直接删/usr/local/cuda-11.8,因为这样会留下软链接和 update-alternatives 的注册记录。用官方卸载脚本最干净:
sudo /usr/local/cuda-11.8/bin/cuda-uninstaller至于驱动卸载,apt 方式安装的用sudo apt purge nvidia-*可以清干净,runfile 方式安装的用:
sudo /usr/bin/nvidia-uninstall两个混杂的话,建议先备份数据,再彻底清理后统一用一种方式重装。
第四个技巧是关于 ORB-SLAM3 这类项目的:很多人部署时源码编译一切都正常,但运行时就报No CUDA device available。这时先别急着怀疑 CUDA 环境,用nvidia-smi看看驱动是否正常,再用nvcc -V确认 Toolkit 是否在位,最后用刚才提到的 CUDNN 样例跑一遍。硬件、驱动、运行时、加速库四层都通了,再回头排查代码里的配置项,比如是否设置了-DCMAKE_CUDA_ARCHITECTURES=75(RTX 20 系是 75,30 系是 86,40 系是 89)。
最后一个技巧是关于磁盘空间的。CUDA、CUDNN 以及后续要装的框架动辄占用十几 GB,装之前用df -h确认根分区和/usr/local所在分区有足够空间。如果空间不够,后面的安装过程会出现各种诡异的中断报错,比如解压到一半提示 no space left on device,处理起来比初始安装麻烦得多。
我在实际使用中还有一个比较深的体会:驱动和 CUDA 环境的维护,本质上是在做“版本对齐”的事。每次升级驱动、升级 CUDA、升级项目依赖这三者之一,都应该主动去核对其余两者的兼容性,不要等到编译报错了再回来翻文档。你可以把当前机器的版本组合记在一个文本文件里,包括驱动版本、CUDA 版本、CUDNN 版本、PyTorch/TensorRT 版本,下次重装或者迁移时,照着文件配,能少走很多弯路。
如果你想试着再简化这套流程,可以后续考虑用 Docker 把 CUDA 环境容器化,宿主机只需要装好驱动,CUDA Toolkit 和 CUDNN 全部以 nvidia/cuda 镜像的方式拉取,这样多版本切换就会变得更干净,宿主机也不会被各种版本的库污染。不过这是另一个话题了,先把本地环境跑通,才是后面一切的基础。