Featured image of post unRAID Nvidia vGPU使用教程

unRAID Nvidia vGPU使用教程

So, fxxk you NVIDIA😤

最近发现了一个很好用的相册备份软件immich,但是他的AI识别需要NVIDIA GPU,可惜我电脑上只有一块卡,需要直通给虚拟机做视频剪辑与转码工作,这下怎么办呢?

在网上找了半天,发现一个Nvidia显卡的虚拟化方案vGPU,类似于intel核显sr-iov,可以拆分物理显卡为多个虚拟化显卡,从而同时分配给docker和虚拟机使用,完美解决我的需求,可惜虚拟化显卡都有个弊端,那就是无法输出视频了,不过我的工作流也刚好不需要视频输出,完美😎

参考教程

感谢以下几位大佬们的教程!这篇文章算是我自己的一个记录,也把我踩的坑总结一下。

准备

  • unRAID系统
  • 合适的网络环境,需要访问github、docker hub、unRAID应用商店
  • BIOS开启VT-d / Above 4G Decoding / IOMMU之类跟直通相关的选项,我这边re-bar也开了,似乎没有问题
  • unRAID系统中不要绑定nvidia显卡,并且检查虚拟机是否有使用该显卡,把直通全部取消掉
  • 一块受支持的NVIDIA显卡,下表仅供参考,实测我的1650也是可以模拟为RTX 6000从而支持vGPU,但是30系及以上必不支持。
Nvidia card GPU Chip vGPU unlock profile
GTX 900 Series (first gen) GM107 x4 Tesla M10
GTX 900 series (second gen) GM204 x2 Tesla M60
GTX 1000 Series GP102 Tesla P40
Titan V, Quadro GV100 GV100 Tesla V100 16GB
RTX 1600/2000 Series TU102 Quadro RTX 6000
RTX 3000 Series GA10x Ampere isnot supported

安装相关插件

  1. 不要安装CA中有ich777大佬提供的Nvidia-Driver插件,这个插件安装的驱动无法使用vGPU。如果已安装请卸载。

  2. CA搜索安装User Scripts以及Dynamix File Manager,用于自动运行vGPU设置脚本,编辑配置文件

  3. 安装支持vGPU的NVIDIA驱动插件,该插件因为破解vGPU的原因无法通过CA审核,需要在插件-安装插件中手动输入链接进行安装。注意安装时会从github下载约500M的驱动文件,请确保网络连接正常,保持耐心等待,坐和放宽。

    1
    
    https://raw.githubusercontent.com/stl88083365/unraid-nvidia-vgpu-driver/master/nvidia-vgpu-driver.plg
    

    image-20240628214139856

  4. 终端运行此命令,告知由主机驱动程序管理设备;

    1
    
    echo "options nvidia cudahost=1" > /boot/config/modprobe.d/nvidia.conf
    
  5. 重启,此时去vgpu插件设置页面会显示一些错误,这应该是正常的,因为还没有设置脚本。可直接进入终端输入nvidia-smi确认显卡正常驱动。image-20240707171350904

    image-20240629162408496

