快轉到主要內容

設定Linux的Nvidia vGPU虛擬化,增強QEMU/KVM虛擬機圖形效能

Linux系統 虛擬機與容器技術 GPU Virtualization Nvidia
🗓️ 民國113年 甲辰年
✍ 切換正體/簡體字
目錄

現在我有Intel內顯 + Nvidia獨顯的電腦,如果要增強QEMU/KVM虛擬機圖形效能,我們會使用Nvidia GPU Passthrough的方式讓虛擬機使用顯示卡資源,再讓Intel內顯負責顯示畫面。

相關文章: Arch Linux如何將Nvidia GPU直通給Windows QEMU/KVM虛擬機

本文探討另一個作法:GPU虛擬化,透過Nvidia的vGPU技術,動態分配Nvidia顯示卡給QEMU/KVM虛擬機使用。

下圖是Nvidia官網的架構圖,與GPU Passthrough比起來,vGPU可以一對多,將顯示卡資源切分給多個虛擬機使用。且不需要把Nvidia顯示卡驅動加入開機黑名單,也不需要綁定VFIO裝置。

我目前的用法是在BIOS調整,由Intel內顯當作Linux電腦的主顯示卡,Nvidia顯示卡在旁納涼,這樣才不會因為意外操作而沒畫面。

vGPU啟用有點複雜,Nvidia不會讓一般人用vGPU的,你需要安裝給企業使用的專門驅動程式。且如果顯示卡不支援vGPU功能,你還得手動打patch。

支援vGPU的顯示卡列表請看 官方列表,Quadro可以直接用,我的是GeForce系列需要手動打patch。

1. 環境
#

  • Host OS:Arch Linux
  • Guest OS:Windows 11 23H2
  • 核心版本:6.6.11
  • QEMU版本:8.2.0
  • Libvirt版本:9.10.0
  • CPU:Intel i5-7400
  • GPU:Intel UHD 630
  • GPU:Nvidia GeForce GTX 1050 Ti
  • Nvidia驅動版本:535.129.03

2. 啟用IOMMU和VFIO
#

如果你有直通過GPU,請將之前做的步驟全撤銷。

  1. 編輯GRUB
sudo vim /etc/default/grub
  1. 啟用Intel的IOMMU功能
GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet intel_iommu=on iommu=pt"
  1. 編輯mkinitcpio.conf
sudo vim /etc/mkinitcpio.conf
  1. 設定開機載入vfio核心模組
MODULES=(vfio_pci vfio vfio_iommu_type1)
  1. 更新initramfs和GRUB,重開機
sudo mkinitcpio -p linux
sudo grub-mkconfig -o /boot/grub/grub.cfg
sudo reboot

3. 設定vGPU系統服務
#

vgpu_unlock-rs專案可以在系統跑一個解鎖vGPU功能的系統服務。

  1. 安裝編譯套件
sudo pacman -S git base-devel dkms linux-headers rust

yay -S mdevctl
  1. 用cargo編譯vgpu_unlock
su
cd /opt
git clone https://github.com/mbilker/vgpu_unlock-rs.git
cd vgpu_unlock-rs/
cargo build --release
  1. 編譯後啟動vgpu_unlock系統服務
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

4. 給顯示卡驅動打patch
#

這裡使用Nvidia官方run版本的驅動,應適用於大多數Linux發行版。

  1. 解除安裝目前的驅動程式,重開機
sudo pacman -R nvidia-dkms
  1. 啟用vGPU需要特製版的Nvidia Grid Driver,到 Nvidia官網註冊企業帳號才能下載Nvidia vgpu-kvm driver。不然你直接Goole搜尋nvidia-linux-x86_64-535.129.03-vgpu-kvm.run也能找到熱心網友提供的檔案,但風險自負就是。

  2. 我的是GeForce系列顯示卡,需要手動給.run檔案打patch。下載vgpu-proxmox專案提供的檔案,套用patch。

chmod +x nvidia-linux-x86_64-535.129.03-vgpu-kvm.run

git clone https://gitlab.com/polloloco/vgpu-proxmox.git

./NVIDIA-Linux-x86_64-535.129.03-vgpu-kvm.run --apply-patch vgpu-proxmox/535.129.03.patch
  1. 之後會得到NVIDIA-Linux-x86_64-535.129.03-vgpu-kvm-custom.run檔案,接著以DKMS模式安裝驅動
sudo ./NVIDIA-Linux-x86_64-535.129.03-vgpu-kvm-custom.run --dkms
  1. 更新initramfs
 sudo mkinitcpio -p linux
  1. 重開機,檢查Nvidia驅動狀況
