☰
Ubuntu 22.04下Nvidia驱动、CUDA和cuDNN安装全指南:从版本匹配到黑屏自救
2026/9/29 9:40:05 网站建设 项目流程

这几天接二连三看到有人在群里问:Ubuntu 22.04下装Nvidia驱动,明明照着教程敲了命令,重启后直接黑屏,连图形界面都进不去。还有人驱动装好了,但Python里import torch之后torch.cuda.is_available()始终是False,查了半天也不知道问题出在哪。这类问题我从18.04时代一路用过来,几乎每个Ubuntu大版本都要看到一批人栽跟头。其实大部分问题不是命令敲错,而是没有把Nvidia驱动、CUDA Toolkit、cuDNN这三层东西的依赖关系理顺,装的时候各装各的,版本互相不匹配,环境自然就乱了。

这篇文章就把我在Ubuntu 22.04上从零安装Nvidia驱动、CUDA和cuDNN的完整思路写出来,包括版本怎么选、每一步为什么这么做、装完之后常见的翻车现场怎么救。不管你是刚接触Linux的小白,还是被版本问题折腾很久的老手,都能找到可以直接照着操作的方案。

1. 版本选型:先弄懂驱动、CUDA、cuDNN三者的依赖关系

很多教程上来就让你跑命令,安装顺序、版本对应关系全都语焉不详,这才是环境出问题的根源。

1.1 三层结构到底分别是什么

简单类比一下。Nvidia驱动是最底层的东西,相当于显卡的"操作系统",它直接和硬件打交道,让系统能识别并驱动这张GPU。CUDA Toolkit是中间层,可以理解成一套开发工具包,里面包含编译器(nvcc)、运行时库和调试工具,你写CUDA代码或者跑PyTorch、TensorFlow的时候,都是通过它去调用GPU算力。cuDNN是更上层的东西,它是Nvidia专门针对深度学习里的卷积、循环神经网络、池化等常见操作做过深度优化的加速库,性能比直接用CUDA原始API高很多。

三个层级依赖关系很明确:驱动决定你能不能识别显卡,CUDA Toolkit决定编译器能编译出什么目标代码,cuDNN决定深度学习框架跑起来能有多快。上层依赖下层,但下层不依赖上层。驱动版本决定它能支持的最高CUDA版本;CUDA Toolkit版本又决定它允许搭配哪个cuDNN版本。

1.2 版本匹配的关键判断方法

先看你要跑什么框架。以PyTorch为例,PyTorch官方对CUDA版本支持很明确,比如某些版本对应CUDA 11.8,另一些对应CUDA 12.1。确定框架要用的CUDA版本之后,再去找一个"支持这个CUDA版本"的Nvidia驱动即可。

驱动和CUDA之间的兼容关系可以从Nvidia官方给的CUDA Compatibility文档里查。简单记忆方式是:新驱动兼容旧CUDA,反过来不行。比如你装了CUDA 11.8,驱动选535或545这类新版本完全没问题;但如果你装了很老的驱动,比如470,想跑CUDA 12.1就不行。所以我的经验是:驱动宁新勿旧,CUDA版本跟着框架需求走。cuDNN则直接按CUDA版本来选,下载页上会明确标注它支持哪个CUDA版本,比如"cuDNN 8.9.7 for CUDA 12.x"这种命名,照着选就行。

1.3 动手之前先摸清自己的显卡和系统状态

别上来就装,先在终端跑几条命令确认现状。第一条:

lspci | grep -i nvidia

这条命令能看到你的Nvidia显卡型号,比如GA106 [GeForce RTX 3060 Lite Hash Rate],确认硬件型号后去Nvidia官网驱动下载页就能找到匹配的驱动。

再看一看你的系统有没有之前装过的驱动残留:

nvidia-smi

如果提示NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver,说明驱动还没装好。如果这条命令能正常显示GPU列表和驱动版本,说明驱动已经存在,下面装CUDA时可以跳过驱动部分。

还需要确认一下Ubuntu当前的内核版本:

uname -r

Ubuntu 22.04默认是5.15内核,如果你手动升级过内核到6.x,驱动安装对内核头文件版本要求会更严格,后面安装时要用对应版本的linux-headers,否则DKMS编译会失败。这个坑后面单独讲。

2. 驱动安装全流程:禁用nouveau、Secure Boot和三种安装方式

2.1 为什么必须先禁用nouveau

nouveau是Linux内核里自带的开源Nvidia驱动,本着"能用就不加载额外驱动"的设计思路,系统默认会先用它来驱动显卡。问题在于nouveau和Nvidia的闭源驱动会抢占同一个设备节点,两者共存会导致Nvidia驱动加载失败,表现出来就是安装时报错提示nouveau正在被使用,或者装完重启黑屏。