设置vGPU拆分脚本

  1. 检查vGPU插件是否包含当前显卡型号

    这一步相对而言比较复杂,主要原因在于显卡太多,且即便是同一个型号的显卡其ID也不尽相同,因此开发者无法全部全面覆盖,如果运气不好碰到没有包含的显卡,需要自行添加相关配置文件,我自己摸索的办法如下:

    • 确认显卡支持vGPU破解,30系及以上均不支持;

    • 使用以下命令检查是否已在配置文件中,如果有输出则说明运气比较好,直接跳转第二步设置脚本,否则需要修改配置文件

      1
      
      mdevctl types
      
    • 在unraid-工具-系统设备中,定位到自己待设置的显卡,记住其ID,也就是下图红框中,以10de开始的内容,比如我的就是 10de:1f82image-20240707172602235

    • 执行以下命令,将配置文件复制到启动U盘的 config文件夹,方便在unraid网页进行可视化编辑。如果你熟悉命令行操作,也可直接命令行编辑,但是一定要复制到U盘中来,因为原始位置的配置文件每次启动系统后都会恢复。

      1
      
      cp /usr/share/nvidia/vgpu/vgpuConfig.xml /boot/config/
      
    • 进入unraid-主界面,进入Flash的文件管理器

      image-20240707173443268
    • 转到config文件夹,打开刚刚复制的 vgpuConfig.xml文件,在PCI\VEN_10DE - NVIDIA Corporation | Device Hunt中查找与自己型号较为接近的桌面端显卡ID,以我的1650为例子,在网站上搜索1660,查到其ID为2184,在 vgpuConfig.xml中搜索 0x2184,发现存在该型号的配置文件,故将 0x2184修改为我GTX1650的ID即 0x1f82。这个过程可能需要多找几次,但是肯定是可以找到的,修改后保存即可。<img src="assets/similar_gpu_id.png" alt="image-20240707182203146" style="zoom: 33%;" />image-20240707182542614

    • 将原始配置文件重命名,复制修改后的文件到原始位置

      1
      2
      
      mv /usr/share/nvidia/vgpu/vgpuConfig.xml /usr/share/nvidia/vgpu/vgpuConfig.xml.bak
      cp /boot/config/vgpuConfig.xml /usr/share/nvidia/vgpu/
      
  2. 修改脚本,进行诸如vGPU设置和配置文件修改等操作。脚本文件有四块地方需要修改

    1. 如需要使用自定义的 vgpuConfig.xml文件,请取消注释修改1处的相关代码;

    2. 定义虚拟机使用的vGPU的UUID,按下方vGPU的类型按需增删,分几个就用几个,uuid可用uuidgen命令创建,名字随意,注意在 arr的括号中也要有相同内容;

    3. 定义N卡的PCI位置,使用nvidia-smi或者去unraid-工具-系统设备中查看,一般只需要修改07为自己的显卡位置;image-20240707184151516

    4. 定义vGPU的类型。在Nvidia Vgpu Driver插件中或使用 medvctl types查询支持的模式。这里的型号选取是根据显存来的。以我的1650 4GB为例,我决定使用Q模式,并将其拆分为2个vGPU,则每个vGPU显存为4096MB÷2=2048MB,查找可知应选用 nvidia-257型号的vGPU类型。image-20240707184804759

    5. 修改完成的脚本如下:

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      
      #!/bin/bash
      
      ### 修改1:如果你需要使用自己修改的vgpuConfig.xml,请删除下列两行的“#”号以取消注释;
      # mv /usr/share/nvidia/vgpu/vgpuConfig.xml /usr/share/nvidia/vgpu/vgpuConfig.xml.bak
      # cp /boot/config/vgpuConfig.xml /usr/share/nvidia/vgpu/
      
      
      ### 修改2:定义虚拟机使用的vGPU的UUID,按下方vGPU的类型按需增删,分几个就用几个,uuid可用uuidgen命令创建,名字随意,注意在arr的括号中也要有相同内容
      windows="ae9572f6-1259-4136-9aa4-497dda98d2db"
      other="868bfe06-47c1-40a3-82df-ffd518be72d3"
      arr=( "${windows}" "${other}" )
      
      
      ### 修改3:定义N卡的PCI位置,使用nvidia-smi或者去unraid-工具-系统设备中查看,一般只需要修改07为自己的显卡位置
      NVPCI="0000:07:00.0"
      
      
      ### 修改4:定义vGPU的类型。在Nvidia Vgpu Driver插件中或使用medvctl types查询支持的模式。这里的型号选取是根据显存来的。以我的1650 4GB为例,我决定使用Q模式,并将其拆分为2个vGPU,则每个vGPU显存为4096MB÷2=2048MB,查找可知应选用nvidia-257型号的vGPU类型。
      MDEVLIST="nvidia-257"
      
      depmod -a
      nvidia-modprobe
      
      if [ ! -d /boot/config/nvidia-vgpu ]; then
      mkdir -p /boot/config/nvidia-vgpu
      fi
      
      if [ ! -d /etc/vgpu_unlock/ ]; then
      mkdir -p /etc/vgpu_unlock/
      fi
      
      if [ -f /boot/config/nvidia-vgpu/profile_override.toml ]; then
      ln -sf /boot/config/nvidia-vgpu/profile_override.toml /etc/vgpu_unlock/profile_override.toml
      else 
      touch /boot/config/nvidia-vgpu/profile_override.toml
      ln -sf /boot/config/nvidia-vgpu/profile_override.toml /etc/vgpu_unlock/profile_override.toml
      fi
      
      echo "unlock = false" > /etc/vgpu_unlock/config.toml
      
      env LD_PRELOAD=/usr/local/lib/libvgpu_unlock_rs.so >/dev/null
      
      if pgrep -x nvidia-vgpu-mgr > /dev/null
      then
      nvidia-vgpud stop
      nvidia-vgpu-mgr stop
      killall nvidia-vgpu-mgr
      fi
      LD_PRELOAD=/usr/local/lib/libvgpu_unlock_rs.so nvidia-vgpud 
      LD_PRELOAD=/usr/local/lib/libvgpu_unlock_rs.so nvidia-vgpu-mgr
      
      sleep 3
      
      for os in "${arr[@]}"; do
      if [[ "$(mdevctl list)" == *"$os"* ]]; then
      echo " [i] Found $os running, stopping and undefining..."
      mdevctl stop -u "$os"
      mdevctl undefine -u "$os"
      fi
      done
      
      for os in "${arr[@]}"; do
      echo " [i] Defining and running $os..."
      mdevctl define -u "$os" -p "$NVPCI" --type "$MDEVLIST"
      mdevctl start -u "$os"
      done
      
      echo " [i] Currently defined mdev devices:"
      mdevctl list
      
  3. 利用User Scripts添加脚本,并设置为 At First Array Start Only(第一次启动阵列时运行脚本)。image-20240707185705551

  4. 重启系统,启动阵列。如果一切顺利,则可以在Nvidia Vgpu Driver插件中正常显示所有内容。

