显卡驱动、CUDA、cuDNN 这三个词,基本是每个刚上手深度学习的人都要被绊一跤的地方。我自己第一次装的时候,折腾了整整两天:先是 ubuntu 装完显卡驱动黑屏进不去图形界面,接着是 CUDA 下到一半报gzip: stdin: invalid compressed>+-----------------------------------------------------------------------------+ | NVIDIA-SMI 535.183.01 Driver Version: 535.183.01 CUDA Version: 12.2 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 NVIDIA GeForce ... Off | 00000000:01:00.0 On | N/A | +-----------------------------------------------------------------------------+
这里的CUDA Version: 12.2不是你机器上装好的 CUDA 版本,而是"这个驱动最高能支持到哪个 CUDA Runtime 版本"。它是驱动的一个能力上限声明,跟/usr/local/下面躺了哪些文件夹半毛钱关系都没有。
真正代表"我装了哪个 CUDA"的命令是nvcc -V,或者看/usr/local/cuda这个软链接指向哪个目录。所以完全可能出现这种组合:nvidia-smi显示 12.2,nvcc -V显示 11.8,而 PyTorch 打印torch.version.cuda是 12.1。三个数字全不一样,但环境是健康的。第一次看到会很慌,理解了上面的规则就踏实了。
1.4 版本选型的正确顺序:从框架倒推
绝大多数人安装失败,是因为安装顺序是"先装驱动,再装最新 CUDA,最后随便挑个 cuDNN",这是从下往上装,一旦框架不支持就得推倒重来。正确做法是从上往下倒推,四步:
- 先确定你要用的框架和版本。比如你要跑某个开源项目,它
requirements.txt里写了torch==2.4.0,那 CUDA 就被框定在 12.1/12.4 这个区间。 - 根据框架官方给的对应表,确定 CUDA 版本。PyTorch 官网的安装页会直接告诉你
cu118、cu121、cu124、cu126、cu128这些轮子分别对应哪个 CUDA Runtime。 - 根据 CUDA 版本反查所需的最低驱动版本,NVIDIA 官方的 CUDA Release Notes 里有一张对应表,也可以在目标机器上直接看
nvidia-smi的上限够不够。 - cuDNN 跟着 CUDA 走,大版本对齐即可,小版本挑最新的稳定版。
这个顺序颠倒过来,就是无穷无尽的返工。我见过最惨的一个同学,为了用最新的 CUDA 13,把驱动升到了最新,结果他那张 Maxell 架构的老卡直接不在支持列表里,机器当场罢工。
2. 显卡驱动:一切的底座
2.1 装之前先摸清硬件和系统底细
动手之前先收集信息,这一步花三分钟,能省掉后面三小时。Ubuntu 下常用这几条:
lspci | grep -i -E "vga|3d|nvidia" lsb_release -a uname -r ubuntu-drivers devices dpkg -l | grep -i nvidia第一条告诉你机器上有几块显示设备、都是什么型号。这里有个坑:很多带独显的笔记本或者台式机同时有 Intel 核显和 NVIDIA 独显,输出里会同时出现Intel Corporation HD Graphics 630和NVIDIA Corporation ...两条。这不代表你要给核显装 NVIDIA 驱动,也不代表必须禁用核显——两者可以共存,只是显示输出走谁的问题,后面会讲。
第二条看系统版本,20.04、22.04、24.04 的包名和内核行为差别不小。第三条看内核版本,因为 NVIDIA 驱动是内核模块,装了之后每次内核升级都要重新编译模块,心里要有数。第四条是最省事的,它会直接推荐一个适合你当前硬件和系统版本的驱动版本号。
还要特别留意一件事:如果机器是品牌工作站或者服务器(比如某些国产工作站机型),原厂驱动包里的显卡型号信息经常滞后,甚至给的还是几年前的旧版本。这种情况别偷懒用原厂包,直接lspci看清显卡真实型号,去 NVIDIA 官方找对应驱动。
2.2 Ubuntu 上装驱动的三条路线,怎么选
Ubuntu 装 NVIDIA 驱动主要有三条路,各有适用场景:
| 安装方式 | 命令 / 入口 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 附加驱动(图形界面) | 软件和更新 → 附加驱动 | 图形化、零学习成本 | 可选版本少、依赖网络 | 桌面用户首次安装 |
| apt 包管理 | apt install nvidia-driver-535 | 自动处理内核模块、自动禁用 nouveau、可卸载 | 版本受仓库限制 | 绝大多数场景推荐 |
| 官方 runfile | .run可执行文件 | 版本最全、可离线 | 需手动禁 nouveau、升级内核易失效 | 无网络、特殊版本需求 |
我的建议很直接:能联网就用 apt,不能联网才用 runfile。apt 方式会自动把 nouveau 加进黑名单、自动配置 DKMS(Dynamic Kernel Module Support),内核升级后自动重编译模块,省掉一大半麻烦。runfile 方式虽然灵活,但每次系统内核更新之后,nvidia-smi就可能报Failed to initialize NVML: Driver/library version mismatch,得手动重装一遍,长期维护成本高。
至于"附加驱动"那个图形界面,适合完全不想碰命令行的桌面用户,可选的版本就是 Ubuntu 仓库里那几个,对应 CUDA 上限往往偏低,做深度学习通常不够用。
2.3 apt 方式完整实操(以 Ubuntu 22.04 + 535 为例)
先装编译环境,这是必须的,NVIDIA 内核模块需要现场编译:
sudo apt update sudo apt install -y build-essential linux-headers-$(uname -r) sudo apt install -y nvidia-driver-535 sudo reboot重启之后执行nvidia-smi,如果能看到显卡型号、显存、温度、驱动版本,就成了。整个过程不需要手动去改blacklist-nouveau.conf,因为nvidia-driver-535这个包在安装时会自动把 nouveau 拉黑并执行update-initramfs。
这里有几个必须知道的细节。第一,linux-headers-$(uname -r)一定要跟当前运行的内核版本严格对应,如果你之前升级过内核但没重启,装上的 headers 可能是新内核的,而当前跑的是旧内核,编译就会失败。第二,笔记本用户如果发现装完驱动之后nvidia-smi正常但图形界面用的是核显,那是 Optimus 混合输出机制,可以用prime-select query查看当前模式,prime-select nvidia切换成独显直连(功耗变高,续航变短),prime-select on-demand让程序按需调用。第三,如果你的主板开了 Secure Boot,安装过程中会弹出一个蓝底界面要求你设置 MOK 密码,设一个简单的记下来,重启后还要在同一个界面里输入一遍完成签名,否则驱动模块加载会被安全启动拦下来。
2.4 离线场景与 runfile 安装的关键参数
无网络的机器(比如内网服务器、离线工作站)只能走 runfile。流程大概是:在能联网的机器上下载对应版本的.run文件,拷到目标机,先禁 nouveau,再切到文本模式安装。
sudo bash -c 'echo -e "blacklist nouveau\noptions nouveau modeset=0" > /etc/modprobe.d/blacklist-nouveau.conf' sudo update-initramfs -u sudo reboot # 重启后 Ctrl+Alt+F3 切到 tty,登录 sudo systemctl stop gdm3 # 或 lightdm / sddm,看你用什么显示管理器 sudo sh NVIDIA-Linux-x86_64-535.183.01.run \ --no-opengl-files \ --no-x-check \ --dkms \ --silent sudo reboot参数含义值得单独说一下。--no-opengl-files是不覆盖系统自带的 OpenGL 库,笔记本双显卡环境加上它,能避免装完进不去桌面。--no-x-check跳过 X 服务检查,因为你已经把显示管理器停了,不加这个参数它可能误判。--dkms让驱动注册进 DKMS,内核升级后自动重建模块,强烈建议加上。--silent是静默安装,批量部署时用。
如果装完黑屏进不去图形界面,别慌,Ctrl+Alt+F3进 tty,先看dmesg | grep -i nvidia和cat /var/log/nvidia-installer.log,八成是 OpenGL 库冲突或者 Secure Boot 没签名。
2.5 Windows 平台的清理与安装
Windows 上装驱动本身很简单,去 NVIDIA 官网按显卡型号下载安装包一路下一步即可。麻烦在于换卡或者降版本的时候,旧驱动的残留会让新驱动装不上或者装上了也不正常。
这时候需要 DDU(Display Driver Uninstaller)。正确姿势是:先把 DDU 下载好放在桌面,然后进安全模式(按住 Shift 点重启 → 疑难解答 → 高级选项 → 启动设置 → 重启 → 按 4),在安全模式下运行 DDU,选择"清除并重启",重启后再装新驱动。直接在正常模式下用 DDU 清理也行,但偶尔会有残留文件删不掉。
还有一个 Windows 用户经常忽略的点:如果用 WSL2 跑 GPU 任务,Windows 侧只需要装普通显卡驱动,WSL 内部不要再装一遍 Linux 版驱动。WSL 用的是 Windows 驱动透传进来的libcuda.so,你在 WSL 里装一遍反而会把透传的库覆盖掉,nvidia-smi直接挂掉。
2.6 不同显卡架构该选哪个驱动分支
这是一个必须看表的问题,选错了就是白装。下面这张表是基于公开支持信息整理的常见情况,实际以 NVIDIA 官方驱动页的"支持产品列表"为准:
| 显卡示例 | 架构 | 常见驱动分支 | CUDA 上限(参考) | 说明 |
|---|---|---|---|---|
| GTX 750 / 750Ti | Maxwell | 470.x 长期分支 | 11.4 左右 | 算力 5.0,别追新,锁旧组合最稳 |
| Quadro P600 | Pascal | 5xx 系列(视架构支持情况) | 12.x(视驱动) | 老专业卡,建议锁 CUDA 11.8 |
| RTX 4060Ti | Ada Lovelace | 535 / 550 / 570+ | 12.2 ~ 12.8 | 主流选择,新驱动随便上 |
| RTX 50 系列 | Blackwell | 570 及以上 | 12.8 及以上 | 老驱动完全不认这张卡 |
| Intel HD 630 | 核显 | Intel 图形栈 | 不适用 | 只负责显示输出,不参与 CUDA |
关于 750Ti 我要多说一句:这张卡算力是 5.0,能跑的 CUDA 版本有天花板,很多人拿着 750Ti 想装 CUDA 12,结果卡在驱动支持列表外面。老老实实用 CUDA 11.8 配 470 或 535 分支的驱动,PyTorch 用cu118的轮子,能跑得挺稳。同样,P600 也是这个思路,它是给专业图形和轻量推理用的,别指望它跑大模型训练。
至于 Intel HD 630 这种核显,它的驱动是 Intel 图形栈自己管的,跟 NVIDIA 那套完全并行。它存在的意义是省电和显示输出,你不需要为它做任何 CUDA 相关的操作。笔记本上如果出现"装了 NVIDIA 驱动之后桌面变卡",通常是显示输出还挂在核显上,或者 PRIME 模式没切对。
3. CUDA Toolkit 安装:从下载到验证
3.1 版本怎么定:再次强调倒推
再重复一次核心逻辑:先定框架版本,再定 CUDA 版本。举个具体例子,你手上有个项目要torch==2.4.0,那基本上就在 CUDA 12.1 / 12.4 里挑;要torch==2.1.x,那 CUDA 11.8 和 12.1 都能选;如果是llama-cpp-python这类带 CUDA 的 whl 包,就得看清楚包名里的编译选项和它依赖的运行时版本,cu12的轮子需要一个能跑 12.x 的驱动环境。
热词里提到"cuda version: 13.0 需要安装 pytorch 的版本",这里要提醒一句:CUDA 主版本刚更新的时候,官方轮子往往还没跟上,别急着升。查框架支持的 CUDA 列表,永远以框架官网安装页给的命令为准,那是唯一可靠来源。
3.2 apt 仓库安装:联网环境首选
NVIDIA 官方为常见发行版维护了 apt 仓库,装起来干净、可升级、可卸载。以 Ubuntu 22.04 装 12.4 为例:
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb sudo dpkg -i cuda-keyring_1.1-1_all.deb sudo apt update sudo apt install -y cuda-toolkit-12-4请注意包名的选择,这是个大坑:
cuda:元包,会把完整工具链加上驱动一起装,还可能顺手升级你现有的驱动,在已经装好驱动的机器上容易出乱子。cuda-toolkit-12-4:只装工具链,不动驱动,已经装好驱动的情况下选这个。cuda-runtime-12-4:只装运行时库,不带编译器,给纯部署环境用。
装完之后到/usr/local/cuda-12.4看一眼,目录结构对就成功了一半。想装多个版本就重复上面的步骤,把版本号换掉即可,各版本会各自躺在一个目录里互不干扰。
3.3 runfile 安装与那个经典的 gzip 报错
离线或者需要精确控制组件的时候用 runfile:
wget https://developer.download.nvidia.com/compute/cuda/12.4.0/local_installers/cuda_12.4.0_550.54.14_linux.run sudo sh cuda_12.4.0_550.54.14_linux.run --toolkit --silent --override--toolkit表示只装工具链不装驱动,--silent静默,--override忽略编译器版本检查。这个检查经常误伤——你的 GCC 版本比 CUDA 支持列表里的新一点,它就拒绝安装,--override直接跳过。不过要意识到风险:跳过检查后,如果 GCC 版本确实太新,编译某些示例代码可能真的报错。
然后说说热词里反复出现的那个报错:
gzip: stdin: invalid compressed>export CUDA_HOME=/usr/local/cuda export PATH=$CUDA_HOME/bin:$PATH export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATHPATH是为了让 shell 找到nvcc、nvprof这些可执行文件。LD_LIBRARY_PATH是为了让动态链接器找到libcudart.so、libcudnn.so这些共享库。CUDA_HOME是给某些构建脚本(比如 OpenCV 编译、llama.cpp 编译)用的,它们会读这个变量去找 CUDA 头文件。
关于LD_LIBRARY_PATH我有个经验之谈:不要无脑往里面塞一长串路径。有些朋友为了多版本共存,把七八个目录都塞进这个变量,结果编译别的软件时链接器从错误的目录抓到了不兼容的库版本,报一堆莫名其妙的symbol lookup error。更好的做法是在需要的时候临时设置,比如写个source setcuda.sh 11.8的小脚本,用完就退出终端。
3.5 多版本共存与切换的三种做法
实际工作中经常需要在 CUDA 11.8 和 12.4 之间来回切,比如一个老模型要 11.8,一个新库要 12.4。三种方案:
方案一:软链接切换。/usr/local/cuda本身是个指向具体版本的符号链接,切换就是重指一下:
sudo rm -f /usr/local/cuda sudo ln -s /usr/local/cuda-11.8 /usr/local/cuda简单粗暴,全局生效,缺点是同一时刻只能有一个版本。
方案二:update-alternatives。系统级的多版本管理工具,能统一管理nvcc和cuda这两个入口,切换有记录,适合长期维护的机器。
sudo update-alternatives --install /usr/local/cuda cuda /usr/local/cuda-11.8 100 sudo update-alternatives --install /usr/local/cuda cuda /usr/local/cuda-12.4 200 sudo update-alternatives --config cuda方案三:环境变量临时覆盖。不改系统状态,每个终端独立:
export PATH=/usr/local/cuda-11.8/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda-11.8/lib64:$LD_LIBRARY_PATH export CUDA_HOME=/usr/local/cuda-11.8我平时最常用第三种,因为容器化部署和多人共用机器的情况下,改全局状态容易影响到别人。写个use_cuda.sh脚本,前面说过,几行就够。
3.6 装完必须验证,别跳
验证分三步,缺一不可:
nvcc -V # 应该输出 Cuda compilation tools, release 12.4, V12.4.xx ls -l /usr/local/cuda # 确认软链接指向你想要的版本 cat /usr/local/cuda/version.json # CUDA 12 之后有 version.json,比 nvcc 更权威再跑一次实机验证,这步最关键,因为它证明驱动和 CUDA 真的能协同工作。CUDA 12 之后 runfile 不再自带 samples,需要单独拉:
git clone https://github.com/NVIDIA/cuda-samples.git cd cuda-samples mkdir build && cd build cmake .. -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc make -j$(nproc) ./Samples/1_Utilities/deviceQuery/deviceQuerydeviceQuery输出的最后一行如果是Result = PASS,说明驱动、CUDA、硬件三方都通了。如果 apt 安装的方式,示例程序可能在/usr/local/cuda/extras/demo_suite/下,直接跑deviceQuery和bandwidthTest也行。热词里提到的"cuda samples 找不到",多半是找错路径了,现在官方推荐自己 clone 下来编译。
4. cuDNN:装法、验证与框架对接
4.1 先搞清楚 cuDNN 跟 CUDA 的对应关系
cuDNN 是跟着 CUDA 大版本走的,它不像 CUDA 那样有明确的次版本兼容规则,大版本必须对齐。给 CUDA 11.x 用的 cuDNN 9 和给 CUDA 12.x 用的 cuDNN 9,是两份不同的包,下载页面上会明确标出for CUDA 11.x和for CUDA 12.x。
版本命名上,cuDNN 8 时代的包名是libcudnn8,cuDNN 9 时代变成libcudnn9-cuda-12这种带 CUDA 主版本后缀的形式,比以前清晰很多。下载需要在 NVIDIA 开发者站点注册账号,虽然不需要付费,但首次操作会绕一点。
4.2 tar 包手动布局:经典但不好卸载
这是流传最广的一种做法,把库文件直接拷进 CUDA 目录:
tar -xvf cudnn-linux-x86_64-8.9.7.29_cuda12-archive.tar.xz cd cudnn-linux-x86_64-8.9.7.29_cuda12-archive sudo cp include/cudnn*.h /usr/local/cuda/include/ sudo cp lib/libcudnn* /usr/local/cuda/lib64/ sudo chmod a+r /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn*它的优点是简单直接,不挑系统版本,一份 tar 包哪个发行版都能用。缺点也很明显:没有包管理记录,想升级或者卸载的时候,你得自己记住拷了哪些文件进去,一个个删。时间长了谁还记得,最后只能整个 CUDA 目录重装。
另外要注意,如果你装了两个版本的 CUDA,这样拷贝只会拷到你指定的那个目录(前提是你得把路径写对,别想当然写成/usr/local/cuda结果实际在 11.8 的目录里),多版本环境下手动管理很容易搞混。
4.3 deb 包安装:我更推荐的方案
现在官方主推 deb 方式,干净、可查、可卸载:
sudo dpkg -i cudnn-local-repo-ubuntu2204-9.x.x.x_1.0-1_amd64.deb sudo cp /var/cudnn-local-repo-ubuntu2204-9.x.x.x/cudnn-*-keyring.gpg /usr/share/keyrings/ sudo apt update sudo apt install -y libcudnn9-cuda-12装完之后apt list --installed | grep cudnn能看到完整的包记录,卸载直接apt remove就行。deb 方式还有个好处,它会自动把库文件放到系统标准库路径里(/usr/lib/x86_64-linux-gnu/),不用再依赖LD_LIBRARY_PATH去找。对你没看错,这就是为什么有些人没配LD_LIBRARY_PATH也能跑起来——他们装的是 deb 版。
如果同时还想装开发用的一些附加组件(比如 samples、静态库),可以再装libcudnn9-samples之类。
4.4 验证 cuDNN 版本的两个办法
验证 cuDNN 是否装好、装的是哪个版本,有两种途径:
# 方法一:看头文件(tar 方式装的库在这找) cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2 # 方法二:看包管理记录(deb 方式装的库用这个) dpkg -l | grep cudnn方法一输出的是CUDNN_MAJOR、CUDNN_MINOR、CUDNN_PATCHLEVEL三个宏,拼起来就是版本号。方法二出来的是包名和版本,更直观。注意 cuDNN 9 之后头文件路径可能有调整,有些发行版放在/usr/include/下面,找不到就往系统 include 目录看一眼。
4.5 一个重要认知:pip 装的 PyTorch 自带 CUDA 和 cuDNN
这是很多人绕不出来的弯。你用pip install torch或者conda install pytorch-cuda=11.8装下来的 PyTorch,包里已经打包了一份 CUDA Runtime 和 cuDNN,它们装在 conda 环境或者 site-packages 里面,运行时优先加载自己那份,不看你系统装的 CUDA。
这就解释了两个看似矛盾的现象:
第一个现象:一台干干净净的机器,没装系统 CUDA,nvcc -V报 command not found,但torch.cuda.is_available()返回 True,模型跑得飞快。因为驱动装了,PyTorch 自带运行时能通过驱动调到 GPU。
第二个现象:你认认真真装了 CUDA 12.4 和 cuDNN 9,结果torch.cuda.is_available()还是 False。原因是装的是+cpu版本的 Pyramid,或者装的是配 CUDA 11.8 的轮子但系统驱动太老。
所以调试时先打印这几个值:
import torch print(torch.__version__) print(torch.version.cuda) print(torch.backends.cudnn.version()) print(torch.cuda.is_available())torch.version.cuda是 PyTorch 编译时用的 CUDA 版本,torch.backends.cudnn.version()是它打包的 cuDNN 版本。这两个数字跟系统里装的 CUDA/cuDNN 可以完全无关,这是正常的,不要试图把它们对齐。
那什么时候真的需要系统 CUDA?两种场景:一是要从源码编译带 CUDA 支持的扩展,比如编译 OpenCV 的 CUDA 版本、编译llama.cpp、编译自定义算子,这时候必须要有完整的 CUDA Toolkit(带 nvcc);二是用 TensorRT、DeepStream 这类 NVIDIA 原生 SDK,它们会明确要求系统 CUDA 版本。
5. 版本匹配矩阵与排错实录
5.1 常见版本组合速查
下面这张表是我在不同机器上验证过、或者被问得最多的组合,可以作为起点,但最终以官方对应表为准:
| 硬件/场景 | 推荐驱动 | 推荐 CUDA | 推荐 cuDNN | 框架轮子 |
|---|---|---|---|---|
| RTX 30/40 系 + 新项目 | 550 及以上 | 12.4 / 12.6 | 9.x for CUDA 12 | cu124 / cu126 |
| RTX 50 系 | 570 及以上 | 12.8 及以上 | 9.x for CUDA 12 | cu128 |
| 老卡(750Ti / P600) | 470 / 535 分支 | 11.8 | 8.9.x for CUDA 11 | cu118 |
| 单位内网服务器 | 视显卡型号 | 11.8(兼容性最好) | 8.9.x | cu118 |
| WSL2 | Windows 侧驱动 | 12.x | 跟随框架 | cu12x |
为什么内网服务器我总推荐 11.8?因为它是 CUDA 11 系列的最后一个大版本,兼容性覆盖了绝大多数还在维护的框架版本,而且对老架构显卡友好。新卡新项目当然可以上 12.x,但如果是多人共用、要求稳定的环境,11.8 的坑最少。
5.2 排错速查表
这张表建议直接收藏,九成的报错都在里面:
| 报错 / 现象 | 大概率原因 | 处理办法 |
|---|---|---|
nvidia-smi: command not found | 驱动没装,或 PATH 里没有 | apt install nvidia-driver-xxx后重启 |
Failed to initialize NVML | 内核升级后模块没重建 | 重装驱动,或用 DKMS 版 |
Driver/library version mismatch | 驱动版本和已加载模块不一致 | 重启;不行就重装驱动 |
torch.cuda.is_available()= False | 装了 CPU 版轮子或驱动太老 | 重装对应 cu 版本的 torch |
libcudnn.so.8: cannot open shared object file | 库路径没配,或 cuDNN 没装 | 配 LD_LIBRARY_PATH 或装 deb 版 |
undefined symbol: cudnnXxx | cuDNN 与 CUDA 大版本不匹配 | 换成对应 for CUDA xx 的包 |
gzip: stdin: invalid compressed data | 安装包下载不完整 | 校验 sha256 后重新下载 |
no supported version of visual studio was found | Windows 装 CUDA 时 VS 版本太新 | 安装时取消 VS 集成勾选,跳过 |
| 装了驱动后进不去桌面 | OpenGL 库冲突 / Secure Boot 未签名 | tty 登录排查,重装加--no-opengl-files |
WSL 里nvidia-smi挂掉 | 在 WSL 内装了 Linux 驱动 | 卸载 WSL 内的驱动,用 Windows 侧透传 |
| 编译 OpenCV 报 CUDA 相关错误 | CUDA_ARCH_BIN 没设对 | 按显卡算力设-DCUDA_ARCH_BIN=8.9 |
cuda by example代码编译失败 | 示例来自 CUDA 5 时代 | 加-arch=sm_xx并改老语法 |
关于cuda by example这类老书里的示例,我得说一句:书本身讲原理很好,但配套代码是基于十几年前的 CUDA 版本写的,里面有大量现在已废弃的语法(比如cutil.h这种早就没有的头文件)。想跑的话得自己大改,不如直接看官方 cuda-samples 里的现代写法。学习原理和跑通代码是两件事。
5.3 几个只有踩过才知道的细节
第一个是内核升级导致的驱动失效。Ubuntu 隔一段时间就推内核更新,重启之后nvidia-smi突然报Failed to initialize NVML。原因就是新内核下没有对应的驱动模块。DKMS 版本的驱动会自动重编译,非 DKMS 的就得手动处理。判断方法:dkms status看有没有 nvidia 条目。所以我在 2.4 节强调 runfile 安装一定要加--dkms。
第二个是 conda 环境之间的 CUDA 版本污染。同一个用户下有多个 conda 环境,每个环境里装的 PyTorch 可能对应不同 CUDA 版本,而系统级的LD_LIBRARY_PATH是共享的。如果你把某个环境自带的库路径写进了全局变量,另一个环境就可能加载到错误的库。解决办法就是不要把 conda 环境里的 lib 目录写进.bashrc,让 conda activate 自己去管。
第三个是 4060Ti 这类新卡在旧驱动上的表现。热词里有"4060ti 支持的 cuda 版本",答案是只要驱动够新(535 以上),CUDA 12.x 全系列都能用。但如果你从旧机器上直接把硬盘搬过来,里面的驱动还是 470,卡根本认不出来,lspci能看到设备但nvidia-smi报错。这时候别怀疑硬件,先升驱动。
第四个是离线安装。内网机器上,apt 仓库那套走不通,得提前在联网机器上把.run文件、cuDNN 的 tar 或 deb、以及一堆依赖(build-essential、dkms、linux-headers)全部下好打包。这里有个技巧:apt-get install --download-only -o Dir::Cache::archives=/tmp/debs可以把包连同依赖一起下到本地目录,拷过去用dpkg -i *.deb批量装,比一个个找依赖省事得多。
第五个是 OpenCV 带 CUDA 编译。这事本身不难,但有几个参数必须设对:-DWITH_CUDA=ON、-DOPENCV_DNN_CUDA=ON(要用 DNN 模块的 CUDA 加速就必须开)、-DCUDA_ARCH_BIN填你自己显卡的算力(4060Ti 是 8.9,3090 是 8.6,750Ti 是 5.0),-DCUDA_FAST_MATH=ON可以提速。编译时间很长,四核机器上可能要一两个小时,用make -j$(nproc)并行编译能快不少。另外注意 OpenCV 每个大版本对 CUDA 版本的要求不同,别拿 4.10 去配一个过老的 CUDA。
最后再提一个日常维护的小习惯:装完环境之后,把这几条命令的输出记录到一个文本文件里,随手存着。
nvidia-smi > ~/env-backup.txt nvcc -V >> ~/env-backup.txt python -c "import torch; print(torch.__version__, torch.version.cuda, torch.backends.cudnn.version())" >> ~/env-backup.txt dpkg -l | grep -E "cuda|cudnn|nvidia-driver" >> ~/env-backup.txt下次环境出问题、或者要给同事复现你的环境时,这份记录就是最快的排查起点。我自己维护过的一台多卡训练机,前后换过四五次 CUDA 版本,靠的就是这些记录,出问题五分钟就能定位到是哪次改动引入的。