所以装闭源驱动的第一步,就是把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"

然后更新内核的initramfs,让修改在重启后生效:

sudo update-initramfs -u

重启之后验证:

lsmod | grep nouveau

如果没有任何输出,说明nouveau已经被禁掉了。如果还有输出,说明配置没生效,需要检查文件内容是否写对,再重新执行sudo update-initramfs -u。

2.2 Secure Boot和驱动签名问题

这一步非常容易忽略,而且后果最隐蔽。现在很多主板的UEFI默认开启Secure Boot,它只允许加载经过签名的内核模块。Nvidia官方run文件打包的驱动模块没有经过UEFI签名,加载的时候会被内核拒绝,表现就是安装过程看起来一切正常,但重启后nvidia-smi报错,查看内核日志全是Lockdown: insmod: module is not signed之类的信息。

处理方案有两种,我建议优先选简单的:

一是进BIOS关掉Secure Boot。具体路径每个主板不一样,常见的位置在Security或Boot标签页里。改完之后F10保存重启。

二是在Ubuntu下用mokutil进行模块签名。这个流程稍复杂,适合不方便改BIOS的场合,需要生成一对密钥、注册到MOK列表、安装驱动时用密钥给模块签名。普通用户直接用方案一就够了。

2.3 三种驱动安装方式的取舍

方式一:通过Ubuntu软件和更新界面的附加驱动(Additional Drivers)安装。这是最省事的方式,在软件源设置里切到"附加驱动"页签,系统会自动检测可用的闭源驱动版本,选中一个点击应用即可。这种方式的优点是集成度高,系统更新时会自动管理驱动,缺点是版本不一定是官网最新的。

方式二:apt命令行安装。本质上和方式一一样,只是换到命令行操作:

sudo apt update sudo apt install nvidia-driver-535

装之前建议先查系统推荐哪个:

ubuntu-drivers devices

它会显示你的GPU推荐的驱动版本。如果没特殊需求,装它推荐的版本就好。

方式三:Nvidia官网下载run文件手动安装。精确掌控版本,适合需要特定驱动版本场景,比如某些老项目只兼容特定驱动分支。但run文件安装方式有个硬性要求:安装过程中必须关闭图形界面,因为驱动会尝试替换正在使用的X server相关文件。

我的建议:如果你只是日常使用,直接选方式一或方式二,版本上不至于太激进也足够稳定。如果你需要精确控制驱动版本号,或者驱动和CUDA版本有较强的兼容性要求,用run文件,但要按下面的步骤走:

sudo service gdm stop sudo telinit 3

等待切换到纯文本终端,然后执行:

sudo sh NVIDIA-Linux-x86_64-535.154.05.run

安装过程按提示走,确认安装DKMS时选Yes,这样未来内核更新时驱动模块可以自动重新编译。装完后重启系统,登录前应该能看到Nvidia的Logo一闪而过。

2.4 驱动装好之后怎么确认

重启后第一件事就是验证驱动状态:

nvidia-smi

正常的输出会显示GPU型号、驱动版本、显存使用情况。比如Driver Version: 535.154.05,显卡信息下方有利用率和显存使用率,这说明驱动已经正常工作。

如果nvidia-smi命令不能运行,大概率是安装过程中nouveau没禁干净,或者Secure Boot的问题。回到2.1和2.2对应检查即可。

3. CUDA Toolkit安装:.run文件的正确打开姿势与多版本共存

驱动就绪之后,就可以安装CUDA Toolkit了。我见过太多人在这一步装错,最常见的问题是下载文件不完整导致安装时报gzip: stdin: invalid compressed>md5sum cuda_12.1.0_530.30.02_linux.run

把输出值和官网给的MD5值对比。很多人报错gzip: stdin: invalid compressed>sudo sh cuda_12.1.0_530.30.02_linux.run

第一次运行会进入一个文本交互界面,第一步是阅读协议,输入accept,之后进入组件选择。

这里有个非常关键的技巧:如果前面已经手动装好了Nvidia驱动,组件选择界面里一定要把Driver那一项取消勾选,只保留CUDA Toolkit以及符号链接(Symbolic link)两项。做法是在Driver选项上按空格键取消,然后移动光标到Install执行。

为什么要取消驱动?因为run文件里集成的驱动版本往往不是最新的,而且它检测到已有驱动时可能要求你先卸载,来回折腾容易把已经稳定的环境搞坏。既然驱动已经装好,就没必要再让CUDA安装器去动它。

安装完成后会默认把CUDA装到/usr/local/cuda-12.1目录下,同时创建/usr/local/cuda软链接指向它。

3.3 环境变量配置:为什么你的nvcc -V永远不可用

