1. 环境理解与整体思路
1.1 这套平台组合到底特殊在哪
接手这个任务的时候,第一反应不是“装个驱动能有多难”,而是要先想清楚:麒麟V10、海光、NVIDIA这三个词凑在一起,意味着什么。
先说海光。海光的CPU是x86架构,指令集兼容AMD的Zen体系,所以它不是ARM、不是龙芯,也不是申威。这意味着在软件生态上,它可以跑绝大多数面向x86_64编译的二进制包,NVIDIA官方的Linux驱动runfile和rpm包理论上都能用。但海光平台多见于国产服务器和工作站,主板、BIOS、BMC这些固件层面的实现各有各家厂商的脾气,和大众消费级的Intel/AMD平台不太一样。很多人卡住,往往不是驱动本身的问题,而是平台底层环境没准备好。
再说麒麟V10。这个系统在国内服务器和政务、金融、能源这些行业里出镜率非常高。它有桌面版和服务器版之分,服务器版又有SP1、SP2、SP3这些迭代版本。内核版本跟着系统走,有的基于4.19,有的基于5.10甚至更高。这个信息很关键,因为NVIDIA驱动对内核版本有编译适配要求,内核太新或太老,都会直接影响安装结果。我这次用的镜像是麒麟V10 SP3的服务器版本,内核是5.10.x系列,整体接近RHEL 8系的技术底子,所以后面的操作很多都能参照RHEL/CentOS系的经验来。
最后是NVIDIA驱动。NVIDIA官方其实没有专门给麒麟V10做一版驱动,但它的Linux驱动是通用的,只要内核头文件齐全、编译器版本匹配、没有Nouveau驱动抢占设备,理论上就能装上。所以整个安装思路本质上是:把一个基于x86_64的Linux发行版上的NVIDIA驱动安装流程,迁移到麒麟V10+海光这个具体环境里。
1.2 为什么不用系统自带驱动管理器
刚开始我也犹豫过,能不能像Ubuntu那样,用麒麟自带的软件包或者驱动管理工具,一键装完。实测下来,这条路不太通。麒麟的软件源里确实有一些NVIDIA相关的包,但版本往往偏旧,而且和当前内核的dkms构建经常对不上。更麻烦的是,国产系统在不同的客户现场,软件源配置五花八门,有的甚至内网环境根本访问不了外部源。
所以我的建议很明确:直接用NVIDIA官网下载的runfile安装包,走传统编译安装路线。runfile的好处是自包含,不依赖系统源的包版本,驱动、内核模块、CUDA相关的用户态库都能自己搞定。缺点是它要走GCC编译内核模块,对系统的GCC版本、内核头文件有要求,这两点恰恰是国产系统上最容易出问题的地方。
换句话说,整个安装过程的难点不在“敲命令”本身,而在“把编译环境准备好”以及“处理掉各种历史包袱”。下面我把完整过程拆开讲,从环境检查到驱动安装,再到验证和排障,把每一步的为什么和怎么做都说清楚。
2. 安装前的环境准备
2.1 确认硬件、内核和系统版本
在动手之前,先花五分钟把环境摸清楚,这一步做扎实了,后面能少走很多弯路。我建议至少收集以下信息:
# 查看CPU信息,确认海光平台 lscpu | grep -i "model name" # 查看当前系统内核版本 uname -r # 查看操作系统版本 cat /etc/os-release # 查看GPU是否被系统识别 lspci | grep -i nvidia我在海光工作站上执行后看到的结果大概是这样的:Hygon C86 7280之类的CPU型号,内核是5.10.0-x,系统版本显示Kylin V10 SP3,lspci能列出NVIDIA的GPU型号。这些信息都正常,才说明硬件底子是好的。
有一个细节值得注意:lspci列出来的GPU名称有时会显示成NVIDIA Corporation Device 2230这样的格式,而不是大家熟悉的RTX 3080或A100。这很正常,因为驱动没装之前,系统不知道显卡的具体商业名称。只要能看到NVIDIA的vendor ID,就说明PCIe设备枚举没问题。
如果lspci里完全看不到NVIDIA设备,那问题就大得多,优先查主板BIOS里PCIe插槽是否启用、显卡供电是否正常、是否插在了被屏蔽的槽位上。这类硬件问题,后面装驱动再怎么折腾也没用。
2.2 让内核和编译工具链先就位
NVIDIA驱动runfile安装时,会为当前内核编译内核模块。如果内核头文件和GCC编译器不匹配,编译会直接失败。最常见的就是unable to find kernel headers或者一堆unknown symbol的报错。
麒麟V10 SP3服务器版基本已经内置了内核头文件,但名称可能和Ubuntu不一样,不是linux-headers-$(uname -r),而是kernel-devel或kernel-headers。可以用yum/dnf的方式检查:
# 先看看当前内核版本对应的devel包是否已安装 rpm -qa | grep kernel-devel rpm -qa | grep kernel-headers # 如果没装,尝试从系统源安装 yum install -y kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc --version make --version如果yum源可用,这一步通常很顺利。但很多生产环境是内网,无法联外网,那就要提前把rpm包下载好,离线安装。我建议在部署前,先在能联网的同版本机器上把这些rpm包通过yum install --downloadonly拉下来,然后用U盘拷到目标机器上手动rpm安装。
GCC版本也要注意。NVIDIA的runfile对GCC版本不是无限兼容的,太新的GCC(比如12以上)有时会在编译老版本驱动时出现告警,甚至直接报错。麒麟V10 SP3自带的GCC一般是8.x或9.x,这个区间比较安全。如果你机器上装了多个GCC版本,建议确认一下gcc --version指向的是哪个。必要时用update-alternatives切换到合适版本。
2.3 把Nouveau这个“绊脚石”按下去
Nouveau是Linux内核里开源的NVIDIA驱动实现。它和闭源驱动的最大冲突是:两者都要抢占NVIDIA GPU的设备控制权。如果Nouveau还挂着,NVIDIA驱动模块加载时会失败,最常见的现象就是装完驱动后执行nvidia-smi报错:
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.要避免这个问题,在安装NVIDIA驱动前,必须把Nouveau禁用掉。具体做法有两个层面。
第一个层面,在启动时给内核传参数,屏蔽nouveau模块。编辑/etc/default/grub:
vi /etc/default/grub在GRUB_CMDLINE_LINUX这一行加上:
rd.driver.blacklist=nouveau nouveau.modeset=0修改后重新生成grub配置:
grub2-mkconfig -o /boot/grub2/grub.cfg注意,麒麟V10用的是grub2,所以配置文件是grub.cfg而不是menu.lst。有些老教程里写的update-grub在Debian系里才有,RHEL系要用grub2-mkconfig。
第二个层面,创建黑名单文件,让modprobe加载内核模块时直接跳过nouveau:
cat > /etc/modprobe.d/blacklist-nouveau.conf << EOF blacklist nouveau options nouveau modeset=0 EOF然后重建initramfs,让这个配置在启动阶段就生效:
mv /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.bak dracut /boot/initramfs-$(uname -r).img $(uname -r)完成之后,重启系统。重启后确认nouveau彻底退出:
lsmod | grep nouveau如果这条命令没有任何输出,说明nouveau已经被按住了。这一步千万不能跳过,我见过很多人在这一步偷懒,结果安装过程中驱动编译成功了,但一重启就进不了图形界面或者nvidia-smi怎么都起不来,排查起来非常痛苦。
2.4 Secure Boot必须关闭
现在很多x86平台默认开启Secure Boot,尤其是品牌工作站和服务器。NVIDIA闭源驱动内核模块没有经过系统固件的签名,如果Secure Boot开着,系统启动时会拒绝加载这个模块。
处理方法是在BIOS里找到Secure Boot选项,设置为Disabled。不同厂商的BIOS菜单层级不一样,但关键词基本是Secure Boot或Security Boot。麒麟系统本身对安全启动的支持也在逐步完善,但就装NVIDIA驱动这件事来说,关掉它是风险最低的方案。
如果不方便进BIOS,也可以临时查看当前Secure Boot状态:
mokutil --sb-state如果是SecureBoot enabled,那还是老老实实去BIOS关掉。有些机器可以用mokutil --disable-validation之类的命令,但不同平台行为不一致,不建议在没把握的情况下在生产环境里冒险。
3. 下载驱动与安装执行
3.1 选择合适的驱动版本
到NVIDIA官网的驱动下载页面,选择Linux 64-bit,然后根据GPU型号选择驱动系列。数据中心GPU(比如V100、A100、A800、H800)有专门的Data Center Driver分支,工作站的RTX系列则用普通的Linux驱动分支。
版本选择上,我的经验是:不要一味追新。新版本虽然对新卡支持更好,但对老内核的兼容性不一定好。在麒麟V10 SP3这种偏RHEL 8的生态里,470系列和535系列是比较稳妥的选择。470系列属于LTS性质的长期维护分支,兼容性好,但新卡(比如Ada架构的RTX 40系)可能不支持。535系列对新一代GPU支持更好,同时也能在5.10内核上正常编译。如果是A100/H800这类数据中心卡,建议选535或更新的专业驱动分支。
举个例子,假设你的GPU是A100,当前NVIDIA官网提供的某个535版本的runfile文件名大概是这样:
NVIDIA-Linux-x86_64-535.154.05.run这个文件名本身包含了版本号,后面安装时要用上。
3.2 停掉图形界面再安装
NVIDIA驱动runfile安装时,会尝试替换系统中的OpenGL库,如果X Server还在运行,替换就可能失败,或者X Server崩溃。所以我在安装前都会把图形界面停掉,直接进入多用户命令行模式。
查看当前系统默认启动级别:
systemctl get-default如果输出是graphical.target,就要临时切到多用户模式:
systemctl isolate multi-user.target安装完成、驱动加载正常后,再切回图形界面:
systemctl isolate graphical.target这一步在桌面版麒麟V10上尤其重要,因为桌面版默认就是图形界面。我之前在桌面版上装驱动,忘了先切多用户模式,结果安装进行到一半,X Server崩溃,屏幕直接黑掉,只能通过SSH继续操作。
切换到命令行模式后,再执行安装程序:
chmod +x NVIDIA-Linux-x86_64-535.154.05.run sudo ./NVIDIA-Linux-x86_64-535.154.05.runrunfile会先做一系列检测,然后询问编译内核模块、安装OpenGL库、更新X配置等等选项。对麒麟+海光环境,我的建议是全程使用默认选项即可。但有一个选项值得留意:是否通过DKMS安装驱动。如果你不想每次升级内核后都手动重装驱动,建议开启DKMS。DKMS会在内核变更时自动重新构建NVIDIA内核模块,省去后续维护的麻烦。
安装完成后,脚本一般会自动modprobe nvidia这个内核模块。确认一下:
lsmod | grep nvidia nvidia-smi执行nvidia-smi如果能正常显示GPU型号、显存、驱动版本、CUDA版本,那就说明驱动已经成功加载。看到类似这样的输出,就代表基本成功:
+-----------------------------------------------------------------------------+ | NVIDIA-SMI 535.154.05 Driver Version: 535.154.05 CUDA Version: 12.2 | |-------------------------------+----------------------+----------------------+3.3 内核模块加载失败的兜底方案
虽然runfile安装偶尔一次就过,但海光平台上我遇到过几次内核模块编译完成、却加载不上的情况。这里提供两种系统性的应对思路。
第一种,检查内核模块文件是否真的存在。NVIDIA驱动安装后,内核模块会放在/lib/modules/$(uname -r)/kernel/drivers/video/nvidia*.ko之类的路径下。如果modules.dep没有更新,可以用depmod -a重建依赖关系,然后手动加载:
depmod -a modprobe nvidia第二种,确认是否有其他模块占用设备。有些系统里可能已经加载了nvidia_drm或nvidia_modeset,但因为版本不一致导致冲突。这种情况先清理旧模块:
rmmod nvidia_drm rmmod nvidia_modeset rmmod nvidia_uvm rmmod nvidia再重新加载。如果驱动版本太老,还可能会出现unknown symbol相关报错,这时基本就要考虑升级驱动版本了。
3.4 添加CUDA用户态环境的细节
NVIDIA的runfile安装驱动后,用户态库(比如libcuda.so、libnvidia-ml.so)会默认装到/usr/lib64或/usr/lib下,但有些时候库路径不在系统默认搜索路径里,导致后续装CUDA Toolkit或跑PyTorch时找不到库。
我的习惯是在/etc/ld.so.conf.d/下新建一个nvidia.conf,把库路径加进去:
echo "/usr/lib64" > /etc/ld.so.conf.d/nvidia.conf echo "/usr/lib" >> /etc/ld.so.conf.d/nvidia.conf ldconfig如果是通过runfile自定义安装路径安装(比如装到了/opt/nvidia),那就要把对应的lib目录加到ld.so.conf.d里。这一步看似无关紧要,但能避免很多“驱动显示装好了,一跑程序就报libcuda.so找不到”的问题。
另外,环境变量也很重要。在/etc/profile.d/nvidia.sh里加上:
export PATH=/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH这样新开的shell会话就能直接用nvcc和跑CUDA程序了。
4. 验证、调优与常见问题排查
4.1 驱动安装完成后的验证清单
驱动装完,不代表万事大吉。我在交付项目的时候,一般会按下面的清单逐项验证,确保系统重启后依然稳定:
第一项,重启系统,确认驱动能自动加载。很多人刚装完驱动能正常用,但一重启就出错,多半是内核模块没有设置成开机自动加载,或者initramfs里的nouveau残留。NVIDIA的runfile安装时一般会自动配置好modprobe加载,但如果是手动编译的内核模块,就需要检查/etc/modules-load.d/或者rc.local里有没有加载nvidia模块。
第二项,跑一遍nvidia-smi -q,查看GPU的详细信息,包括温度、功耗、显存使用率、PCIe链路速率。PCIe链路速率如果显示在x16 Gen3以下(比如卡在x1),说明卡的插槽没插对或者PCIe协商有问题,这个对性能影响很大。
第三项,跑一个简单的CUDA样例测试。如果你已经装了CUDA Toolkit,用自带样例验证:
cd /usr/local/cuda/samples/1_Utilities/deviceQuery make ./deviceQuery能看到Detected 1 CUDA Capable device(s)并且列出GPU型号,说明CUDA运行时能正常访问设备。如果想测更实际的计算性能,可以跑一下bandwidthTest或者cudaMemtest,这些工具能暴露显存或PCIe链路的隐性故障。
第四项,检查系统日志有没有NVIDIA相关的异常。dmesg | grep -i nvidia和journalctl -u nvidia-persistenced如果有ERROR级别的报错,要尽早处理。
4.2 安装过程中最常踩的坑
根据我自己的经历,以下是麒麟V10+海光平台安装NVIDIA驱动时最容易踩的几个坑,我按出现概率排个序,方便你自查。
坑一:nouveau没有完全屏蔽。这个出现概率最高。很多时候你明明写好了blacklist文件,但重启后发现nouveau还是加载了。原因往往是initramfs没有重建成功,或者BIOS里开启了某种fast boot,跳过了initramfs阶段的某些钩子。解决办法就是严格按照2.3节的步骤,先写blacklist,再重建initramfs,最后重启验证。不要省这一步。
坑二:内核头文件与当前内核版本对不上。很多国产系统的镜像包里,kernel-devel的版本和实际跑的内核不一致,尤其是管理员手动升级过内核后,头文件没跟上。安装驱动时runfile会提示找不到kernel headers,这时候不要硬装,先把头文件版本对齐。用rpm -qa | grep kernel-devel确认版本号。
坑三:GCC版本不兼容。NVIDIA驱动源码本身对GCC的warning比较敏感,新版GCC可能把一些warning当成error。如果编译报错里出现了error: implicit declaration of function或者unknown type name这类信息,优先考虑是不是GCC版本太新。降级GCC版本,或者用CC=/usr/bin/gcc-8 ./NVIDIA-Linux-x86_64-...run指定编译器版本。
坑四:nvidia-smi has failed because it couldn't communicate with the NVIDIA driver。这个报错我在“nouveau没屏蔽”和“内核模块编译不匹配”两种情况都遇到过。有一个快速判断方法:先执行lsmod | grep nvidia。如果nvidia模块完全没加载,优先查dmesg;如果模块加载了但nvidia-smi还是报错,检查/dev/nvidia*设备节点是否存在。很多时候设备节点没生成,手动执行mknod或者重新运行一次nvidia驱动安装程序来重建设备节点就能解决。
4.3 一个实战排障案例的完整还原
有一次在客户现场,海光服务器装驱动后,第一次启动一切正常,nvidia-smi也认卡,但重启后直接卡在登录界面,键盘鼠标没反应。
排查过程是这样的:
第一步,通过SSH远程登录服务器(如果SSH服务和网络正常),切换到命令行模式:
systemctl isolate multi-user.target第二步,查看X Server日志和dmesg:
dmesg | grep -i nvidia cat /var/log/Xorg.0.log | grep -i nvidia发现日志里有这样一句话:
(EE) NVIDIA: Failed to load module "glxserver_nvidia" (module does not exist, 0)这个报错说明X Server在启动时找不到NVIDIA的GLX模块。原因是runfile安装时,虽然装好了库文件,但Xorg的模块路径没配置好,或者安装时OpenGL库更新不完整。
第三步,解决办法有两个方向。一个是重新运行runfile,选择“更新X配置”,让驱动自己重新生成/etc/X11/xorg.conf。另一个是手动创建一个xorg.conf,指定GLX模块路径。
我通常的做法是先让runfile重新配置一遍:
sudo ./NVIDIA-Linux-x86_64-535.154.05.run --update如果不行,就手动生成xorg.conf:
nvidia-xconfig然后在/etc/X11/xorg.conf中的Module段确认有Load "glx"这行。如果用的是nvidia-drm模式,可能还需要在Device段加上:
Option "DRM" "true"重启X服务或者重启系统,问题就解决了。
第四步,如果上述方法都无效,直接检查/usr/lib/xorg/modules/extensions/libglxserver_nvidia.so是否存在。麒麟V10的X Server搜索路径有时不包括这个默认目录,需要在xorg.conf里指定ModulePath,让X Server能找到NVIDIA自带的GLX模块。这个坑在某型号海光桌面上我遇到过两次,后来就学乖了,安装完驱动后手动核对一下这个文件是否在正确位置。
4.4 性能验证与工作负载稳定性测试
驱动的安装只是第一步。如果这台机器是用来跑AI训练或推理的,我建议再做一轮更严格的压力测试,确保GPU在满载下不会因为驱动或散热问题崩溃。
显存压力测试工具cuda-memtest不一定自带,可以用简单的方法先测一下显存访问是否正常,比如反复申请和释放显存的脚本。如果机器上有PyTorch,也可以跑一段简单的训练循环,观察显存占用和核心温度曲线。
我还有一个习惯,就是在交付前把nvidia-smi -q -d TEMPERATURE和nvidia-smi -q -d POWER的输出保存一份,当作性能基线。如果过段时间用户反馈“GPU变慢了”,对比基线就能快速定位是不是散热老化、显存故障或驱动降频。
在H系列或A系列数据中心卡上,建议启用或确认nvidia-persistenced服务。数据中心卡默认不太喜欢频繁的上下文切换,持久化守护进程能让GPU保持在就绪状态,避免每次调用都重新初始化,影响推理延迟。
systemctl enable nvidia-persistenced systemctl start nvidia-persistenced5. 装机实战中的几点体会
5.1 用系统包里自带的兼容层和依赖处理常见问题
麒麟V10的服务器版本质上是一个RHEL衍生的生态,很多在CentOS上验证过的操作都能直接复用。有一类问题是编译器工具链之外的系统库缺失,比如libGL、libX11相关的包没装好。遇到这类情况,可以直接执行:
yum groupinstall -y "Development Tools" yum install -y libX11-devel libXi-devel libGL-devel装完后重新跑runfile安装,很多莫名其妙的报错就消失了。
5.2 能写进项目文档的经验
如果你是在给单位或客户做交付,我建议把下面这些内容整理进项目文档里。它们绝对能帮你省下大量“回访式排障”的时间:
- 当前内核版本和内核头文件版本的匹配情况,升级内核前必须先核对新版本有没有对应的kernel-devel包。
- Secure Boot是否关闭、BIOS里PCIe插槽是否插对了位置。
- Nouveau是否已屏蔽,以及initramfs是否已重建。
- NVIDIA驱动版本和安装日期,以及驱动对应的CUDA版本兼容性。
nvidia-persistenced是否已设置开机自启。- X Server的GLX模块路径是否被正确指定,特别是桌面版系统。
有一次用户反馈装完驱动后无法远程访问桌面,排查半天发现是Xorg的GLX模块路径配置问题,最后就是在xorg.conf里加了一行ModulePath "/usr/lib64/xorg/modules"解决的。这类东西如果项目文档里提前写明,后面运维的人会非常感激。
5.3 驱动安装后的系统更新策略
最后提醒一个坑:NVIDIA驱动对内核版本很敏感,一旦你升级了内核,旧的内核模块大概率就失效了。所以生产机器上如果有跑训练任务,我一般建议“系统更新要谨慎,内核更新除非必要否则推迟”。
如果你确实需要升级内核,那就升级前先把新版内核对应的kernel-devel装好,然后把NVIDIA驱动runfile再执行一次,让它重新编译内核模块。如果是通过DKMS安装的驱动,升级内核后一般会自动触发重新编译,但也建议手动验证一次:
dkms status nvidia-smiDKMS状态里如果显示驱动模块状态为installed,就说明内核更新后模块重建成功。如果显示built和installed不一致,多半是编译日志里有报错,需要查看/var/lib/dkms/nvidia/xxx/build/make.log来定位问题。
对我个人来说,这套流程虽然看起来步骤多,但每一步都是踩坑踩出来的。麒麟V10和海光平台在国产化替代的浪潮里会越来越多,NVIDIA驱动只是其中一个基础环节,但它是否装好,直接决定了上层AI框架能不能稳定跑起来。只要把环境检查、内核准备、nouveau屏蔽、驱动安装、模块验证这几步扎实执行,这个平台上的NVIDIA驱动安装并没有想象中那么玄乎。