在 Proxmox VE 上使用 Nvidia vGPU

前言

前幾週在中國的二手平台上看到了很便宜的 Nvidia Tesla P4,由於 Tesla P4 是半高單槽顯示卡,又不需要額外插電,非常適合放在 1U 伺服器上做使用,於是就買了幾張來測試 vGPU 看看。本篇將會介紹如何在 Proxmox VE 上使用 Nvidia 的 vGPU 功能。

vGPU 技術

先前一直對 vGPU 技術還蠻有興趣的,尤其是 AMD 號稱是開源且只要硬體支援就可以使用的 MxGPU 技術。但是在獲得一張 AMD Instinct MI25 後,卻發現開源的驅動程式只有支援到古老的 S7150,連不開源的驅動程式也沒有發布下載,只有大間的雲端廠商如 Microsoft Azure、阿里雲等才能夠獲得。在經過各種 patching 後 kernel driver 還是沒辦法正常運作,於是那張卡就被我放置在倉庫了。

Nvidia 自己獨有的 GRID 技術則是沒有開源,但是只需要註冊帳號就可以下載到驅動程式,這點相較於 AMD 我覺得是做得好很多。
至於運作的方式,AMD 的 MxGPU 是使用 SR-IOV,而 Nvidia GRID 在這張 Tesla P4 是用 mdev 的方式做 vGPU passthrough。

接下來我們進入正題來介紹如何在 Proxmox VE 上使用 Nvidia vGPU。

前置設定

首先我們先加入 Proxmox VE 的 community repo 並且移除 enterprise repo

echo "deb http://download.proxmox.com/debian/pve bullseye pve-no-subscription" >> /etc/apt/sources.list
rm /etc/apt/sources.list.d/pve-enterprise.list

更新並升級

apt update
apt dist-upgrade

安裝一些需要的軟體套件

apt install -y git build-essential dkms pve-headers mdevctl

安裝並設定 vgpu_unlock

vgpu_unlock 是一個開源在 GitHub 上面的工具,能夠讓你在 Geforce 跟 Quadro 卡上面也能使用原先在 Tesla 跟一些 Quadro 顯示卡上面才能用的 Nvidia vGPU 技術。

Tesla P4 是不需要使用 vgpu_unlock 就可以運作的,但是它提供了一些可以覆蓋原先 mdev 設定的功能,在這個只有 7680MB 記憶體的顯示卡上還蠻實用的。

首先先把需要的 GitHub repo clone 下來

git clone https://gitlab.com/polloloco/vgpu-proxmox.git
cd /opt
git clone https://github.com/mbilker/vgpu_unlock-rs.git

安裝 Rust compiler

curl https://sh.rustup.rs -sSf | sh -s -- -y

將 Rust binaries 加入 PATH 中

source $HOME/.cargo/env

編譯

cd vgpu_unlock-rs/
cargo build --release

建立一些需要的設定檔,讓 Nvidia vGPU service 在啟動的時候會讀取 vgpu_unlock library

mkdir /etc/vgpu_unlock
touch /etc/vgpu_unlock/profile_override.toml
mkdir /etc/systemd/system/{nvidia-vgpud.service.d,nvidia-vgpu-mgr.service.d}
echo -e "[Service]\nEnvironment=LD_PRELOAD=/opt/vgpu_unlock-rs/target/release/libvgpu_unlock_rs.so" > /etc/systemd/system/nvidia-vgpud.service.d/vgpu_unlock.conf
echo -e "[Service]\nEnvironment=LD_PRELOAD=/opt/vgpu_unlock-rs/target/release/libvgpu_unlock_rs.so" > /etc/systemd/system/nvidia-vgpu-mgr.service.d/vgpu_unlock.conf

如果像我一樣是使用本來就支援 vGPU 的顯示卡如 Tesla 系列的顯示卡,把 unlock 功能關閉避免增加不必要的複雜性

echo "unlock = false" > /etc/vgpu_unlock/config.toml

載入需要的 kernel module 跟黑名單不需要的

vGPU 要運作會需要 vfio, vfio_iommu_type1, vfio_pcivfio_virqfd 這幾個 kernel module

echo -e "vfio\nvfio_iommu_type1\nvfio_pci\nvfio_virqfd" >> /etc/modules

然後要黑名單開源的 Nvidia 驅動程式

echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf

重新啟動

reboot

Nvidia Driver

在撰寫這篇文章的時候 (2022 12 月),目前最新的 GRID driver 是 15.0 版本並且搭配 vGPU driver 525.60.12。你可以在這邊看到最新的版本。新版本可能會需要其他額外的 patch 才能使用。

獲得 driver

Nvidia GRID driver 沒有公開下載,但是你可以透過 NVIDIA Licensing Portal 註冊並寫下載試用版本。

注意在註冊得時候如果使用免費的 email 提供商的 email 會需要透過人工認證才能註冊成功,請使用自己 domain 的 email。

下載完成後,解壓縮並上傳到伺服器上

scp NVIDIA-Linux-x86_64-525.60.12-vgpu-kvm.run root@pve:/root/

有支援 vGPU 的 GPU

如果你的顯示卡本身就支援 vGPU,直接安裝驅動程式即可,不需要 patching

chmod +x NVIDIA-Linux-x86_64-525.60.12-vgpu-kvm.run
./NVIDIA-Linux-x86_64-525.60.12-vgpu-kvm.run --dkms

安裝後重啟

reboot

不支援 vGPU 的 GPU