很多教程让你把环境变量写到~/.bashrc里,但你如果用的是zsh,就得写~/.zshrc。这是很多初学者忽略的细节。

打开对应的shell配置文件,在文件末尾添加:

export PATH=/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH

然后让配置生效:

source ~/.bashrc

验证是否配置成功:

nvcc -V

正常会输出Cuda compilation tools, release 12.1, V12.1.105之类的信息。如果提示command not found,优先检查是不是配置写错了shell文件,或者source的时机不对。

这里顺带提一个很多人困惑的知识点:nvidia-smi输出的右上角也有一个"CUDA Version"字样,但那表示你当前驱动支持的最高CUDA版本,并不代表系统已经装了对应版本的CUDA Toolkit。两者显示版本不一致是完全正常的,并不代表环境坏了。

3.4 通过软链接实现多版本CUDA共存

实际项目中不同框架对CUDA版本要求可能不同。比如老项目用CUDA 11.8,新项目要CUDA 12.1,两个版本共存是完全可行的。

安装第二个CUDA版本时,只安装Toolkit部分,同样会生成一个/usr/local/cuda-11.8目录。这时/usr/local/cuda软链接指向哪个,当前默认的CUDA版本就是哪个。

切换版本的办法:

sudo rm -f /usr/local/cuda sudo ln -s /usr/local/cuda-11.8 /usr/local/cuda hash -r

执行完之后重新nvcc -V,应该显示对应当前软链接的版本。这套方案的优美之处在于:环境变量始终指向/usr/local/cuda这个软链接,切换只改一个链接,编译时不依赖具体版本路径,非常干净。

4. cuDNN安装:tar包方案、拷贝权限与版本验证

cuDNN是很多教程里一笔带过的部分,但它在运行模型时的重要性一点不低。cuDNN选错了版本,PyTorch或TensorFlow可能直接报libcudnn.so.8: cannot open shared object file之类的错误。

4.1 为什么推荐tar包而不是deb包

去Nvidia cuDNN下载页,能看到提供的几种安装方式:deb安装包、tar包、以及pip安装。很多人习惯性选deb包,因为看起来"更适合Ubuntu",但我的经验是tar包方案更省心。

原因有三:其一,deb包对系统版本有严格要求,官方只发布特定几个Ubuntu版本的deb包,版本对不上依赖关系会很乱。其二,deb包在安装时会写一堆系统级配置,如果想换版本,卸载不干净是个大问题。其三,tar包本质就是压缩文件,解压之后手动拷贝到CUDA目录,完全不影响系统包管理,想切换cuDNN版本只需要重新拷贝对应文件。

下载时注意选择Local Installer for Linux x86_64 (Tar)格式,文件名类似cudnn-linux-x86_64-8.9.7.29_cuda12-archive.tar.xz,后面的cuda12表示这个cuDNN版本适配CUDA 12.x。

4.2 解压、拷贝、权限处理的完整步骤

解压tar包:

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

然后把头文件和库文件复制到CUDA安装目录下:

sudo cp include/cudnn*.h /usr/local/cuda/include/ sudo cp lib/libcudnn* /usr/local/cuda/lib64/

这里有一个特别容易踩的坑:如果不加sudo,会提示Permission denied,因为/usr/local/cuda目录默认是root所有。拷贝完成后需要调整权限,确保普通用户也能读取:

sudo chmod a+r /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn*

最后更新动态链接库缓存:

sudo ldconfig

4.3 三种验证cuDNN是否生效的方式

方式一,查看头文件里的版本宏定义:

cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR

输出类似:

#define CUDNN_MAJOR 8 #define CUDNN_MINOR 9 #define CUDNN_PATCHLEVEL 7

这里必须注意:新版cuDNN是cudnn_version.h,不是老教程里说的cudnn.h。很多老教程写cudnn.h导致新手在include目录里找不到文件,怀疑自己装错了。

方式二,用ldconfig确认动态库:

ldconfig -p | grep cudnn

应该能看到libcudnn.so.8、libcudnn_ops.so.8等一堆输出。

方式三,运行一个真实的深度学习测试,这是最终验证。在Python里跑:

import torch print(torch.backends.cudnn.version()) print(torch.cuda.is_available())

如果torch.backends.cudnn.version()能返回数字,说明你的PyTorch已经成功识别cuDNN。

5. 装完之后的经典翻车现场与排查路径

前面流程都能顺利走完,环境就算建好了。但这套环境在你手里用久了,迟早会遇到下面几个问题,我在多种机器上分别踩过,每次排查至少花掉半天。

5.1 nvidia-smi显示的CUDA版本和nvcc -V不一致,不是故障

这个问题出现的频率高到让人怀疑人生。网上不少人发帖问"为什么nvidia-smi显示CUDA 12.2,但nvcc -V显示11.8,系统是不是出问题了",底下回复也是五花八门。

其实前面在3.3已经提到:nvidia-smi显示的是驱动支持的最高CUDA版本上限,也就是驱动能力边界;nvcc -V显示的是当前默认CUDA Toolkit的版本,是你实际拿来编译的工具。一个说"我能支持到12.2",一个说"我现在用的是11.8",完全没有矛盾。

只有当你的框架需要某个CUDA版本,而当前驱动支持不到那个版本时,才是真正需要升级驱动的时机。

5.2 内核升级后驱动失效,怎么办

Ubuntu系统每次升级内核,都会触发DKMS重新编译Nvidia驱动模块。如果你用的是run文件手动安装,而安装时没有安装DKMS,那么内核一更新,驱动就"丢了",nvidia-smi报couldn't communicate with the NVIDIA driver是必然结果。

解决办法分两步:第一步检查当前内核和头文件是否匹配:

sudo apt install linux-headers-$(uname -r)

第二步重新执行run文件安装一次,记得在安装选项里选DKMS模块注册:

sudo sh NVIDIA-Linux-x86_64-535.154.05.run -s --dkms

如果嫌麻烦,以后驱动更新直接用apt装的nvidia-driver-*包,它天然集成DKMS管理,升级内核时基本不用手动干预。

5.3 重启后黑屏的自救方法

这是安装过程中最绝望的场景,也是很多人直接重装系统的原因。黑屏一般分两种情况:一种是nouveau没禁干净,驱动加载时和开源驱动冲突,直接崩溃;另一种是Secure Boot拦截了驱动模块加载。

自救办法:重启后按Ctrl+Alt+F2(也可能是F3到F6,多试几个)进入纯文本终端,用你的账号密码登录。如果黑屏连字符都看不到,可以尝试在GRUB菜单里按e编辑启动项,在linux那一行末尾加上nomodeset参数,按F10启动,这个参数让系统用基础显示模式启动,绕过图形驱动,一般能救回来。

进入文本终端之后,先卸载现有驱动:

sudo apt purge nvidia-* -y

然后检查nouveau是否被正确禁用(参考2.1),再决定是否重装。重新装驱动之前,先把BIOS里的Secure Boot关掉,这一条能解决大量重启后的奇怪问题。

5.4 torch.cuda.is_available()返回False的排查顺序

明明驱动、CUDA、cuDNN都装好了,但PyTorch就是检测不到GPU,这也是高频问题。按照下面顺序排查,多数情况能解决:

第一步,确认PyTorch本身的CUDA版本支持。检查安装的PyTorch是不是CPU版:

python -c "import torch; print(torch.version.cuda)"

如果输出None,说明你装的是CPU版,用GPU版命令重装:

pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121

第二步,检查驱动是否正常:

nvidia-smi

如果驱动挂了,PyTorch自然检测不到GPU。

第三步,检查conda环境里是否同时装了cudatoolkit。如果你用conda管理环境,conda list里如果同时有pytorch和cudatoolkit,可能出现版本冲突。官方推荐的conda方式虽然会自动带一个cudatoolkit,但它和系统级的CUDA是两套东西,混合使用时容易互相干扰。我的建议是:conda环境里尽量用pip安装PyTorch对应的GPU版本,系统级CUDA只负责编译和运行C扩展,两边分工明确,少很多麻烦。

6. 我的长期习惯:从新系统到能跑模型的稳定路线

装环境这么多年,经历过各种稀奇古怪的问题之后,我形成了自己的一套固定流程,照着走基本不会出乱子。

第一步,先禁nouveau,关Secure Boot,然后装驱动,验证nvidia-smi能正常识别GPU。第二步,再用run文件装CUDA Toolkit,取消Driver选项,只装Toolkit和符号链接,配置好环境变量,nvcc -V能跑通。第三步,用tar包方式装cuDNN,验证头文件和动态库文件存在,再用PyTorch跑一次确认深度学习框架层面能看到GPU。

这套流程的核心思路是"层层剥离,互不干扰":驱动只管硬件,CUDA只管编译运行,cuDNN只管库文件。系统级环境和conda环境分开管理,比把一堆东西都塞进同一个环境里要稳定得多。

还有一个容易被忽略的小习惯:每次安装完大组件,我会写一个环境说明文件放在家目录下,记录驱动版本、CUDA版本、cuDNN版本、安装日期、用的什么安装方式。别看这个操作简单,几个月后系统出问题需要回溯环境状态时,这份记录能帮你精准定位问题,比对着终端历史记录一行行翻高效太多。

最后再分享一个实用的小技巧:如果遇到不确定的版本兼容问题,先别急着反复卸驱动,去Nvidia官方文档的兼容性对照表里查清楚,一次选对版本,比试错十次都省时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询