Ubuntu 20.04 NVIDIA驱动、CUDA、CUDNN安装与NVENC并发限制突破实战

发布时间:2026/9/29 9:35:27
Ubuntu 20.04 NVIDIA驱动、CUDA、CUDNN安装与NVENC并发限制突破实战
Ubuntu 20.04上搞定NVIDIA显卡驱动、CUDA、CUDNN、NVENC并发限制突破和多版本CUDA切换这五件事看着简单实际踩坑的人一抓一大把。我从深度学习环境编译到视频编码服务部署前前后后在20.04上折腾了不知道多少台机器这里把整个流程和踩过的坑一次性说清楚。无论是刚入门准备装环境跑PyTorch还是老手想解锁NVENC并发限制这篇文章都可以直接拿来参考。1. 环境摸底与准备工作1.1 先弄清楚自己显卡的型号和架构不要上来就敲安装命令先花两分钟把机器摸清楚。显卡型号直接决定驱动版本选型而驱动版本又决定CUDA版本上限这条链子任何一个环节断掉后面全都白搭。查看显卡型号和PCI设备信息用这条命令lspci | grep -i nvidia如果输出为空先别急着排查软件问题去BIOS里看是不是把独立显卡禁用掉了或者显卡根本没插好。输出类似NVIDIA Corporation GA106 [GeForce RTX 3060 Lite Hash Rate]这种就说明系统已经识别到显卡了。然后查看当前系统是否有NVIDIA驱动残留dpkg -l | grep nvidia如果之前装过驱动又没清理干净这里会列出一堆nvidia-*的软件包记得先全部清理掉再开始新的安装流程不然后面很容易出现驱动加载冲突。1.2 驱动、CUDA、框架三者版本匹配关系很多人搞不清楚驱动版本和CUDA Toolkit版本之间的约束关系。简单说显卡驱动是硬件和操作系统之间的桥梁CUDA Toolkit是开发库和编译器。驱动向上兼容——只要驱动版本足够新就能运行任何低版本的CUDA Toolkit。真正卡脖子的是向下不兼容驱动太老新型号的CUDA根本跑不起来。Ubuntu 20.04默认的apt源里就带NVIDIA驱动用ubuntu-drivers devices可以列出系统推荐的驱动版本ubuntu-drivers devices输出里会有driver: nvidia-driver-535 - distro non-free recommended这样的行recommended字样的就是系统推荐的版本。我的建议是如果没有特殊需求直接装推荐版本如果要用到比较新的CUDA版本在驱动上尽量选新不选旧因为新版驱动对老CUDA的兼容性通常没问题。判断驱动版本和CUDA版本匹配基本原则是参考NVIDIA官方的兼容性对照表其中驱动版本号可以理解为支持该CUDA所需的最低驱动版本。比如CUDA 12.2要求驱动版本最低为525.60.13CUDA 12.4要求550.54.14CUDA 11.8要求520.56.06。日常使用中装一个较新的驱动比如535或550系几乎可以通吃CUDA 11.x到12.x的所有版本这也是为什么我推荐大家优先选新版驱动。1.3 安装前的系统准备禁用nouveau和备份Ubuntu自带的nouveau开源驱动和NVIDIA官方驱动互斥不先禁用的话装上NVIDIA驱动后大概率黑屏或者循环登录。禁用nouveau的步骤创建配置文件sudo bash -c echo blacklist nouveau /etc/modprobe.d/blacklist-nvidia-nouveau.conf sudo bash -c echo options nouveau modeset0 /etc/modprobe.d/blacklist-nvidia-nouveau.conf然后更新内核并重启sudo update-initramfs -u sudo reboot重启后验证nouveau是否被禁用lsmod | grep nouveau没有输出就说明禁用成功了。这一步不做后面百分之百会出事别偷懒。系统备份方面主要备份/etc/apt/sources.list、/etc/modprobe.d/下的配置文件以及记录一下自己内核版本。用uname -r查看内核版本后续安装驱动时如果遇到unable to load the kernel module这类报错多半是内核头文件和驱动不匹配。2. NVIDIA显卡驱动安装apt和run文件两条路线实测2.1 最简单的方式apt直接安装驱动如果对驱动版本没有特殊要求只想快速把环境跑起来直接用apt安装是最省事的方案。对应搜索词里常见的apt install nvidia-driver-535命令如下sudo apt update sudo apt install nvidia-driver-535安装完成后重启sudo reboot然后用nvidia-smi验证能看到显卡型号、驱动版本和显存使用情况就说明驱动工作正常了。apt方式的优点非常明显依赖关系自动处理内核更新后驱动模块也会自动重建几乎不需要手动维护。缺点是版本受Ubuntu源更新节奏的限制想要第一时间用上最新驱动就比较难。另外apt方式装的是nvidia-driver-535这种带桌面集成件的完整包如果你用的是无桌面环境的服务器版很多组件其实用不上白白增加体积。2.2 进阶操作run文件安装驱动run文件方式灵活度更高适合需要精确控制驱动版本或者apt源里没有目标版本的场景。先把老驱动清理干净sudo apt purge nvidia-* -y sudo apt autoremove -y去NVIDIA官网下载对应型号的驱动run文件比如NVIDIA-Linux-x86_64-550.54.14.run放到家目录下然后进入纯命令行模式。Ubuntu 20.04默认GDM3显示管理器需要先停掉它sudo systemctl set-default multi-user.target sudo reboot重启后系统会直接进入命令行登录界面没有桌面环境登录后执行安装chmod x NVIDIA-Linux-x86_64-550.54.14.run sudo ./NVIDIA-Linux-x86_64-550.54.14.run安装过程中会问是否安装32位兼容库、是否更新Xorg配置一般一路默认即可。装完后切回图形界面sudo systemctl set-default graphical.target sudo rebootrun文件方式有个好处是安装过程可控性强可以在安装时加--no-opengl-files参数跳过OpenGL文件替换如果你需要用到CUDA的OpenGL互操作这里要谨慎。同时也可以加--silent静默安装配合--no-questions跳过交互提示。2.3 两条路线的选择逻辑我的实践结论是服务器无桌面环境用run文件更干净个人桌面用apt更省心。如果机器需要装CUDA Toolkit、TensorRT这类重型库我还是推荐run文件方式因为apt源中的nvidia驱动会和CUDA Toolkit的版本绑定关系更复杂出问题时排查链路长。run文件方式装了之后驱动位于/usr/lib/x86_64-linux-gnu/libcuda.so这种固定路径后续CUDA切换版本时不会互相干扰。2.4 驱动安装验证清单驱动装完不代表结束至少确认以下三件事nvidia-smi能看到显存、驱动版本号、正在运行的进程就OK。接着确认libcuda.so链接正常ldconfig -p | grep libcuda最后做一次简单的CUDA计算验证nvidia-smi --query-gpuname,driver_version,memory.total --formatcsv这一条命令能直接输出显卡名称、驱动版本和总显存如果输出正常驱动层面基本稳了。3. CUDA Toolkit多版本安装与自由切换3.1 选定CUDA版本的前置判断装CUDA之前先想清楚你的主力框架是什么。PyTorch官方在不同版本里支持不同的CUDA版本比如PyTorch 2.1对应CUDA 11.8和12.1PyTorch 2.4支持CUDA 12.1PyTorch 2.5开始主推CUDA 12.4。TensorFlow的版本兼容矩阵也有类似的规律。先看驱动能支持到哪个CUDA版本。nvidia-smi输出右上角会有CUDA Version: 12.4这个数字表示当前驱动支持的最高CUDA版本。如果这个数字是12.4那你装CUDA 12.2、12.1、11.8都没问题但装CUDA 13.0就会报错或者跑不起来。还有一个技巧是查官方兼容性表NVIDIA有详细的CUDA Toolkit和驱动版本对应关系文档安装前务必对照检查。另外注意架构兼容性。如果你用的是RTX 30系安培架构CUDA 11.x完全支持RTX 40系是ADA架构所有最新的CUDA特性往往只在新版CUDA里提供所以40系用户建议至少装CUDA 11.8以上版本。像搜索词里提到的4060 Ti最好直接上CUDA 12.x。3.2 run文件安装CUDA到自定义目录CUDA安装没有必须用deb包的说法反而run文件方式在多版本共存时更好用因为可以指定安装目录。去NVIDIA官网下载目标版本的run文件以CUDA 12.2为例文件名类似cuda_12.2.0_535.54.03_linux.run这个文件名末尾的数字就是对应的最低驱动版本。执行sudo sh cuda_12.2.0_535.54.03_linux.run进入交互界面后注意不要选安装驱动如果之前驱动已经装好了只选CUDA Toolkit和Driver那行取消其他组件可以全选。安装路径默认是/usr/local/cuda-12.2这个路径很重要后续多版本共存全靠它区分。如果之前装过其他版本CUDA安装时可能会提示已经存在/usr/local/cuda软链接不用管安装脚本一般不会去动既有版本目录只会更新/usr/local/cuda这个符号链接指向最后一次安装的版本。同样的方法再安装另一个版本比如CUDA 11.8sudo sh cuda_11.8.0_520.61.05_linux.run装完你会发现/usr/local/下多了cuda-11.8和cuda-12.2两个目录而/usr/local/cuda这个软链接指向最后安装的那个版本。3.3 用update-alternatives实现优雅切换直接改环境变量也能切换但每次都要手动改PATH和LD_LIBRARY_PATH太容易出错。Ubuntu的update-alternatives机制在这里非常好用先在系统里注册两个CUDA版本sudo update-alternatives --install /usr/local/cuda cuda /usr/local/cuda-11.8 118 sudo update-alternatives --install /usr/local/cuda cuda /usr/local/cuda-12.2 122后面这个数字是优先级数值越大优先级越高。查看当前版本sudo update-alternatives --config cuda会出现交互式选择列表输入对应编号就能切换。切换后/usr/local/cuda软链接自动指向所选版本。接下来配置环境变量。编辑~/.bashrcexport PATH/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda/lib64:$LD_LIBRARY_PATH export CUDA_HOME/usr/local/cuda然后source ~/.bashrc用nvcc -V验证当前生效的CUDA版本nvcc -V输出Cuda compilation tools, release 12.2, V12.2.0就说明切换成功了。以后每次切换版本只要跑一次sudo update-alternatives --config cuda不用再动环境变量所有依赖/usr/local/cuda的库和工具链会自动跟着走。3.4 多版本CUDA共存时的编译注意事项切换了CUDA版本后如果草稿编译时遇到找不到libcudart.so或者cuda.h找不到的错误多半是环境变量没生效或者某些第三方库被硬编码了路径。编译时可以用-I/usr/local/cuda/include -L/usr/local/cuda/lib64显式指定路径但这样不够灵活。更推荐的做法是在CMakeLists.txt里写set(CUDA_TOOLKIT_ROOT_DIR /usr/local/cuda) find_package(CUDA REQUIRED)这样每次切换版本后重新跑一次CMake就能自动关联到新的CUDA环境。还有个容易踩的坑LD_LIBRARY_PATH里同时存在多个CUDA版本的路径时动态链接器默认找其中一个很可能不是你想要的那个。切换版本后建议执行ldconfig刷新动态链接库缓存并且确认ldconfig -p | grep cudart看输出路径是否指向当前选中的CUDA版本目录。这种方式我实测非常稳定从CUDA 11.x切到12.x只需要几十秒。4. CUDNN安装与验证4.1 下载CUDNN不要选错版本CUDNN是NVIDIA的深度神经网络加速库装PyTorch或TensorFlow时都会隐式依赖它。下载CUDNN需要去NVIDIA官网注意选择与CUDA版本对应的CUDNN版本。CUDNN的命名格式是cudnn-linux-x86_64-8.9.4.25_cuda12-archive.tar.xz其中_cuda12表示这个版本对应CUDA 12.x。下载和安装的核心是版本匹配。如果你的CUDA是11.8就选带_cuda11的包CUDA 12.2就选_cuda12。版本搞错的话后面编译任何深度学习框架都会报libcudnn.so.8 not found或者undefined symbol: cudnn_*这类错误。4.2 tar包安装与符号链接配置推荐用tar包方式安装灵活且方便多个CUDA版本共用。下载后解压tar -xzvf cudnn-linux-x86_64-8.9.4.25_cuda12-archive.tar.xz然后把对应文件拷贝到当前CUDA目录cd cudnn-linux-x86_64-8.9.4.25_cuda12-archive sudo cp include/cudnn*.h /usr/local/cuda/include/ sudo cp lib/libcudnn* /usr/local/cuda/lib64/ sudo chmod ar /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn*这里有一个细节CUDNN的头文件和库文件分发给系统的CUDA目录如果你有多个CUDA版本最简单的方式是给每个版本都拷一份或者做成软链接。我更推荐在/usr/local/cuda-12.2和/usr/local/cuda-11.8下分别执行上面的拷贝操作这样切换CUDA版本时CUDNN不冲突。验证CUDNN是否生效cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2输出里会显示#define CUDNN_MAJOR 8、#define CUDNN_MINOR 9这样的行只要能看到版本信息就说明头文件到位了。再验证库文件ldconfig -p | grep cudnn能列出libcudnn.so.8就OK。4.3 用一个小程序验证CUDNN计算是否正常头文件和库文件拷贝到位不代表CUDNN真正能跑还需要一个实际的计算验证。写一个简单的CUDNN版本号查询程序cat test_cudnn.cpp EOF #include cudnn.h #include iostream int main() { cudnnHandle_t handle; cudnnCreate(handle); std::cout CUDNN Version: CUDNN_MAJOR . CUDNN_MINOR . CUDNN_PATCHLEVEL std::endl; cudnnDestroy(handle); return 0; } EOF g -o test_cudnn test_cudnn.cpp -I/usr/local/cuda/include -L/usr/local/cuda/lib64 -lcudnn LD_LIBRARY_PATH/usr/local/cuda/lib64 ./test_cudnn编译运行后输出CUDNN Version: 8.9.4就说明整个CUDNN环境完全正常。这个验证程序我一般会保留在机器上以后每次切换CUDA版本都会跑一遍确认环境没问题。5. 突破NVENC并发限制5.1 限制机制说明NVIDIA在消费级显卡GeForce系列上对NVENC视频编码器的并发会话数做了限制。最初只有GTX 10系和20系限制为3路并发后来RTX 30系和40系恢复为5路。专业卡Quadro、RTX A系列和数据中心卡Tesla、A10没有这个限制。这个限制在实际应用里非常烦人。比如你想在服务器上跑一个视频转码服务同时处理5路以上的实时流消费级显卡直接卡死在Maximum number of NVENC sessions is 5的报错上。工业批量转码、直播转码、多路视频监控分析都会碰到这个硬墙。5.2 补丁工具选择与编译安装好在社区有方案可以解除这个限制目前常用的是一个开源补丁项目通过给libnvidia-encode.so打补丁的方式去掉会话数检查。具体步骤首先从GitHub上将补丁项目源码clone到本地git clone https://github.com/keylase/nvidia-patch.git cd nvidia-patch然后执行打补丁脚本./patch.sh脚本会自动找到当前系统NVIDIA驱动对应的libnvidia-encode.so文件备份原文件后写入补丁。需要加载补丁./patch-fbc.sh这个补丁脚本还会一并解除NVFBC帧缓冲捕获限制如果你做屏幕捕获相关开发会更方便。打完补丁后需要重启相关服务或者重新加载驱动sudo modprobe -r nvidia_drm nvidia_modeset nvidia_uvm nvidia sudo modprobe nvidia nvidia_uvm nvidia_modeset nvidia_drm验证限制是否解除用FFmpeg做个多路并发编码测试ffmpeg -f lavfi -i testsrcduration10:size1920x1080:rate30 -c:v h264_nvenc -b:v 5M -f null -连续并发开启6个以上这样的转码任务如果能同时跑起来不报错说明限制已经打破。5.3 补丁的注意事项和风险补丁并不是一劳永逸的。每次升级NVIDIA驱动后libnvidia-encode.so会被新版驱动覆盖需要重新执行一次./patch.sh。另外升驱动后旧补丁直接失效务必重新打。风险方面要权衡打补丁属于修改驱动二进制文件的行为不符合NVIDIA最终用户许可协议。如果是生产环境且依赖显卡编码服务建议先在测试机器上验证稳定再推广到生产。另外新版驱动经常更新NVENC的库逻辑某些补丁可能在新版本上失效注意关注补丁仓库的更新动态。还有一个容易被忽略的点如果驱动版本跳过太多旧补丁脚本可能无法识别新版本。这时候需要手动指定驱动文件路径执行补丁。建议在打补丁前先备份原始libnvidia-encode.sosudo cp /usr/lib/x86_64-linux-gnu/libnvidia-encode.so.535.104.05 /usr/lib/x86_64-linux-gnu/libnvidia-encode.so.535.104.05.bak这里要根据实际驱动版本号调整文件名可以用find /usr/lib -name libnvidia-encode.so.*找到确切的文件名再进行备份。6. 高频问题排查与实战踩坑记录6.1 gzip: stdin: invalid compressed data -- format violated 问题这个报错经常出现在执行CUDA run文件安装时例如sudo sh cuda_12.2.0_535.54.03_linux.run然后终端弹出gzip: stdin: invalid compressed>sha256sum cuda_12.2.0_535.54.03_linux.run和官网公布的哈希值比对不一致就重新下载。下载时尽量用wget或浏览器原生下载不要用多线程下载工具这类工具在断点续传时极容易破坏文件完整性。之前我在某个机器上就是图省事用了加速下载结果连续两次碰到这个报错换成wget重新下载后一次通过。6.2 循环登录、黑屏和分辨率异常驱动装完重启后卡在登录界面输完密码又弹回登录界面这是最经典的驱动安装失败症状。通常原因有nouveau没有禁用干净、驱动版本与内核不兼容、之前的老驱动没有清理。处理方法是进TTY终端CtrlAltF3登录查看日志cat /var/log/Xorg.0.log | grep -i EE journalctl -xe如果是nouveau冲突日志里会看到Failed to load module nvidia之类的信息。这时候回到第一步确认lsmod | grep nouveau输出为空。如果novueau仍然在加载多半是/etc/modprobe.d/blacklist-nvidia-nouveau.conf配置没生效重新执行更新initramfs步骤。另外需要确认内核头文件是否安装sudo apt install linux-headers-$(uname -r)驱动安装时如果报unable to find the kernel source tree就是内核头文件缺失导致的。6.3 nvcc -V和nvidia-smi显示的CUDA版本不一致nvidia-smi右上角显示的CUDA Version是指当前驱动支持的最高CUDA版本nvcc -V显示的是当前激活的CUDA Toolkit版本。两者不一致是正常的不代表环境坏了。比如nvidia-smi显示CUDA Version: 12.4但nvcc -V显示release 11.8这是因为你当前shell环境里PATH指向了CUDA 11.8的nvcc。用which nvcc确认当前nvcc路径再用sudo update-alternatives --config cuda切换版本即可。需要注意区分的是运行深度学习框架时真正起作用的是驱动支持的CUDA Runtime即nvidia-smi的版本而不是nvcc -V显示的工具链版本。PyTorch在编译和运行时会调用自己的CUDA运行库所以有时候工具链版本和框架实际用的CUDA版本不一致也能跑这也是为什么很多人用conda装PyTorch时不需要额外装完整CUDA Toolkit的原因。6.4 新显卡用旧驱动导致的不兼容比如4060 Ti这类比较新的卡装了旧版驱动后nvidia-smi出现No devices were found或者显示Unknown Error。这种情况一般是驱动不认识新硬件的PCI ID解决办法就是升级驱动到官方支持该型号的最新版本。新显卡用户在选择CUDA时也要注意某些老版本的CUDA11.0、11.1对ADA架构支持不完善编译或运行时会出现no kernel image is available for execution on the device的报错。如果遇到这个错误优先换CUDA 12.x版本或者至少升级到11.8以上。6.5 conda环境下PyTorch和CUDA版本选择问题用conda管理Python环境时很多人习惯用conda install pytorch cudatoolkit11.7 cudnn这时conda会把CUDA库装在conda环境内部和系统级CUDA是两套独立的运行时。这种模式的好处是每个conda环境可以有独立的CUDA版本互相不干扰适合需要在同一台机器上测试不同CUDA配置的项目。坏处是conda装的CUDA版本一般比较滞后新版PyTorch对新CUDA特性的依赖可能没法满足。建议如果系统级已经装好了一套稳定的CUDA和CUDNNPyTorch直接装默认版本即可它会自动依赖系统CUDA运行库。如果遇到libcudnn.so.8找不到的错误说明conda环境里的CUDNN缺失用conda install -c conda-forge cudnn补上即可。注意conda环境里安装CUDNN后要确认LD_LIBRARY_PATH没有把系统路径覆盖掉。6.6 CUDA Samples编译失败或找不到很多人装完CUDA后想编译一个Samples测试结果make的时候报各种头文件缺失。CUDA Toolikt自带的Samples默认安装在/usr/local/cuda/samples下但有些版本需要手动补充安装sudo apt install freeglut3-dev libx11-dev libxmu-dev libxi-dev编译前先设置环境变量然后进入Samples目录执行sudo make -j$(nproc)编译过程中如果报cannot find -lGL需要安装OpenGL开发库sudo apt install libgl1-mesa-dev如果Samples目录都没找到可能是安装CUDA时没勾选Samples组件重新执行run文件安装脚本在选项里勾选即可。6.7 内核更新导致驱动失效Ubuntu自动升级内核后经常出现nvidia-smi报错或者驱动模块加载失败。这是因为DKMS机制在某些情况下没有正确重建驱动模块。解决方法是重新触发DKMSsudo dkms install -m nvidia -v 535.104.05这里的版本号根据实际驱动版本调整。如果提示DKMS模块不存在可能之前驱动不是通过apt安装的比如run文件方式这时候需要重新执行run文件安装或者干脆切换到apt方式。我的建议是需要长期稳定运行的机器做一个内核版本锁定不随系统自动升级。编辑/etc/apt/apt.conf.d/50unattended-upgrades把内核相关包加入黑名单然后只手动升级软件包避开内核变动带来的驱动失配风险。7. 个人经验和效率建议这些环境配置步骤全部走下来前后大概需要一个下午其中大半时间花在下载大文件和各种验证上。我自己的习惯是准备一个笔记文件把当前机器的驱动版本、CUDA版本、CUDNN版本、NVENC补丁状态、内核版本全部记录下来方便下次升级时快速定位问题。另外强烈建议装完一套能用的环境后用tar打包一份/usr/local/cuda目录和/etc/modprobe.d/blacklist-nvidia-nouveau.conf这样万一系统崩了恢复起来比重新走一遍全流程快得多。具体做法sudo tar -czf cuda_backup.tar.gz /usr/local/cuda*装新环境时解压回去再重建软链接和环境变量即可。最后再分享一个不少人在用的技巧多版本CUDA切换和CUDNN管理可以用一个shell脚本封装起来避免每次敲一长串命令。把常见的 switch-cuda 11.8、switch-cuda 12.2 这类操作写进函数放在~/.bashrc里日常切换环境只需要敲一行命令。环境这东西配置好之后越简单越好用能自动化的别手动能备份的别裸奔。