Intel GVT-gをProxmox VEで設定する:iGPUを複数の仮想マシンで同時共有する

Virtualization tutorial - IT technology blog
Virtualization tutorial - IT technology blog

背景:iGPUが遊んでいるのにCPUが悲鳴を上げているとき

私のホームラボはProxmox VEで12個のVMとコンテナを管理しています。ここはプロダクションに移す前にあらゆることをテストするための遊び場です。あるとき、VM上でJellyfinを動かしてH.265 4Kビデオをトランスコードしたくなったのですが、CPUソフトウェアトランスコードは恐ろしく遅く、クラスター全体のリソースを食い尽くしてしまいます。トランスコードだけのために別途GPUカードを購入するのは無駄ですし、ボードに挿しているIntel i7-8700のCPUにはUHD 630 iGPUがついていながら、まったく使われていない状態でした。

そこで出会ったのがIntel GVT-g(Graphics Virtualization Technology – graphics)です。通常のVFIOのように1つのVMにiGPU全体をパススルーするのではなく、GVT-gは1つの物理iGPUから複数の仮想vGPUを作成し、複数のVMで同時に共有できます。各VMは独立して動作する独自のグラフィックスデバイスを認識します。

ハードウェアの互換性について:GVT-gはIntel Broadwell(第5世代)以降をサポートしています。実際のところ、Skylake(第6世代、i-6xxxシリーズ)が安定しており十分なテストが行われています。それより古いボードは過度な期待を持つ前にまず試してみることをお勧めします。

GVT-gが適しているケース

  • VM上で動作するPlexまたはJellyfinでのハードウェアビデオトランスコード(H.264/H.265)
  • UIのレンダリングやオフィスグラフィックスアプリの実行のために軽いGPUが必要なWindows VM
  • ハードウェアアクセラレーション(WebGL、VA-API)が必要なLinuxデスクトップVM
  • 仮想化環境でのOpenCLアプリの開発・テスト

率直に言うと、GVT-gはゲーミングや重い3Dレンダリングには向いていません。それには専用GPUと完全なVFIOパススルーが必要です。GVT-gは軽度から中程度のワークロードに適しています。ホームラボにとっては、追加費用なしに既存ハードウェアを活用できる方法です。

開始前の環境準備

ハードウェアの確認

まず、ProxmoxホストがIntel iGPUを認識しているか確認します:

lspci | grep -i vga
# 期待される出力:
# 00:02.0 VGA compatible controller: Intel Corporation UHD Graphics 630 (rev 02)

# i915ドライバーがロードされているか確認
lsmod | grep i915

lspciの出力が表示されない場合は、BIOSでiGPUが無効になっていないか確認してください。専用GPUを挿すと自動的にiGPUを無効にするボードもあります。

ソフトウェア要件

  • Proxmox VE 7.xまたは8.x(kernel 6.2+の8.xを推奨)
  • Linux kernel 5.4以降(Proxmox VE 7はkernel 5.15、VE 8はkernel 6.2+を使用)

インストール:GVT-gをステップごとに有効化する

ステップ1:BIOS/UEFIでVT-dを有効にする

BIOSでVT-d(Intel Virtualization Technology for Directed I/O)の項目を探して有効にしてください。名称はボードによって異なりますが、通常はAdvanced CPU ConfigurationまたはChipset Settingsにあります。

ステップ2:カーネルパラメータを追加する

Proxmoxホストの/etc/default/grubファイルを編集します:

nano /etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULTの行を見つけて次のように変更します:

GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt i915.enable_gvt=1"

各フラグの役割:

  • intel_iommu=on — Intel IOMMU(VT-d)を有効にする
  • iommu=pt — パススルーモード、IOMMUが不要なデバイスのオーバーヘッドを削減
  • i915.enable_gvt=1 — i915ドライバーでGVT機能を有効にする
update-grub
reboot

ステップ3:必要なカーネルモジュールをロードする

再起動後、/etc/modulesにモジュールを追加します:

echo "kvmgt" >> /etc/modules
echo "vfio-mdev" >> /etc/modules
echo "mdev" >> /etc/modules

# 再起動なしで即時ロード
modprobe kvmgt
modprobe vfio-mdev
modprobe mdev

GVT-gが有効になっているか確認します:

dmesg | grep -i gvt
# 正常な出力:
# [    5.12] i915 0000:00:02.0: GVT-g enabled

# 作成可能なvGPUの種類を確認
ls /sys/bus/pci/devices/0000:00:02.0/mdev_supported_types/
# i915-GVTg_V5_1  i915-GVTg_V5_2  i915-GVTg_V5_4  i915-GVTg_V5_8

詳細設定:vGPUを作成してVMに割り当てる

適切なvGPUタイプの選択