使用不支援 vGPU 的顯示卡,如 Geforce 系列,必須對驅動程式進行 patching

chmod +x NVIDIA-Linux-x86_64-525.60.12-vgpu-kvm.run
./NVIDIA-Linux-x86_64-525.60.12-vgpu-kvm.run --apply-patch ~/vgpu-proxmox/525.60.12.patch

應該會 output 以下訊息

Self-extractible archive "NVIDIA-Linux-x86_64-525.60.12-vgpu-kvm-custom.run" successfully created.

接下來安裝 driver

./NVIDIA-Linux-x86_64-525.60.12-vgpu-kvm.run --dkms

安裝後重啟

reboot

最後檢查

安裝重新啟動後,輸入此指令

nvidia-smi

應該會得到類似這樣的輸出

Fri Dec  9 22:57:28 2022
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.60.12    Driver Version: 525.60.12    CUDA Version: N/A      |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla P4            On   | 00000000:86:00.0 Off |                    0 |
| N/A   36C    P8    10W /  75W |     27MiB /  7680MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

然後確認 vGPU mdev 存在

mdevctl types

輸出會像這樣

  nvidia-69
    Available instances: 2
    Device API: vfio-pci
    Name: GRID P4-4A
    Description: num_heads=1, frl_config=60, framebuffer=4096M, max_resolution=1280x1024, max_instance=2
  nvidia-70
    Available instances: 1
    Device API: vfio-pci
    Name: GRID P4-8A
    Description: num_heads=1, frl_config=60, framebuffer=8192M, max_resolution=1280x1024, max_instance=1
  nvidia-71
    Available instances: 8
    Device API: vfio-pci
    Name: GRID P4-1B
    Description: num_heads=4, frl_config=45, framebuffer=1024M, max_resolution=5120x2880, max_instance=8

也可以透過 nvidia-smi 檢查

nvidia-smi vgpu
Fri Dec  9 22:58:03 2022
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.60.12              Driver Version: 525.60.12                 |
|---------------------------------+------------------------------+------------+
| GPU  Name                       | Bus-Id                       | GPU-Util   |
|      vGPU ID     Name           | VM ID     VM Name            | vGPU-Util  |
|=================================+==============================+============|
|   0  Tesla P4                   | 00000000:86:00.0             |   0%       |
+---------------------------------+------------------------------+------------+

vGPU overrides

在前面我們建立 /etc/vgpu_unlock/profile_override.toml 這個檔案,這個檔案是用來做 vGPU override 的,由於 Tesla P4 只有 7680MiB 的記憶體,在預設 4GB mdev 底下我們只能建立 1 個 vGPU,於是我們就可以用 vGPU override 來更改 mdev 的 VRAM 數值。

以下為範例:

[profile.nvidia-259]
num_displays = 1          # Max number of virtual displays. Usually 1 if you want a simple remote gaming VM
display_width = 1920      # Maximum display width in the VM
display_height = 1080     # Maximum display height in the VM
max_pixels = 2073600      # This is the product of display_width and display_height so 1920 * 1080 = 2073600
cuda_enabled = 1          # Enables CUDA support. Either 1 or 0 for enabled/disabled
frl_enabled = 1           # This controls the frame rate limiter, if you enable it your fps in the VM get locked to 60fps. Either 1 or 0 for enabled/disabled
framebuffer = 0x76000000  # VRAM size for the VM. In this case its 2GB
                          # Other options:
                          # 1GB: 0x3B000000
                          # 2GB: 0x76000000
                          # 3GB: 0xB1000000
                          # 4GB: 0xEC000000
                          # 8GB: 0x1D8000000
                          # 16GB: 0x3B0000000
                          # These numbers may not be accurate for you, but you can always calculate the right number like this:
                          # The amount of VRAM in your VM = `framebuffer` + `framebuffer_reservation`
[mdev.00000000-0000-0000-0000-000000000100]
frl_enabled = 0
# You can override all the options from above here too. If you want to add more overrides for a new VM, just copy this block and change the UUID

[profile.nvidia-259] 會覆蓋所有使用 nvidia-259 這個 mdev 的 VM,而 [mdev.00000000-0000-0000-0000-000000000100] 只會對 UUID 00000000-0000-0000-0000-000000000100 的 VM 作用。

讓 Proxmox VM 使用 vGPU

只需要在 command line 做一件事就可以讓 Proxmox VM 使用 vGPU:那就是給 VM 一個 UUID

vim /etc/pve/qemu-server/<VM-ID>.conf

在最後面加上一個隨機的 UUID,或是使用 VM ID

args: -uuid 00000000-0000-0000-0000-00000000XXXX

如 VM ID 1000 我們就可以用

args: -uuid 00000000-0000-0000-0000-000000001000

接下來我們可以在 Proxmox VE UI 中操作,選擇你的 VM,進入 Hardware,加入 PCI device,選擇你要使用的 GPU。這個 GPU 在 Mediated Devices 這行應該是顯示 Yes。選擇後你應該還可以選擇 MDev Type,從中挑選你要使用的 mdev

接下來開機並且安裝 driver,安裝完成後可以將內建的 Display 設成 none (none),接下來所有視訊輸出都會透過 vGPU 進行運算。注意更改後內建的 Proxmox console 將會無法使用,請確認你有可以遠端連線至 VM 的方法在進行更改。

Reference

https://gitlab.com/polloloco/vgpu-proxmox#adding-a-vgpu-to-a-proxmox-vm