nvidia-smi
  1. 檢查vgpu是否啟用
nvidia-smi vgpu

5. 建立vGPU mdev裝置
#

註:這一段我無法成功,卡在最後一段賦予UUID的部份,一直遇到「不適用的引數」錯誤。可能是Arch Linux核心太新了?換Ubuntu LTS比較好。

  1. 取得顯示卡PCI位址
lspci | grep NVIDIA
  1. 取得GPU在Virsh中的full identifier,例如這裡是pci_0000_01_00_0
virsh nodedev-list --cap pci| grep 01_00_0
  1. 取得domain, bus, slot, function資訊
virsh nodedev-dumpxml pci_0000_01_00_0 | egrep 'domain|bus|slot|function'

範例輸出:

<domain>0</domain>
    <bus>1</bus>
    <slot>0</slot>
    <function>0</function>
      <address domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
      <address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
      <address domain='0x0000' bus='0x01' slot='0x00' function='0x1'/>
  1. 列出可用設定檔(也可以用mdevctl types指令查看)
ls -l /sys/bus/pci/devices/0000:01:00.0

ls /sys/class/mdev_bus/0000:01:00.0/mdev_supported_types
  1. 賦予uuid
uuid1 = $(uuidgen)
echo $uuid1 > nvidia-286/create
  1. 如果賦予多個UUID,等同建立多個虛擬GPU,讓不同的虛擬機使用。

  2. 查看mdev裝置狀態

ls -l /sys/bus/mdev/devices/
  1. 如果要移除裝置就傳入1
echo 1 > /sys/bus/pci/devices/0000:01:00.0/填入UUID/remove

6. 修改vGPU overrides數值
#

編輯/etc/vgpu_unlock/profile_override.toml

控制要分配給虛擬機的VRAM大小,我這裡是設定2GB。你可以給多個虛擬機均分GPU。

# 全域設定
[profile.nvidia-286]
num_displays = 1
display_width = 1920
display_height = 1080
max_pixels = 2073600
cuda_enabled = 1
frl_enabled = 1
framebuffer = 0x74000000
framebuffer_reservation = 0xC000000

# 個別設定:mdev的UUID為vGPU mdev的UUID
[mdev.3613e491-7ff6-4e26-bab0-c6209306f0f4]
num_displays = 1
display_width = 1920
display_height = 1080
max_pixels = 2073600
cuda_enabled = 1
frl_enabled = 1
framebuffer = 0x74000000
framebuffer_reservation = 0xC000000

7. 將顯示卡分配給KVM虛擬機
#

  1. 安裝Libvirt和Windows 11虛擬機

  2. 編輯虛擬機,點選編輯XML

  3. </domain>之前加入段落,添加mdev裝置。UUID1即為剛剛給vGPU賦予的UUID

<hostdev mode="subsystem" type="mdev" managed="no" model="vfio-pci" display="on">
  <source>
    <address uuid="填入UUID1"/>
  </source>
</hostdev>
  1. 如果你無法添加mdev裝置,那就點選新增硬體 → 新增PCI,退回到直通GPU的作法。(如果這樣做,Nvidia顯示卡在分配給虛擬機後會從宿主機暫時「斷線」,所以你得準備內顯用於顯示螢幕)

  2. 開機後,Linux Guest安裝 Nvidia GRID driver;Windows Guest安裝 一般版驅動

  3. 執行 繞過Nvidia授權驗證的批次檔

  4. 確認虛擬機認得到驅動版本

參考資料
#

相關文章

QEMU/KVM虛擬機Nvidia雙GPU直通,Linux Host對Linux Guest
Linux系統 虛擬機與容器技術 GPU Passthrough QEMU Nvidia Linux
讓WSL Docker的OpenGL程式可以使用Windows GPU硬體加速
Linux系統 虛擬機與容器技術 Nvidia Windows Subsystem for Linux Docker
Windows 11 WSL2跑Linux桌面環境與圖形程式的方法,使用WSLg XWayland
Linux系統 虛擬機與容器技術 Windows Subsystem for Linux KDE Plasma GNOME

留言板

此處提供二種留言板。點選按鈕,選擇您覺得方便的留言板。要討論程式碼請用Giscus,匿名討論請用Disqus。

這是Giscus留言板,需要Github帳號才能留言。支援markdown語法,若要上傳圖片請貼Imgur連結。您的留言會在Github Discussions向所有人公開。

這是Disqus留言板,您可能會看到Disqus強制投放的廣告。有時留言可能會被系統判定需審核,導致延遲顯示,請見諒。