ProxmoxにはVRAM容量と同時実行可能インスタンス数が異なる4種類のvGPUがあります:

  • i915-GVTg_V5_1 — VRAM 512MB、最大7インスタンス
  • i915-GVTg_V5_2 — VRAM 1GB、最大3インスタンス
  • i915-GVTg_V5_4 — VRAM 2GB、最大1インスタンス
  • i915-GVTg_V5_8 — VRAM 2GB(高解像度サポート)、1インスタンス

Jellyfinのトランスコード用には、2つのVMを並列で動かすためにV5_2(VRAM 1GB)を選択しました。十分な余裕があります。

vGPU(メディエイテッドデバイス)の作成

# vGPUのUUIDを生成
UUID1=$(uuidgen)
echo $UUID1
# 例: a297db4a-f4c2-11ee-b956-0242ac120002

# V5_2タイプのvGPUを作成
echo "$UUID1" > /sys/bus/pci/devices/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_2/create

# 作成を確認
ls /sys/bus/mdev/devices/
# a297db4a-f4c2-11ee-b956-0242ac120002

再起動のたびにvGPUが自動的に再作成されるよう、systemdサービスを作成します:

cat > /etc/systemd/system/gvt-g-create.service << 'EOF'
[Unit]
Description=Create Intel GVT-g vGPU devices
After=syslog.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c 'echo "a297db4a-f4c2-11ee-b956-0242ac120002" > /sys/bus/pci/devices/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_2/create'

[Install]
WantedBy=multi-user.target
EOF

systemctl enable --now gvt-g-create.service

ProxmoxでVMにvGPUを割り当てる

ProxmoxのVMの設定ファイルは/etc/pve/qemu-server/に格納されています。VM ID 100の場合:

nano /etc/pve/qemu-server/100.conf

次の行を追加し、UUIDを先ほど生成したものに置き換えてください:

hostpci0: 0000:00:02.0,mdev=a297db4a-f4c2-11ee-b956-0242ac120002

かなりの時間をかけてようやく分かった重要な点があります:VMはSeaBIOSi440fxマシンタイプを使用する必要があり、OVMF/UEFIやq35は使えません。GVT-gのレガシーモードはi440fxでのみ正常に動作します:

# VMの設定ファイルで確認
bios: seabios
machine: pc-i440fx-8.1

VMを起動して内部で確認します:

# Linux VM内で実行
lspci | grep -i vga
# 00:02.0 VGA compatible controller: Intel Corporation ...

# GPU情報を確認
vainfo
# libva info: VA-API version 1.x.x
# libva info: Trying to open /dev/dri/renderD128
# vainfo: VA-API version: 1.x (libva 2.x.x)
# vainfo: Driver version: Intel i965 driver

確認とモニタリング

ホストでのGPU使用状況の監視

# intel-gpu-toolsをインストール
apt install intel-gpu-tools

# リアルタイムのGPU使用状況
intel_gpu_top

# レジデンシーを確認(GPUが動作中かどうか)
cat /sys/class/drm/card0/gt/gt0/rc6_residency_ms

JellyfinがH.265 4Kをトランスコードしている際、intel_gpu_topでVCS engine(Video Codec)が60〜80%で動いているのが確認できます。これはソフトウェアではなくハードウェアトランスコードが機能している証拠です。

Jellyfinでハードウェアトランスコードを設定する

# jellyfinユーザーに/dev/driへの読み取り権限を付与
usermod -aG render,video jellyfin

# デバイスを確認
ls -la /dev/dri/
# crw-rw---- 1 root video   226, 0   card0
# crw-rw---- 1 root render  226, 128 renderD128

Jellyfin管理ダッシュボード → 再生 → トランスコーディングで、Intel QuickSync(QSV)を選択し、H.264、H.265、VP9を有効にしてください。

よくあるエラーと対処法

「GVT-g is not enabled」エラー — cat /proc/cmdlineを実行してパラメータi915.enable_gvt=1が含まれているか確認してください。見当たらない場合はupdate-grubが正しく実行されていません。

起動後にVMがGPUを認識しない — hostpciの行にx-vga=1を追加してみてください:hostpci0: 0000:00:02.0,mdev=UUID,x-vga=1。旧世代CPUではこのフラグが必要な場合があります。

Jellyfinが依然としてソフトウェアトランスコードを使用している — 9割がた権限エラーが原因です。journalctl -u jellyfin | grep driで具体的なエラーを確認し、usermod -aG render jellyfinを実行してサービスを再起動してください。

このセットアップを数週間運用した結果、VM上のJellyfinでのH.265 4Kトランスコードに使用するCPUはソフトウェアの100%から約15%まで削減され、クラスター全体が安定して動作しています。追加のGPU購入なしに既存ハードウェアを最大限活用できる方法です。

Share: