ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Ubuntu 18.04安装深度学习环境:NVIDIA驱动+CUDA 10.2+cuDNN实战

Ubuntu 18.04安装深度学习环境:NVIDIA驱动+CUDA 10.2+cuDNN实战 我实验室那台深度学习机器系统是 Ubuntu 18.04显卡是 RTX 2080 Ti之前一直是别人在维护驱动装得乱七八糟nvidia-smi时而能用时而报错。上周接到一个 TensorFlow 老项目要复现需要 CUDA 10.2 cuDNN 7.6.5我决定把整个环境推倒重装顺手把完整过程记录下来。这篇文章就是针对 Ubuntu 18.04 上安装 NVIDIA 显卡驱动 CUDA 10.2 cuDNN 的实操记录覆盖从卸载旧驱动、禁用 nouveau、安装驱动、配置 CUDA 环境变量到验证 cuDNN 的完整链路。如果你也是在自己机器上搭深度学习环境、跑 PyTorch 或 TensorFlow 老版本这篇应该能帮你少走不少弯路。1. 装之前先把版本匹配关系搞明白别急着敲命令很多人一上来就sudo apt install nvidia-driver-xxx装完发现 CUDA 编译器不认驱动或者驱动版本太新导致老 CUDA 直接拒绝工作。这里必须先理清一个核心关系驱动版本决定 CUDA 版本的上限CUDA 版本又决定 cuDNN 版本的选择。1.1 显卡驱动、CUDA、cuDNN 三者的依赖链NVIDIA 显卡驱动是硬件和系统之间的桥梁CUDA 是并行计算平台cuDNN 是基于 CUDA 的深度神经网络加速库。三者的版本关系大致是CUDA 10.2 要求驱动版本 440.33Linux x86_64NVIDIA 驱动只要版本 440.33都能支持 CUDA 10.2cuDNN 7.6.5 是支持 CUDA 10.2 的常用稳定版本我这次选择的是NVIDIA 驱动 450.80.02因为它的官方支持周期覆盖 CUDA 10.2而且对 Turing 架构RTX 20 系支持很成熟。如果你的显卡是 Ampere 架构RTX 30 系建议直接把系统升级到 Ubuntu 20.04 或 22.04因为老驱动对 Ampere 支持并不完善而且 CUDA 10.2 在新架构上本身就有兼容性问题。提示nvidia-smi右上角显示的 CUDA Version 是驱动支持的最高 CUDA 版本不代表你当前已经安装了对应版本的 CUDA Toolkit。这是个非常容易误解的地方。1.2 确认显卡型号和当前系统状态打开终端先跑几个命令确认环境# 查看显卡型号 lspci | grep -i nvidia # 查看当前是否已装驱动 nvidia-smi如果nvidia-smi提示has failed because it couldnt communicate with the nvidia driver说明驱动没装好或内核模块加载失败。如果你之前装过驱动但出了各种问题不要急着在当前环境上打补丁直接卸载干净重装是最节省时间的方案。再看一下内核版本Ubuntu 18.04 默认内核是 4.15但很多人的系统更新后变成 5.4 或更高uname -r内核版本和驱动编译直接相关。runfile 方式安装驱动时会在内核里编译 NVIDIA 内核模块需要确保有对应内核版本的 header 包。如果你是多内核版本共存装驱动时务必确认当前启动的是哪个内核。2. 干净起步卸载旧驱动和禁用 nouveau 的完整链路我见过大量装驱动失败的案例一半以上都是因为旧驱动没卸干净或者 nouveau 没禁用彻底。这一步做得干净后面会省非常多事。2.1 先卸旧驱动别留残余文件如果你系统里已经有 NVIDIA 驱动不管是 apt 装还是 runfile 装的先这样卸载# 通过 apt 安装的驱动 sudo apt purge nvidia-* -y sudo apt autoremove -y # 通过 runfile 安装的驱动 sudo nvidia-uninstall如果两个都不知道直接全跑一遍不报错就好。卸载完成后重启一次确保内核模块没有被占用。2.2 禁用 nouveau 是装驱动前最关键的防火墙nouveau 是 Linux 内核自带的开源 NVIDIA 驱动它和官方闭源驱动水火不容。如果不禁止 nouveau装官方驱动时大概率会遇到类似ERROR: The Nouveau kernel driver is currently in use by your system的报错。禁用步骤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重启后确认 nouveau 确实被禁用lsmod | grep nouveau没有任何输出就说明禁用成功。如果还有输出检查/etc/modprobe.d/下是否还有其他配置文件重新加载了 nouveau或者initramfs是否没有刷新成功。注意禁用 nouveau 后在装好 NVIDIA 驱动之前你的屏幕分辨率可能会变低这在安装过程中是正常现象不用慌。如果你用的是服务器没有显示器操作全靠 SSH禁用 nouveau 就更安全了。2.3 安装内核头文件防止驱动编译失败runfile 装驱动时会调用dkms或直接编译内核模块没有内核头文件基本必挂。提前装好sudo apt update sudo apt install linux-headers-$(uname -r) build-essential这步看起来简单但很多人会忽略。build-essential装的是 gcc、make 等编译工具链没有它 runfile 会在编译阶段直接失败。3. runfile 方式安装 NVIDIA 驱动每一步都有讲究驱动安装无非三种方式apt 直接装、PPA 源装、runfile 装。我这次选 runfile 而不是 apt原因很简单apt 源里的驱动版本是区分 LTS 的Ubuntu 18.04 的官方源停留在 390 或 440 左右跑 CUDA 10.2 没问题但如果你想更精确地锁定驱动版本runfile 最可控。3.1 下载对应版本的驱动去 NVIDIA 官网的驱动下载页面输入你的显卡型号和操作系统选择 Linux 64-bit拿到一个.run文件。我下载的是NVIDIA-Linux-x86_64-450.80.02.run。下载时注意网站会根据当前时间推荐最新驱动你用 CUDA 10.2 的话不是越新越好。驱动太新比如 470虽然兼容性更好但没必要450 系列对 CUDA 10.2 最稳。3.2 安装命令和参数说明文件下载完成后先给它执行权限chmod x NVIDIA-Linux-x86_64-450.80.02.run安装命令sudo ./NVIDIA-Linux-x86_64-450.80.02.run --no-opengl-files--no-opengl-files这个参数我是强烈建议加上的。它表示不安装 OpenGL 相关的库文件。在带显示器的桌面上这个参数可以大量避免桌面环境冲突比如登录循环。如果你机器上跑的是无桌面环境或者纯粹作为计算服务器加这个参数更安全。安装过程中会出现几个交互提示是否安装 DKMS选择 Yes。DKMS 会在内核更新后自动重新编译驱动模块否则每次升级内核驱动就废了。是否运行 nvidia-xconfig如果你用的是 Xorg 桌面选 Yes纯计算或 SSH 远程的话选 No。是否安装 32 位兼容库按需选择一般 No。3.3 验证驱动是否装成功安装完成后重启sudo reboot再次打开终端运行nvidia-smi正常输出应该长这样----------------------------------------------------------------------------- | NVIDIA-SMI 450.80.02 Driver Version: 450.80.02 CUDA Version: 11.0 | |---------------------------------------------------------------------------注意这时的 CUDA Version 显示的是驱动支持的最高版本11.0不表示你系统里已经装了 CUDA 11.0。这只是驱动的属性后面还需要单独装 CUDA Toolkit。如果nvidia-smi依然报错先看内核模块lsmod | grep nvidia如果没有输出查一下/var/log/nvidia-installer.log里最后几行八成是内核头文件没装对或者 nouveau 没禁干净。4. CUDA 10.2 安装坑集中在路径和环境变量驱动装好后CUDA Toolkit 的安装相对简单但路径和环境变量配置不当会导致nvcc -V版本对不上或者程序运行时报 CUDA driver 版本不匹配。这些坑我基本都踩了一遍。4.1 下载 CUDA 10.2 安装包CUDA 10.2 的官方下载链接可以从 NVIDIA Archive 页面找到选择 Linux → x86_64 → Ubuntu → 18.04 → runfilelocal方式。这里有必要解释一下为什么选 runfile 而不是 deb 包。deb 包安装会直接把 CUDA 装到/usr/local下后续如果你想切换多版本 CUDA比如切到 11.8deb 方式的路径管理比较麻烦。runfile 安装时可以选择安装目录更灵活。而且 runfile 不依赖 apt 源不污染系统包管理器。wget http://developer.download.nvidia.com/compute/cuda/10.2/Prod/local_installers/cuda_10.2.89_440.33.01_linux.run下载后也是一个.run文件执行sudo sh cuda_10.2.89_440.33.01_linux.run安装时会先卡在一个协议界面按q跳过文档然后输入accept。接下来进入组件选择界面关键一步取消勾选 Driver。因为我们已经手动装好了 450.80.02不需要 CUDA 里自带的 440.33 驱动。如果这里不取消安装程序会覆盖你的驱动版本可能造成版本回退甚至驱动冲突。其他组件默认全选安装路径默认/usr/local/cuda-10.2就可以。4.2 软链接确认与环境变量配置安装完成后检查目录ls -l /usr/local/ | grep cuda你会看到/usr/local/cuda-10.2和/usr/local/cuda两个目录。cuda是指向cuda-10.2的软链接。如果之前装过其他版本的 CUDA这里的软链接可能指向旧版本需要手动改sudo rm -rf /usr/local/cuda sudo ln -s /usr/local/cuda-10.2 /usr/local/cuda之后配置环境变量。编辑~/.bashrcvim ~/.bashrc在文件末尾加上export PATH/usr/local/cuda-10.2/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda-10.2/lib64:$LD_LIBRARY_PATH export CUDA_HOME/usr/local/cuda-10.2然后source ~/.bashrc验证nvcc --version正常能看到Cuda compilation tools, release 10.2, V10.2.89。4.3 PATH 和 LD_LIBRARY_PATH 配置后常见的坑这里有一个非常多人踩的坑nvcc -V显示的是 10.2但跑 Python 程序时用的却是别的地方的 CUDA。原因是你的~/.bashrc里配置的LD_LIBRARY_PATH只对 shell 有效而 Python 的torch或tensorflow在加载 CUDA 库时会按照ldconfig的缓存来找不是按LD_LIBRARY_PATH找。如果运行程序报错libcudart.so.10.2: cannot open shared object file可以手动刷新库缓存sudo ldconfig还是不行就在/etc/ld.so.conf.d/下新建一个cuda-10.2.confecho /usr/local/cuda-10.2/lib64 | sudo tee /etc/ld.so.conf.d/cuda-10.2.conf sudo ldconfig这样整个系统层面的动态链接库搜索都能找到 CUDA 10.2 的 so 文件。另外环境变量配置在~/.bashrc里只在交互式 shell 生效。如果你通过 systemd 服务或 cron 跑训练任务这些变量的配置方式不一样建议写进/etc/environment或服务文件里否则程序启动时找不到 CUDA 库。5. cuDNN 安装复制文件、给权限别用 aptcuDNN 的安装其实非常简单因为本质上就是一堆.h头文件和.so动态库文件。但 NVIDIA 要求先注册账号才能下载这一点很多人会被卡住这里说下流程。5.1 下载 cuDNN 7.6.5 for CUDA 10.2登录 NVIDIA 开发者网站进入 cuDNN Archive 页面选择Download cuDNN v7.6.5 (November 18th, 2019), for CUDA 10.2对应 Ubuntu 18.04 的版本是cuDNN Library for Linux (x86_64)它是一个.tgz压缩包不需要安装器直接解压复制。这里选.tgz而不是 Debian 包的原因和之前选 runfile 一样方便多版本管理。Debian 包会把 cuDNN 装到系统目录切换版本时很难清理干净。.tgz方式只是复制文件想换版本重新复制就行。5.2 文件复制和权限设置下载解压后tar -xzvf cudnn-10.2-linux-x64-v7.6.5.32.tgz解压出cuda目录里面包含include、lib64和docs三个子目录。将头文件和库文件复制到 CUDA 安装目录sudo cp cuda/include/cudnn.h /usr/local/cuda-10.2/include/ sudo cp cuda/lib64/libcudnn* /usr/local/cuda-10.2/lib64/注意 cuda 10.2 实际上有 lib64 也有 lib32这里的 CUDA 10.2 是默认 x86_64 的所以 lib64 就够。动态库文件不是简单的复制就完事还要确保符号链接正确。libcudnn的文件名一般有几种形式libcudnn.so - libcudnn.so.7 libcudnn.so.7 - libcudnn.so.7.6.5 libcudnn.so.7.6.5 实际文件解压包里通常已经带好了这些软链接复制时用cp -P保留链接关系sudo cp -P cuda/lib64/libcudnn* /usr/local/cuda-10.2/lib64/如果之前已经复制过但软链接断了清理后重新复制sudo rm /usr/local/cuda-10.2/lib64/libcudnn* sudo rm /usr/local/cuda-10.2/include/cudnn.h sudo cp -P cuda/lib64/libcudnn* /usr/local/cuda-10.2/lib64/ sudo cp cuda/include/cudnn.h /usr/local/cuda-10.2/include/然后更新权限sudo chmod ar /usr/local/cuda-10.2/include/cudnn.h sudo chmod ar /usr/local/cuda-10.2/lib64/libcudnn*再刷新动态库缓存sudo ldconfig5.3 验证 cuDNN 版本的正确姿势用复制文件的方式安装 cuDNNnvcc -V是看不到 cuDNN 版本信息的需要直接查文件cat /usr/local/cuda-10.2/include/cudnn.h | grep CUDNN_MAJOR -A 2注意cuDNN 7.x 的版本信息写在cudnn.h里。但新版 cuDNN 8.x 改成了cudnn_version.h。这里安装的是 7.6.5所以直接看cudnn.h即可。正常输出#define CUDNN_MAJOR 7 #define CUDNN_MINOR 6 #define CUDNN_PATCHLEVEL 5有时这个头文件路径可能在子目录里比如include/x86_64-linux-gnu/cudnn_v7.h这时候用find全盘搜find /usr/local/cuda-10.2 -name cudnn*.h还有一个更实用的验证方式直接编译运行 cuDNN 自带的示例代码。源码路径在解压包的/docs目录下或者直接上网找一个 mnistCUDNN 示例cp -r /path/to/cudnn_samples_v7/mnistCUDNN ~/ cd ~/mnistCUDNN make clean make ./mnistCUDNN如果输出包含Test passed!说明 cuDNN 安装正确TensorFlow 或 PyTorch 在调用 cuDNN 时不会报DNN library not found之类的错误。6. 重启后驱动失效和版本不对是最常见的两个翻车点装完三件套之后很多人以为大功告成结果重启后nvidia-smi打不开或者 Python 里torch.cuda.is_available()返回 False。这里把最常见的两个问题的排查思路完整梳理一遍。6.1 重启后nvidia-smi失效内核模块没加载重启后 nvidia-smi 失效大概率是 NVIDIA 内核模块没被自动加载。先手动加载试一下sudo modprobe nvidia如果modprobe报错Key was rejected by service这通常和 Secure Boot 有关。你的机器如果开启了 UEFI Secure Boot内核会拒绝加载未签名的第三方驱动模块。实际上就是在安装驱动时NVIDIA 模块无法通过 Secure Boot 的签名验证导致模块被系统丢弃。解决方式有两个在 BIOS 里关闭 Secure Boot这是最快的。使用 DKMS 添加签名密钥比较复杂不推荐新手。绝大多数人关闭 Secure Boot 后modprobe nvidia就能正常加载了。手动加载成功后确认nvidia-smi正常之后再检查模块是否设置开机自启systemctl list-unit-files | grep nvidia如果没有相关的 systemd 服务可以手动把模块加进/etc/modulesecho nvidia | sudo tee -a /etc/modules echo nvidia_modeset | sudo tee -a /etc/modules echo nvidia_uvm | sudo tee -a /etc/modules echo nvidia_drm | sudo tee -a /etc/modules为什么nvidia-drm也要加因为现代桌面环境的合成器比如 GNOME 的 Mutter如果开启了 DRM 内核模式设置KMS需要nvidia_drm模块提前加载否则显示会出问题。对于纯计算服务器不加也可以但加了更省心。6.2 Python 里显示 CUDA 版本不对环境变量和 PyTorch 的坑如果你安装 PyTorch 时用的是默认源它默认会安装最新版本而最新版 PyTorch 需要 CUDA 11.x 以上。在 CUDA 10.2 环境下跑最新版 PyTorch会直接报CUDA driver version is insufficient for CUDA runtime version。这里要明确一点PyTorch 是自带 CUDA runtime 的。pip install torch装的版本不等于你系统里nvcc -V的版本它内部编译时依赖的 CUDA 版本是预编译好的。如果你系统只有 CUDA 10.2那么必须安装对应的 PyTorch 版本。用 CUDA 10.2 对应的 PyTorch 版本建议这样安装pip install torch1.7.1 torchvision0.8.2PyTorch 1.7.1 是支持 CUDA 10.2 的比较稳定的版本。如果你想跑更新版本的 PyTorch可以在官网找对应 CUDA 10.2 的安装命令但最终会发现老版本依赖链上很多东西要一起老下去。在 Python 里验证import torch print(torch.version.cuda) print(torch.cuda.is_available())如果输出10.2和True环境就通了。6.3 驱动 450.80.02 和 CUDA 10.2 的匹配度说明你可能注意到我这里驱动装的是 450.80.02而官方对应 CUDA 10.2 的最低驱动是 440.33。NVIDIA 驱动和 CUDA 有一个minor version compatibility机制意思是新的驱动版本可以跑旧的 CUDA Toolkit 编译出来的程序所以 450.80.02 完全支持 CUDA 10.2。如果你遇到编译出来的程序报错CUDA error: insufficient driver那说明驱动装得不够新。用 450.80.02 就没这个问题。不要看到nvidia-smi显示CUDA Version: 11.0就慌那只是驱动支持的最高版本不影响你跑 10.2 的 CUDA 程序。7. 达成 CUDA 10.2 可用环境后我给新手的配置结论如果你也想组装一套稳定跑旧项目的环境这里给你一个可直接参考的配置组合组件版本说明操作系统Ubuntu 18.04.5内核 5.4 以下更稳NVIDIA 驱动450.80.02向下兼容 CUDA 10.2CUDA Toolkit10.2.89需要取消安装内置驱动cuDNN7.6.5 for CUDA 10.2使用 tgz 解压复制PyTorch1.7.1对应 CUDA 10.2TensorFlow2.3.0对应 CUDA 10.2如果你的卡是 Ampere 架构RTX 30 系不用往下看了先把系统升级到 20.04 再说。Turing 和旧架构10 系、20 系跑这套配置完全没有问题。8. 一些零碎但真实有效的实操经验总结最后讲几个我踩过的零碎坑经验分享不是教程但每一个都让我多花了至少半小时。8.1 下载慢和下载失败的处理CUDA 的 runfile 安装包大概 2GB 多NVIDIA 官方的下载速度时快时慢经常断。下载到一半断了以后新的wget -c支持断点续传但 NVIDIA 下载服务器有时候不配合建议直接用浏览器下载或者挂一个下载工具。下载完以后顺手校验一下 MD5官网每个文件都提供了 MD5 值。文件损坏是安装时报stdin: invalid compressed>
返回列表