KVMやXenといったLinuxハイバーバイザ上のVMでGPUを使用する場合、GPUパススルーを用いてVM一つにGPUをまるごと渡してしまうのが個人ユースでは一般的です
GPUパススルーを用いた場合、VM一つがGPUを専有してしまうため、使用できるVMの数に制約があったり、そもそもノートPCのように物理的にGPUが増設できない環境が存在したりと制約が多いのが難点でした
これまでも一部のエンタープライズ向けGPUではGPUの共有機能はサポートされていましたが、最近のカーネル(実用レベルになってきたのは4.18ぐらいから)ではIntel GVT-gと呼ばれるIntel iGPUの共有機能が使えるようになってきました。
今回はopenSUSE Tumbleweedを用いてGVT-gによる複数VMでのGPU共有を行ってみます
テスト環境
現時点のカーネル(4.20)ではGVT-gはBroadwell〜KabyLakeまでのGPUしかサポートされていません
カーネル4.21(仮)でCoffeeLakeに対応する予定(Intelがプルリク投げている)です
ということで、SkyLake世代のノートPCでテストしてみました
大須のPCコンフルの初売りで29800円でしたが、SkyLake世代の中古PCも値頃になってきましたね
- DELL Latitude E5470
- CPU: Intel Core i5 6200U
- GPU: Intel UHD Graphics 520
- Mem: 8GB
- OS: openSUSE Tumbleweed x86_64
- qemu: 3.1.0
とりあえずYaSTなりでvirt-manager経由でVMの制御が行えていることを前提とします
initramfsへのモジュール展開
まずはGVT-gを使うために必要なカーネルモジュールの準備をします。
ブート時点で関連モジュールが必要になるため、dracut.confに必要なモジュールを列挙してinitramfsに突っ込んでおきます
1 | # echo "drivers+=\"kvmgt vfio-iommu-type1 vfio-mdev\"" > /etc/dracut.conf.d/98-gvtg.conf |
kvmgtとvfio-mdevが今回のキーモジュールです
カーネルパラーメータの設定
YaST > システム > ブートローダーを呼び出し、カーネルパラメータに1
i915.enable_gvt=1 kvm_ignore_msrs=1 intel_iommu=1
を追加し、GVT-gを有効にします
設定後、再起動して
1 | $sudo lspci |
でGPUのPCIアドレスを確認したら
1 | ls /sys/device/[GPUのPCIアドレス]/mdev_supported_types/ |
で使える共有GPUの一覧が取れたら成功です1
2$ ls /sys/devices/pci0000\:00/0000\:00\:02.0/mdev_supported_types/
i915-GVTg_V5_4 i915-GVTg_V5_8
1 | cat /sys/device/[GPUのPCIアドレス]/mdev_supported_types/[出てきた共有GPU]/description |
で共有GPUの詳細を確認できますので確認しておきます
1 | $ cat /sys/devices/pci0000\:00/0000\:00\:02.0/mdev_supported_types/i915-GVTg_V5_4/description |
fenceとweightに注目してください
- fence = この環境で使える最大共有GPU枠
- weight = この共有GPU一つで専有する共有GPU枠
なので、今回の環境では1920x1080、VRAM128MB〜512MBが1枚、もしくは1024x768、VRAM64MB〜384MBが2枚取れることがわかります
共有GPUの確保と開放
共有GPUを確保するためには1
echo '[任意のUUID]' > /sys/devices/[GPUのPCIアドレス]/mdev_supported_types/[共有GPU]/create
を行います。成功すれば1
ls /sys/device/[GPUのPCIアドレス]/
でデバイスディレクトリ下に与えたUUIDのディレクトリが登場します。1
2
3
4
5
6
7
8
9$ ls -l /sys/devices/pci0000\:00/0000\:00\:02.0/
合計 0
drwxr-xr-x 4 root root 0 1月 23 04:14 ab8c3af8-8366-449d-8489-fe9254e44621 ←こいつ
-r--r--r-- 1 root root 4096 1月 23 04:14 ari_enabled
-r--r--r-- 1 root root 4096 1月 23 04:14 boot_vga
-rw-r--r-- 1 root root 4096 1月 23 04:14 broken_parity_status
-r--r--r-- 1 root root 4096 1月 23 04:14 class
-rw-r--r-- 1 root root 4096 1月 23 04:14 config
〜以下略〜
確保した共有GPUを開放するには1
echo '1' > /sys/devices/[GPUのPCIアドレス]/[確保の時使ったUUID]/remove
を行います
UUIDはuuidgenなりで適当に決めてください
サービス化
システム起動時に共有GPUを自動で確保できるようにsystemdサービスを作ります
/usr/lib/systemd/systemの下に任意のサービス名でserviceファイルを作ります
今回はgvtgpu.serviceということで
1 | $ cat /usr/lib/systemd/system/gvtgpu.service |
↑のような感じで作りました
これで1
sudo systemctl start gvtgpu
で確保され1
sudo systemctl stop gvtgpu
で開放され1
sudo systemctl enable gvtgpu
で起動時に自動確保されるようになります
私の場合ですが、
- UUIDその1でi915-GVTg_V5_4を確保するgvtgpu.service
- UUIDその1でi915-GVTg_V5_8を確保するgvtgpu2.service
- UUIDその2でi915-GVTg_V5_8を確保するgvtgpu3.service
の3つを作り、1枚確保の時はgvtgpuを、2枚確保の時はgvtgpu2と3をenableにする。という運用を行っています
とりあえずここまでとし、実際のVMに適用してみる部分はその2にてで
(続く)