GPU-PVは生のPCIデバイスを見せるのではなく、ゲスト側の準仮想化ドライバを通して、ホスト側のGPUドライバにアクセスさせる機能と理解
ゲスト側がWindowsならフル機能を活用できそうだが、Linuxの場合はCUDAが利用できるにとどまる(十分だけど)
モチベーション
Discordで運用中であるTTSBotの音声変換をVOICEVOXエンジン(GPU版)で処理している
処理は基本的にHyper-V上の仮想マシン側だが、GPUを使う関係で音声変換は物理マシンで処理している
なんか気持ち悪いので仮想マシンでVOICEVOXエンジン(GPU版)を使う方法を模索する
環境
- CPU:Intel(R) Core(TM) i7-13700T
- Mem:32GB
- GPU:NVIDIA T1000 8GB
- OS(Host):Windows 11 Pro (23H2)
- OS(Guest):Ubuntu Server 24.04
Hyper-V上で使えそうな技術
- RemoteFX → セキュリティ上の理由で廃止
- DDA (PCIEレベルのパススルー) → なんかうまくいかなかった
- GPU-PV → うまくいった!
Hyper-Vの仮想マシン(Ubuntu)の設定
- VMの世代:第二世代
- セキュアブート:無効
- 動的メモリ:無効
- チェックポイント:無効
- 自動停止アクション:シャットダウン
セキュアブートは後述の準仮想ドライバを組み込む関係で無効にする
他はホスト機側のGPUのVRAMの状態を保持することができないからだろうか?
Ubuntu Server24.04 導入
インストーラに従って粛々と実施
GPU-PV 有効化(ホスト側 Powershell)
ゲスト側はシャットダウンしておく
# デバイスファイルパス名の取得
Get-VMHostPartitionableGpu | Format-Table Name
# GPU-PVの設定
Add-VMGpuPartitionAdapter -VMName "仮想マシン名" -InstancePath "デバイスファイルパス名"
Set-VMGpuPartitionAdapter -VMName "仮想マシン名" -Passthru #リソース制限はかけずに割り当て
Set-VM -GuestControlledCacheTypes $true -VMName "仮想マシン名"
Set-VM -LowMemoryMappedIoSpace 3GB -VMName "仮想マシン名"
Set-VM -HighMemoryMappedIoSpace 32GB -VMName "仮想マシン名"
# Get-VMGpuPartitionAdapter -VMName "仮想マシン名" で過去設定のゴミが残ってたら、
# Remove-VMGpuPartitionAdapter -VMName "仮想マシン名"で一旦全部掃除すること
ドライバ導入(ホスト側 Powershell)
参考:
https://github.com/staralt/dxgkrnl-dkms
ゲスト側は起動しておく
$username="user name(ubuntu)"
$ip="ip address(ubuntu)"
# Create a destination folder.
ssh ${username}@${ip} "mkdir -p ~/wsl/drivers; mkdir -p ~/wsl/lib;"
# Copy driver files
# https://github.com/brokeDude2901/dxgkrnl_ubuntu/blob/main/README.md#3-copy-windows-host-gpu-driver-to-ubuntu-vm
(Get-CimInstance -ClassName Win32_VideoController -Property *).InstalledDisplayDrivers | Select-String "C:\\Windows\\System32\\DriverStore\\FileRepository\\[a-zA-Z0-9\\._]+\\" | foreach {
$l=$_.Matches.Value.Substring(0, $_.Matches.Value.Length-1)
scp -r $l ${username}@${ip}:~/wsl/drivers/
}
scp -r C:\Windows\System32\lxss\lib ${username}@${ip}:~/wsl/
ドライバ導入(ゲスト側 bash)
sudo mv ~/wsl /usr/lib/wsl
sudo chmod -R 555 /usr/lib/wsl
sudo chown -R root:root /usr/lib/wsl
sudo sh -c 'echo "/usr/lib/wsl/lib" > /etc/ld.so.conf.d/ld.wsl.conf'
ldsoconf
curl -fsSL https://content.staralt.dev/dxgkrnl-dkms/main/install.sh | sudo bash -es
# 確認
/usr/lib/wsl/lib/nvidia-smi
# /usr/lib/wsl/lib内のsoファイルのシンボリックリンクを正しく作成してやらないとエラーになるかもしれない
VOICEVOXエンジン導入
version-0.20.0を導入
cd /opt
sudo wget https://github.com/VOICEVOX/voicevox_engine/releases/download/0.20.0/voicevox_engine-linux-nvidia-0.20.0.7z.001
sudo wget https://github.com/VOICEVOX/voicevox_engine/releases/download/0.20.0/voicevox_engine-linux-nvidia-0.20.0.7z.002
sudo apt-get install -y p7zip-full
sudo 7z x voicevox_engine-linux-nvidia-0.20.0.7z.001
sudo mv linux-nvidia/ voicevox
systemctlサービス登録
sudo vi /etc/systemd/system/voicevox.service
[Unit]
Description=Voicevox Service
After=network.target
[Service]
User=root
Group=root
WorkingDirectory=/opt/voicevox
ExecStart=/opt/voicevox/run --host=0.0.0.0 --port=50021 --use_gpu --load_all_models
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl enable voicevox
sudo systemctl start voicevox
さいごに
ひとまず、Ubuntuの仮想マシンがVOICEVOX(CUDA版)のAPIサーバーとして動作した
ホストであるWindows上のタスクマネージャーからもGPUを使用していることを確認できた
しばらく運用してみて問題が出ないか様子を見ることとする
参考
https://qiita.com/Hyper-W/items/e189790fd4534d9d51ad
https://qiita.com/Hyper-W/items/5ddfc93891f7b620da8a
https://ascii.jp/elem/000/004/019/4019541/