ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux服务器NVIDIA GPU驱动安装:nvidia-smi到CUDA衔接

Linux服务器NVIDIA GPU驱动安装:nvidia-smi到CUDA衔接 服务器上装 GPU 驱动这件事我第一次做的时候也以为跟家里那台带独显的台式机差不多——下载个安装包双击下一步下一步就完事。结果 SSH 上去敲完nvidia-smi屏幕上蹦出一行NVIDIA-SMI has failed because it couldnt communicate with the NVIDIA driver那一刻的懵圈至今记得。更麻烦的是这台机器在机房里没法插显示器看画面全靠命令行盲操作一旦装崩了连图形界面都没有兜底只能靠 iDRAC/IPMI 进去救。这篇就聊聊在 Linux 服务器上安装 NVIDIA GPU 驱动的完整流程。它跟你日常在笔记本上装驱动最大的区别在于服务器通常没有图形界面、跑的是计算卡Tesla、A100、H100、L40S 这类、可能堆了好几块卡走 NVLink还可能开着 Secure Boot。这些条件叠加起来会让很多在桌面机上顺手就成的操作直接失效。文章会从硬件勘察一路讲到nvidia-smi出图、再到后面 CUDA 和深度学习框架的衔接中间重点拆解 nouveau 冲突、Secure Boot 签名、DKMS 与内核升级这几个最容易让人卡整晚的环节。适合刚接触 GPU 服务器运维的工程师、算法同学以及需要自己动手搭训练/推理环境的人。1. 服务器装驱动和桌面机到底差在哪很多人对装显卡驱动的印象来自 Windows 或者带图形界面的 Ubuntu 桌面版那套流程的核心矛盾是装了驱动会不会把图形界面搞黑屏。服务器场景下这个矛盾基本不存在因为绝大多数 GPU 服务器根本不装桌面环境没有 X Server 在跑也就不会有安装程序弹出那句让人头疼的You appear to be running an X server; please exit X before installing。但少了图形界面问题并没有变少只是换了个形状。桌面机装崩了最坏结果是进不去桌面、还能切 tty 抢救服务器装崩了通常表现为 SSH 上去之后nvidia-smi报错、lsmod里看不到nvidia模块、或者深度学习框架直接退回 CPU 模式跑你甚至没法直观判断驱动到底装上了没有。而且服务器往往是多人共用、跑着线上任务你没法像折腾自己电脑那样随便重启所以每一步都得想清楚后果。我把服务器场景下最容易翻车的点归成四类。第一类是nouveau 冲突这是 Linux 开源的 NVIDIA 显卡驱动几乎所有发行版默认就给你装上并加载了它会死死占住 GPU导致官方驱动装不进去或装完不生效。第二类是Secure Boot服务器 BIOS 里这个选项出厂经常是开的一旦开启未经签名的内核模块会被拒绝加载你装完驱动重启后modprobe nvidia就会失败。第三类是内核头文件缺失驱动需要编译内核模块而服务器上的内核版本往往比普通发行版更新得勤头文件没装或者版本对不上编译直接报错。第四类是计算卡的特殊性像 A100/H100 这种卡在部分整机尤其是 HGX/NVSwitch 架构上还需要配套的 Fabric Manager光装驱动不装它多卡之间通信会出问题。提示动手之前先确认这台机器是不是你独占的以及上面有没有正在跑的任务。装驱动大概率要重启重启意味着任务中断这个确认动作比任何技术细节都重要。另外要建立一个概念NVIDIA 的驱动包、CUDA Toolkit、cuDNN、框架版本之间是有依赖关系的。驱动是底座它决定了你最高能用哪个大版本的 CUDACUDA Toolkit 决定了你能编译/运行什么样的算子cuDNN 和框架则是再往上一层。很多人一上来就想着我要装 CUDA 12.x其实应该反过来——先看你的框架需要什么 CUDA再看这个 CUDA 需要多新的驱动。这个顺序搞反了后面全是返工。2. 动手前的勘察三分钟摸清机器底细在敲任何安装命令之前先把机器的基本情况摸清楚这一步花三分钟能省掉后面三小时的抓瞎。我习惯按卡、系统、现状三个维度来查。2.1 先确认显卡型号和总线状态lspci | grep -i nvidia这条命令会列出所有 NVIDIA 设备。如果是一条都看不到那要么卡没插好、要么被 BIOS 禁用了、要么是虚拟化环境里没做 PCI 直通这时候先别急着装驱动先把硬件层面的问题解决。加个-nn参数还能看到 PCI IDlspci -nn | grep -i nvidia输出里的[10de:xxxx]中10de是 NVIDIA 的厂商 ID后面那串是设备 ID。如果设备名显示成3D controller或者一串看不懂的代号说明当前系统的 PCI 数据库没认全这块卡这不影响装驱动但心里要有个数——它可能是比较新的卡需要较新的驱动分支才支持。顺便看一眼卡的拓扑和数量nvidia-smi -L # 如果旧驱动还在能直接列出卡 lspci | grep -c -i nvidia # 数一下有几块2.2 系统发行版和内核版本必须记下来cat /etc/os-release uname -runame -r的输出一定要记牢比如5.15.0-91-generic。这个完整版本号后面装内核头文件的时候要用到写成linux-headers-$(uname -r)是最稳妥的写法别偷懒只写linux-headers-generic因为头文件和当前运行内核哪怕差一个小版本模块编译都可能失败。顺便确认一下架构uname -m输出x86_64就是常规的 64 位 Intel/AMD 平台aarch64则是 ARM 平台比如某些国产化服务器或者 Grace 平台两者的驱动安装包完全不同别下错。2.3 查清楚机器上有没有残留的旧驱动或旧 CUDA这是最容易被忽略的一步。很多服务器是别人用过的或者之前装过一半失败了残留的配置文件会让新驱动装出各种诡异问题。lsmod | grep -i nvidia # 内核里有没有加载 nvidia 模块 dpkg -l | grep -i nvidia # Debian/Ubuntu 系看装了哪些包 rpm -qa | grep -i nvidia # RHEL/CentOS 系看装了哪些包 ls /usr/lib/modules/$(uname -r)/updates/dkms/ 2/dev/null # 看看有没有 DKMS 编译出来的模块如果lsmod里已经有nvidia、nvidia_modeset、nvidia_uvm这些模块在跑说明驱动是装过的这时候你要么是想升级、要么是想重装。两种情况的处理方式不一样升级可以用包管理器平滑处理重装的话建议先把旧驱动彻底卸载干净nvidia-uninstall或apt purge再动手。还要看一眼 nouveau 是不是在跑lsmod | grep nouveau只要这条命令有输出就意味着 nouveau 占着卡后面的步骤必须先把禁用 nouveau 这件事做掉。3. nouveau 与 Secure Boot两个能让你卡一整晚的环节如果说整套流程里有两个环节最容易出事那一定是 nouveau 冲突和 Secure Boot。它们有个共同特点——如果你不知道它们的存在报错信息会把你往完全错误的方向带。3.1 nouveau 为什么要禁用怎么禁才彻底nouveau 是社区逆向工程出来的开源 NVIDIA 驱动发行版默认给你装上是为了让系统开箱就能点亮显卡输出画面。但对于要装官方驱动的场景它就是个纯粹的障碍两块驱动抢同一块硬件官方驱动安装程序会检测到 nouveau 正在占用然后直接退出并提示The Nouveau kernel driver is currently in use by your system。禁用 nouveau 的标准做法是写一个黑名单配置文件让它开机不加载sudo tee /etc/modprobe.d/blacklist-nouveau.conf EOF blacklist nouveau options nouveau modeset0 EOF这两行的含义不一样blacklist nouveau是告诉系统不要自动加载它options nouveau modeset0是万一被别的模块依赖拉起来了也禁掉它的内核模式设置功能。只写第一行在有些发行版上不够两行一起写才保险。写完配置文件还不算完因为 nouveau 已经被打进 initramfs开机时加载的初始内存文件系统里了必须重新生成# Debian / Ubuntu sudo update-initramfs -u # RHEL / CentOS / Rocky sudo dracut -f注意这两条命令别搞混。在 Ubuntu 上敲dracut通常提示命令不存在在 RHEL 上敲update-initramfs同样不认。看清楚自己的发行版再执行。做完重启一次再用lsmod | grep nouveau验证没有任何输出才算干净。这一步我强烈建议单独重启验证一次别嫌麻烦直接往下走——如果 nouveau 没禁干净后面安装程序会以失败告终你还得回来重做一遍。3.2 Secure Boot 开启时模块加载会被拒绝Secure Boot 是 UEFI 的一项安全机制只允许加载经过可信签名的内核模块。服务器出厂时这玩意儿经常是开着的而 NVIDIA 官方的.run安装包编译出来的模块默认没有签名于是你装完重启nvidia-smi报错去dmesg里翻会发现类似module verification failed: signature and/or required key missing或者Loading of module with unavailable key is rejected的提示。先确认 Secure Boot 状态mokutil --sb-state输出SecureBoot enabled就是开着的。这时候有三条路一是直接进 BIOS 把它关掉最省事但有些托管服务器或者合规环境不允许二是用发行版仓库里的驱动包比如 Ubuntu 的nvidia-driver-XXX系列这些包通过 DKMS 编译时会自动处理签名走 MOK 机制三是自己给模块签名需要生成密钥、导入 MOK再配置 DKMS 签名脚本最麻烦但最灵活。# 生成签名密钥的流程自己签名的情况 openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -nodes -days 36500 -subj /CNLocal NVIDIA Module Sign/ sudo mokutil --import MOK.der # 执行后会让你设置一个密码重启时要在蓝色界面输入重启时会进入 MOK 管理界面选 Enroll MOK输入刚才设的密码完成导入。这一步如果没做后面即使签名了系统也不认这把钥匙。说实话如果服务器是你自己管的、内网环境我个人更倾向于直接关 Secure Boot省下的时间比折腾签名划算得多只有在权限受限的托管环境下才值得去走签名流程。4. 三条安装路线怎么选runfile、发行版仓库、官方 CUDA 仓库搞清楚障碍之后就要选安装方式了。市面上主流的就三条路各有各的适用场景选错了会给自己埋坑。安装方式典型命令/来源优点缺点适合谁官方 runfileNVIDIA 官网下载.run版本可控、干净、不依赖发行版仓库内核升级后容易失效、签名要自己搞想精细控制版本、机器网络受限发行版仓库ubuntu-drivers install/apt install nvidia-driver-XXX自动处理依赖和 DKMS、签名省心版本相对滞后、可能与需求版本不匹配追求稳定、不想折腾的大多数人官方 CUDA 仓库添加 NVIDIA 的 apt/yum 源版本比较新、和 CUDA 配套好需要配源、有时会污染系统 GL 库需要特定新版 CUDA 的场景我自己的选择逻辑是这样的如果服务器是 Ubuntu 且对驱动版本没有特别苛刻的要求优先用发行版仓库因为 DKMS 和 Secure Boot 签名它都帮你处理好了升级内核后驱动会自动重编长期维护最省心。如果框架明确要求某个新驱动版本、或者这台机器完全离线只能用 U 盘拷安装包那就走 runfile。官方 CUDA 仓库我用得最少主要是它装的东西比较多容易和系统自带的 GL 库打架。先说发行版仓库这条路在 Ubuntu 上非常简单sudo apt update ubuntu-drivers devices # 列出推荐驱动 sudo ubuntu-drivers autoinstall # 自动装推荐版本ubuntu-drivers devices会输出每块卡推荐的驱动版本标着recommended的那个通常就是经过测试的稳定版。想指定版本就sudo apt install nvidia-driver-550这样写。这条路装完直接重启就能用了DKMS 会保证内核升级后模块自动重建。再说 runfile 这条路这也是最原教旨、最能体现你到底懂不懂底层的方式。下一节详细展开。5. 保姆级实操从下载 runfile 到 nvidia-smi 出图以官方 runfile 为例走一遍完整流程。假设发行版是 Ubuntu 22.04内核是5.15.0-91-generic机器上是一块 A100。5.1 装齐编译依赖驱动安装时需要现场编译内核模块所以编译工具链和内核头文件必须先就位sudo apt update sudo apt install -y build-essential gcc make dkms \ linux-headers-$(uname -r) \ libglvnd-dev pkg-config这里解释几个容易被问到的点。dkms是可选的但强烈建议装装了之后驱动模块会在内核升级时自动重建能省掉后面无数的麻烦。linux-headers-$(uname -r)里的$(uname -r)一定要保留它会自动展开成当前内核版本写成固定版本号迟早出问题。libglvnd-dev是给需要 OpenGL/EGL 渲染的场景准备的如果你这台机器纯做计算、完全不涉及图形渲染可以省掉但如果后面要用到 headless 渲染比如某些视频处理、可视化任务就得装上否则驱动的 EGL 支持会缺一块。5.2 停掉图形界面如果存在的话纯粹的服务器通常没这个烦恼但如果装了桌面环境必须先把 X 或显示管理器停掉sudo systemctl isolate multi-user.target # 或者按发行版停对应的服务 sudo systemctl stop gdm3 # GNOME sudo systemctl stop lightdm # 有些发行版用这个验证一下没有图形进程占着卡ps aux | grep -i xorg没输出就说明干净了。这一步的目的是防止安装程序检测到 X Server 在跑然后拒绝安装。5.3 下载并执行安装先去 NVIDIA 官网找到对应驱动版本。挑版本有个原则不要盲目追最新要看你的框架和 CUDA 需求。一般来说选一个比你的 CUDA 需求稍新一个分支的驱动最稳。比如你要用 CUDA 12.4那驱动选 550 系列就够没必要上到最新的 570。# 假设下载到了 /tmp cd /tmp chmod x NVIDIA-Linux-x86_64-550.xx.xx.run # 执行安装各参数含义见下方说明 sudo ./NVIDIA-Linux-x86_64-550.xx.xx.run \ --dkms \ --silent \ --no-opengl-files \ --no-x-check安装参数逐个拆解一下这些参数比安装动作本身更重要--dkms把编译好的模块注册到 DKMS内核升级后自动重建。这个参数是长期省心的关键一定要加。--silent静默安装跳过交互式提问。第一次装建议先不加看看它问了什么心里有底再用。--no-opengl-files不安装 OpenGL 相关的库文件。服务器上通常不需要而且不装可以避免覆盖系统自带的 Mesa 库导致图形界面出问题。但如果你的场景需要 EGL headless 渲染这个参数就别加。--no-x-check跳过 X Server 检查。没桌面环境的服务器本来就没 X加不加都行加上更省事。--no-nouveau-check跳过 nouveau 检查。只有在确认 nouveau 已禁用但安装程序仍误报时才用不建议无脑加。安装过程会持续几分钟中间会编译内核模块你能看到一堆编译输出滚过去。最后提示Installation has completed successfully就成功了。5.4 加载模块并验证装完先不重启手动加载模块试试sudo modprobe nvidia lsmod | grep nvidia nvidia-smilsmod应该能看到nvidia_uvm、nvidia_modeset、nvidia这几个模块。nvidia-smi成功的话会输出一个表格显示驱动版本、CUDA 版本、每块卡的型号、显存占用、温度、功耗等。那个表格顶部的CUDA Version: 12.x要正确理解——它表示当前驱动最高支持的 CUDA 运行时版本不是你系统里装了什么 CUDA。很多人看到这个就以为自己装好了 CUDA其实 CUDA Toolkit 还得单独装。--------------------------------------------------------------------------------------- | NVIDIA-SMI 550.xx.xx Driver Version: 550.xx.xx CUDA Version: 12.4 | |------------------------------------------------------------------------------------- | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | ... | || | 0 NVIDIA A100-SXM4-80GB On | 00000000:07:00.0 Off | 0 | ... | -------------------------------------------------------------------------------------看到这张表驱动这块就算通了。重启一次再验证一遍确保模块能随系统正常加载。6. 报错排查nvidia-smi failed 这类问题的完整链路驱动报错最烦人的地方在于同一个nvidia-smi has failed because it couldnt communicate with the nvidia driver背后可能有五六种完全不同的原因。我总结了一套从上到下的排查顺序照着走基本能定位到根因。6.1 第一步永远是看内核消息dmesg | grep -i nvidia dmesg | grep -i -E nouveau|nvidia|nvrm内核消息是真相的第一现场。新版内核建议用sudo dmesg或者journalctl -k | grep -i nvidia。常见的几类输出对应不同的问题出现NVRM: API mismatch说明用户态库和内核模块版本不一致出现module verification failed是 Secure Boot 没处理出现nouveau相关字样是 nouveau 没禁干净出现No such device或者根本没输出可能是卡没被识别。6.2 第二步确认模块到底加载了没有lsmod | grep nvidia modinfo nvidia | head -5 modprobe -v nvidia # 手动加载看报什么错如果modprobe -v nvidia直接报Module not found说明模块文件根本没编译出来或者不在当前内核的模块目录下多半是内核头文件版本对不上或者 DKMS 没跑起来。如果报的是签名相关的错误回到第 3 节处理 Secure Boot。6.3 常见报错对照表报错现象最可能的原因处理方式couldnt communicate with the driver模块没加载 / 被 nouveau 占用查 dmesg禁 nouveau加载模块Driver/library version mismatch用户态库与内核模块版本不一致重启或卸载模块后重新modprobeNo devices were found卡未被识别 / 掉了lspci确认检查供电和插槽module verification failedSecure Boot 拦截了未签名模块关闭 Secure Boot 或签名模块安装程序提示 nouveau 在用nouveau 没禁干净重做黑名单 重建 initramfsUnable to find the kernel source tree缺内核头文件装linux-headers-$(uname -r)关于Driver/library version mismatch这个报错值得专门说一句。它的典型场景是你通过 apt 升级了驱动包但内核里跑的旧模块还在内存里没被替换于是用户态的nvidia-smi是新版本、内核模块是旧版本两边对不上。最简单的解法就是重启不方便重启的话先停掉所有用 GPU 的进程卸载模块再重新加载sudo rmmod nvidia_uvm nvidia_drm nvidia_modeset nvidia sudo modprobe nvidia注意卸载模块之前必须确保没有任何进程在使用 GPU否则会提示Module nvidia is in use。用fuser -v /dev/nvidia*能查出是哪些进程占着。6.4 一个容易被忽略的坑残留模块路径有时候你重装了驱动nvidia-smi还是报旧版本号原因是旧模块躺在/lib/modules/$(uname -r)/updates/dkms/里没被清掉系统优先加载了旧的。这时候需要手动清理ls /lib/modules/$(uname -r)/updates/dkms/ # 确认是残留后删掉再 depmod 重建依赖关系 sudo depmod -a这个坑我在一次灰度升级里踩过明明装了 550nvidia-smi却一直显示 535查了半天才发现是残留模块在作祟。7. 驱动通了只是起步CUDA、容器与框架的衔接驱动装好、nvidia-smi出图只说明底层通了。真正要跑训练或推理后面还有 CUDA Toolkit、容器运行时、深度学习框架三层要接上。7.1 驱动与 CUDA 的版本对应关系NVIDIA 的驱动设计上是有向后兼容性的一个驱动版本支持的 CUDA 版本有上限但可以向下运行更老的 CUDA。大致对应关系如下具体以官方兼容性矩阵为准版本更新很快驱动分支最高支持 CUDA大致535 系列CUDA 12.2550 系列CUDA 12.4570 系列CUDA 12.8这里有个实用的判断技巧你的 CUDA Toolkit 版本只要不高于nvidia-smi顶部显示的那个 CUDA 版本一般就能跑。比如显示CUDA Version: 12.4那你装 12.0、12.1、12.2 的 Toolkit 都没问题。只有当框架要求比这更高的 CUDA 时才需要升级驱动。需要说明的是如果只是用 pip 安装的 PyTorch/PaddlePaddle很多时候不需要单独装 CUDA Toolkit因为 pip 包会自带 runtime 组件。只有需要自己编译 CUDA 算子比如一些自定义扩展、TensorRT、或者编译带 GPU 支持的第三方库时才需要装完整的 Toolkit。7.2 容器方案把驱动和框架解耦现在生产环境越来越倾向于用容器跑 GPU 任务好处是驱动装在宿主机上容器里只带 CUDA 和框架升级框架不用动驱动。需要装 nvidia-container-toolkit# Ubuntu 为例配好 NVIDIA 的容器源之后 sudo apt install -y nvidia-container-toolkit sudo nvidia-ctk runtime configure --runtimedocker sudo systemctl restart docker # 验证 docker run --rm --gpus all nvidia/cuda:12.4.0-base-ubuntu22.04 nvidia-smi最后那条命令能在容器里跑出nvidia-smi的输出就说明容器运行时和驱动对接好了。这套方案的好处是宿主机上只要驱动版本够新容器里想跑什么 CUDA 版本都行互不干扰。7.3 PyTorch / PaddleOCR 的 GPU 验证装完框架后务必用一段小代码验证 GPU 是否真的可用别等训练跑起来了才发现一直在用 CPU。# PyTorch import torch print(CUDA available:, torch.cuda.is_available()) print(Device count:, torch.cuda.device_count()) print(Device name:, torch.cuda.get_device_name(0)) print(cuDNN version:, torch.backends.cudnn.version()) # 跑一个张量运算确认不是假可用 x torch.randn(1000, 1000).cuda() y x x print(Compute ok:, y.sum().item())# PaddlePaddle / PaddleOCR import paddle paddle.utils.run_check() # 输出里出现 PaddlePaddle is installed successfully 且检测到 GPU就说明通了这里有个我踩过的坑torch.cuda.is_available()返回True不代表计算真的走 GPU。因为 PyTorch 的 GPU 支持在导入时初始化如果 CUDA 是假可用比如只加载了 stub 库有些版本会返回 True 但实际运算报错。所以一定要跑一个真实的张量运算确保能出结果。8. 内核一升级驱动就挂长期维护的几个习惯驱动装好只是开始真正考验人的是长期维护。服务器上最常见的突发状况就是某天重启之后nvidia-smi又挂了八成是内核升级导致的。如果你的驱动是用 runfile 装的且没加--dkms那么每次内核升级新内核对应的nvidia.ko都不会自动生成系统默认启动新内核模块目录里却没有对应版本nvidia-smi自然报错。处理方式有两种一是回退到旧内核启动GRUB 里选Advanced options二是给新内核重新跑一遍安装程序。用 DKMS 是最根本的解法。无论走仓库还是 runfile都尽量把 DKMS 用上。仓库方式默认就是 DKMSrunfile 记得加--dkms。装好后可以用这条命令确认 DKMS 状态dkms status # 输出类似 nvidia/550.xx, 5.15.0-91-generic, x86_64: installed看到installed就对了。安装 DKMS 后内核升级时会自动触发模块重建省心很多。另外几个实用的运维习惯值得一提。第一给内核版本加锁可以避免意外升级在/etc/apt/apt.conf.d/或者用apt-mark hold linux-image-$(uname -r)把当前内核固定住等你确认新驱动兼容再解锁。第二开启持久化模式用sudo nvidia-smi -pm 1让驱动常驻减少多进程频繁初始化驱动的开销在多卡共享的机器上尤其明显。第三记录一份装机文档把驱动版本、CUDA 版本、内核版本、装的时间点写清楚等半年后再来这台机器不至于两眼一抹黑。最后再分享两个容易忽视的点。一是在数据中心的 A100/H100 机器上如果用了 NVSwitch 架构记得装对应的 Fabric Manager否则多卡的 NVLink 拓扑可能识别不全nvidia-smi topo -m看到的拓扑图会不对。二是做好监控nvidia-smi --query-gpuindex,name,temperature.gpu,utilization.gpu,memory.used,memory.total --formatcsv -l 5这条命令能每 5 秒拉一次所有卡的运行状态很适合接到监控系统里GPU 掉的、温度飙升这类问题能第一时间发现。我自己维护这批 GPU 服务器这几年最大的体会是装驱动这件事本身不难难的是把环境之间的依赖关系理清楚并且让这个环境在后续的内核升级、框架升级里不掉链子。把 DKMS 用上、把 Secure Boot 处理干净、把版本对应关系记在文档里后面就能少掉一大半的救火时间。真遇到nvidia-smi报错也别慌dmesg里那句报错基本已经把答案写在脸上了顺藤摸瓜就行。
返回列表