配置虚拟机以及vGPU授权

  1. 本文以windows为例,首先正常添加一个windows虚拟机,并安装好系统,注意使用 SPICE而不是默认的 VNC作为虚拟显卡协议,因为 VNC和vGPU有冲突;image-20240707191432257

  2. 为虚拟机添加vGPU。这一步需要手动编辑虚拟机的xml文件,注意编辑xml后如果切换普通视图再编辑保存,则自定义的xml内容会消失,需重新编辑xml。

    • 切换为xml视图image-20240707190439751

    • 在配置文件最末尾,找到 </video>字符,在其后添加下列内容。有两处按需修改,其中,uuid为自己脚本中配置的UUID,slot中的数字比一定要和宿主机中的相同,如果在保存时提示创建虚拟机错误如 XML error: Attempted double use of PCI Address 0000:00:07.0,则可能是当前 slot 07 已经被其他设备占用,修改成任意不会起冲突的数字后保存即可。

      1
      2
      3
      4
      5
      6
      
          <hostdev mode='subsystem' type='mdev' managed='no' model='vfio-pci' display='off'>
            <source>
              <address uuid='868bfe06-47c1-40a3-82df-ffd518be72d3'/>
            </source>
            <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
          </hostdev>
      
  3. 启动虚拟机,安装驱动

  4. vGPU授权。为了能够正常使用vGPU,仅有驱动是不行的,还需要有NVIDIA的授权,但是消费级显卡是没有授权的,这就需要使用大佬们配置好的仿冒授权

    • UNRAID下载容器模板

      1
      
      wget -O /boot/config/plugins/dockerMan/templates/FastAPI-DLS.xml https://raw.githubusercontent.com/s1oz/unraid/master/fastapi-dls.xml
      
    • 在docker中添加容器,选择对应的模板,自行修改模板中DLS_URL变量的IP,然后启动;image-20240707223345834

    • 浏览器访问 https://容器IP:9443/-/client-token,会下载一个授权config文件,将该文件放入 C:\Program Files\NVIDIA Corporation\vGPU Licensing\ClientConfigToken文件夹中,没有文件夹新建一个就好。

  5. 重启,即可看到自动跳出的授权,此时所有功能均可使用,除了物理显示输出。

    vGPU-license

配置Emby docker

如果需要使用emby调用显卡进行解码,需要进行一些修改。

  • 编辑Emby docker配置,打开高级视图
  • 在额外参数中添加 --runtime=nvidiaimage-20240707224136655
  • 新建变量,名称随意,键为 NVIDIA_VISIBLE_DEVICES,值为 all<img src="assets/NVIDIA_VISIBLE_DEVICES.png" alt="image-20240707224039334" style="zoom:50%;" />
  • 启动容器web界面,进入设置-转码,勾选显卡即可image-20240707224252556

总结

  1. 该功能适合不需要物理输出,需要同时在虚拟机和docker中使用Nvidia独立显卡的用户进行使用
  2. 过程比较复杂,需要细致进行配置
  3. 玩的愉快🙌🙌
Licensed under CC BY-NC-SA 4.0