在RHEL8上安装Nvidia Driver(CUDA)
一般来说深度学习还是用Ubuntu比较好,安装的时候直接帮你把Nvidia驱动装好,非常方便。
但是国内大批公司还是RHEL(CentOS)的,至于我们公司那只能用RHEL了。
RHEL装CUDA较为麻烦,牵涉的知识较为广泛。我也卡了很久,百思不得其解。
过去如果遇到装不上CUDA的问题,那很可能是无解的问题。因为Nvidia过去对Linux的支持可谓极差,又不开源。常见问题例如:
- 为旧硬件不提供新kernel的适配
- 为旧kernel不提供新硬件的适配
- bug无人修,也无处可以问等等
所以过去都要买主流硬件,比如1080/20系/30系等等。我目前手上是一块非常便宜的Geforce 730桌面显卡。过去这块显卡只有CUDA 8的驱动,而且只能适配特定版本的kernel。这次惊喜的发现,黄夹克居然为这款硬件更新驱动了,目前支持CUDA11。
这里写一下一般的安装方法。
硬件配置
一台Lenovo ThinkCenter台式机,附带730显卡(这块显卡居然还贴着精粤的标签),内存32G,一块512G固态硬盘,一块2T机械硬盘。
软件配置
RHEL 8.8
SELinux必须开启
需要安装vim这样的编辑工具
主要问题和预想的解决方案
历史背景是,N卡过去驱动并不开源,因为N卡也不是OpenGL的路子,社区没法像A卡那样给他做基于OpenGL的驱动。所以经历了漫长(最起码有10+年)的努力后,给N卡做了一款通用驱动叫nouveau。这款驱动神奇就是一个版本对应所有显卡,另外常常会无故花屏死机。但是目前如果不像Ubuntu那样自己给kernel做适配的话,Linux发行版默认都是用nouveau这款版本的驱动的。因为Linux内核的发行许可是GPL,这就意味着如果N社不做开源,Linux就无法把N社的驱动集成到自己内核里,GPL的license限制了这一点。所以就必须用户自己来装。
那方案其实一开始就是很明确的。
先在N社官方主页找到并下载驱动,然后进命令行界面把nouveau这款驱动禁了,再把N社驱动装上,再回到GUI界面,只要nvidia-smi命令执行完不报错即可。
实际步骤稍微有些不同。
需要再追加一些步骤。由于N社驱动是在本机编译代码然后生成内核模块添加进linux内核。所以首先要在BIOS里禁止安全启动(Secure Boot),在Linux里SELinux。然后要搞定内核签名的问题,不然BIOS里没法把安全启动再开起来。
解决步骤
1. 在BIOS里禁止安全启动
以Lenovo为例,开机按F2进入BIOS。然后在安全(Security)选项卡里找到安全启动(Secure Boot),选择关闭即可。没有鼠标的用上下方向键和回车/空格操作。
为何要禁止安全启动?安全启动本质上是让Linux校验内核模块的签名,拒绝自签名的内核模块。如果不禁止安全启动的话,内核就会无法加载下面编译完的nvidia驱动。换言之,在安装完成后,重新开启安全启动,也会造成内核无法加载nvidia驱动,导致进不了GNome/KDE等X Windows。
2. 在RHEL里临时禁止SELinux
编辑/etc/selinux/config
执行命令
然后找到SELINUX=enforcing这行,改为SELINUX=disabled
禁止SELinux的资料还可以参考:链接
3. 安装必要软件
N卡驱动实际上是源代码,然后安装过程就是编译源代码生成内核模块。所以至少需要基础的编译和一些devel包。已知编译需要下列包(可能过多)
dkms kernel-devel libglvnd-devel libva-utils libva-vdpau-driver vdpauinfo
安装dkms后就可以让dkms每次在安装新kernel后自动编译驱动,但是代价就是内核签名用的公私钥找不到放哪里了。
然后RHEL(CentOS)需要开启epel-release。这方法网上很多这里就不写了。
所以执行过程是
3.1. 安装epel-release
方法略
3.2. 安装必要的软件包
执行下列命令
无需reboot,继续执行下一步。
4. 禁止nouveau
主要参考文档:Disabling Nouveau Drivers in RHEL 8
4.1. 修改grub参数
编辑/etc/default/grub
文件
找到GRUB_CMDLINE_LINUX
这行,在最后加入rd.driver.blacklist=nouveau modprobe.blacklist=nouveau nvidia-drm.modeset=1
内核模块黑名单的解说可以看这里
nvidia-drm.modeset=1的含义是enable DRM (Direct Rendering Manager) kernel mode setting
然后执行
sudo echo "blacklist nouveau" > /etc/modprobe.d/denylist.conf
sudo echo "options nouveau modeset=0" >> /etc/modprobe.d/denylist.conf
因为已经禁止了显卡驱动,所以重启自然进不了X,然后执行下列命令把下次登陆改为命令行
sudo systemctl set-default multi-user.target
改回图形界面的命令是
sudo systemctl set-default graphical.target
4.2. 重新生成initramfs
sudo dracut --force
4.3. 重建grub
MBR
UFEI
4.4. 重启
sudo systemctl reboot
5. 生成Machine Owner Key
主要参考https://gist.github.com/lijikun/22be09ec9b178e745758a29c7a147cc9这篇文章
我们这次是使用dkms这个工具来自动编译nvidia驱动模块,所以希望把dkms用自己的key来签名,这样可以把这个证书加到安全启动里去。
首先我们已经在命令行界面了,执行sudo -i 切换到root用户。接下来均在root用户下操作
创建/root/mok目录
5.1. 生成MOK公私钥
生成公私钥命令
openssl req -new -x509 \
-newkey rsa:2048 -keyout /root/mok/mok.key \
-outform DER -out /root/mok/mok.der \
-nodes -days 36500 -subj "/CN=MOK"
5.2. 用MOK导入内核
执行命令
mokutil --import /root/mok/mok.der
此时需要输入密码。密码是必须输入的,一定要记住这个密码。
5.3. 重启系统
- 选择 "Enroll MOK"
- 选择 "Continue"
- 选择 "Yes"
- 输入上面输入的密码
- 选择 "OK" 然后电脑会重启
5.4. 编辑/etc/dkms/framework.conf
把/root/mok/mok.key拷贝到/var/lib/dkms/mok.key,把/root/mok/mok.der拷贝到/var/lib/dkms/mok.der。权限不变。
在/etc/dkms/framework.conf最后加入(如果已经配置了mok_signing_key及mok_certificate则不适用)
mok_signing_key=/var/lib/dkms/mok.key
mok_certificate=/var/lib/dkms/mok.der
安全起见这里再重启一次。
6. 安装Nvidia驱动
将在Nvidia官方网站上下载的驱动标记成可执行文件
执行命令
chmod +x NVIDIA....run
sudo ./NVIDIA....run
问选择dkms管理的时候选择Yes
问是否要更新XOrg conf的时候选择No
然后就安装好了
7. 清理,重启
将SELinux改回最开始的状态。
安全启动还是关闭
执行sudo systemctl set-default graphical.target
然后重启系统
再进入系统后执行nvidia-smi
正常出结果即为安装正确