対象:
- Host: Windows 11 Pro
- Hypervisor: Hyper-V Manager
- Guest: Ubuntu 24.04 Server
- GPU: NVIDIA GTX 1660 Ti
この手順は Hyper-V 上の Linux VM で GPU-PV を実験的に構成する手順です。 Microsoft の GPU partitioning の公開情報は主に Windows Server 2025 を中心としており、クライアント OS 上の Linux VM については明確な正式手順が薄いです。
また、多くの記事ではHyper-V ≒ WSL2へのGPU-PV環境という内容が多く、
たとえば VMとして複数のマシンを建てたい というユースケースの場合、
WSL2上で構築するのはなんだかなぁという方もいると思います。(筆者がそう)
そこで、改めてですが今回の手順は Hyper-V上の Linux VM で GPU-PV を構成する 手順になります。
0. 前提
この手順の前提は以下です。
- Host 側で
Get-VMHostPartitionableGpuにより GPU が見えていること - WSL2 側ではすでに GPU が利用できる状態であること
- Guest 側では Linux 用 NVIDIA ドライバを入れないこと
- Guest 側では WSL 由来の
dxgkrnl/ ライブラリ / DriverStore を流用すること
特に重要なのは、まずは公式通りWSL2上でGPUが利用できる状態まで持っていけてる環境であることです。
この手順で動作確認ができていなければ、今回の手順でも難しい場合があります。
NVIDIA の WSL ガイドでも、WSL 系構成では Windows 側ドライバを使い、Guest 側に Linux 用 display driver を入れない前提になっています。
1. [Host側] GPU Partition が見えることを確認
管理者 PowerShell で以下を実行します。
Get-VMHostPartitionableGpu | Format-List Name,ValidPartitionCounts,PartitionCount
期待値の例:
Name : \\?\PCI#VEN_10DE&DEV_....
ValidPartitionCounts : {32}
PartitionCount : 32
これで GPU が見えていれば、Host 側の入口は通っています。
Microsoft の GPU partitioning 手順でも、まず partitionable GPU が見えることが前提です。
2. [Host側] Hyper-V VM を作成
以下の条件で VM を作成します。
- Generation 2
- Secure Boot: OFF
- Dynamic Memory: OFF
- Checkpoints: Disabled
- Ubuntu 24.04 Server
- ネットワークは任意の vSwitch を利用
PowerShell 例
$VMName = "gpu-ubuntu"
$VHDPath = "D:\Hyper-V\$VMName\$VMName.vhdx"
$ISOPath = "D:\ISO\ubuntu-24.04-live-server-amd64.iso"
$VMSwitch = "ExternalSwitch"
New-VM -Name $VMName `
-Generation 2 `
-MemoryStartupBytes 8GB `
-NewVHDPath $VHDPath `
-NewVHDSizeBytes 80GB `
-SwitchName $VMSwitch
Set-VMProcessor -VMName $VMName -Count 4
Set-VMMemory -VMName $VMName -DynamicMemoryEnabled $false
Set-VMFirmware -VMName $VMName -EnableSecureBoot Off
Set-VM -VMName $VMName -CheckpointType Disabled -AutomaticStopAction ShutDown
Add-VMDvdDrive -VMName $VMName -Path $ISOPath
追加設定
Set-VM -VMName $VMName `
-LowMemoryMappedIoSpace 3GB `
-HighMemoryMappedIoSpace 32GB `
-GuestControlledCacheTypes $true
この手順は必須ではないですが、コミュニティの多くがこの手順を入れているため、今回もいれています。
3. [Guest側] Ubuntu 24.04 をインストールし、SSH を有効化
ここは通常のUbuntuインストールです。
インストール完了後、以下を実行します。
※ この時点では sudo apt upgrade はしないように。してもいいかもしれないですが、筆者は全ての手順が完了してからアップグレードしました。
sudo apt update
sudo apt install -y openssh-server
sudo systemctl enable --now ssh
ip a
また、手順簡素化/権限エラー周りを防ぐため、この手順ではrootログインでの作業としています。
一時的にrootログインを許可しておきます。
sudo su
echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config
systemctl restart ssh
Host 側から root で SSH できることを確認します。
ssh root@<vm_ip>
4. [Host側] GPU Partition Adapter を VM に追加
管理者 PowerShell で以下を実行します。
$VMName = "gpu-ubuntu"
# VM停止
Stop-VM -Name $VMName -Force
# 念のため既存アダプタ設定を削除 (何度も試してたので古いのが残ってる場合がある)
Remove-VMGpuPartitionAdapter -VMName $VMName -ErrorAction SilentlyContinue
# アダプタ追加
Add-VMGpuPartitionAdapter -VMName $VMName
# GPU-PV詳細設定
Set-VMGpuPartitionAdapter -VMName $VMName -MinPartitionVRAM 1
Set-VMGpuPartitionAdapter -VMName $VMName -MaxPartitionVRAM 900000000
Set-VMGpuPartitionAdapter -VMName $VMName -OptimalPartitionVRAM 900000000
Set-VMGpuPartitionAdapter -VMName $VMName -MinPartitionEncode 1
Set-VMGpuPartitionAdapter -VMName $VMName -MaxPartitionEncode 1
Set-VMGpuPartitionAdapter -VMName $VMName -OptimalPartitionEncode 1
Set-VMGpuPartitionAdapter -VMName $VMName -MinPartitionDecode 1
Set-VMGpuPartitionAdapter -VMName $VMName -MaxPartitionDecode 1
Set-VMGpuPartitionAdapter -VMName $VMName -OptimalPartitionDecode 1
Set-VMGpuPartitionAdapter -VMName $VMName -MinPartitionCompute 1
Set-VMGpuPartitionAdapter -VMName $VMName -MaxPartitionCompute 1
Set-VMGpuPartitionAdapter -VMName $VMName -OptimalPartitionCompute 1
# 確認
Get-VMGpuPartitionAdapter -VMName $VMName | Format-List InstancePath,PartitionId,PartitionVfLuid
この時点では InstancePath や PartitionId が空になっていると思いますが、
VMを起動すれば値が入ります。
VM起動後に再確認
一度 VM を起動してから再確認します。
Start-VM -Name $VMName
Get-VMGpuPartitionAdapter -VMName $VMName | Format-List InstancePath,PartitionId,PartitionVfLuid,Id
期待値の例:
InstancePath : \\?\PCI#VEN_10DE&DEV_....
PartitionId : 1
PartitionVfLuid : xxxxxxxxxx
Id : Microsoft:....
トラブルシュート
-
Add-VMGpuPartitionAdapter実行直後にInstancePathが空でも、起動後に埋まることがある - 起動後も空のままなら、
-InstancePathを明示して再追加する -
Get-VMHostPartitionableGpuで見えている GPU を使っているか確認する
Microsoft の手順でも、追加後に VM を起動して partition が解決される流れです。
5. [Host側] GPU 関連ファイルを集める
Host 側に staging 用フォルダを作成します。
$Stage = "C:\Temp\gpup-files"
Remove-Item $Stage -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Path $Stage | Out-Null
New-Item -ItemType Directory -Path "$Stage\wsl-lib" | Out-Null
New-Item -ItemType Directory -Path "$Stage\lxss-lib" | Out-Null
New-Item -ItemType Directory -Path "$Stage\driverstore" | Out-Null
WSL 由来ライブラリをコピーします。
Copy-Item "C:\Program Files\WSL\lib\*" "$Stage\wsl-lib\" -Recurse -Force
Copy-Item "C:\Windows\System32\lxss\lib\*" "$Stage\lxss-lib\" -Recurse -Force
NVIDIA の DriverStore ディレクトリを丸ごとコピーします。
※最新のDriverがわかれば1つのみでいいですが、確実に動かすことを優先したため丸ごとコピーしてます。
$NvDir = (Get-ChildItem "C:\Windows\System32\DriverStore\FileRepository" -Directory |
Where-Object { $_.Name -like "nv*.inf_amd64*" } |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1).FullName
Copy-Item $NvDir "$Stage\driverstore\" -Recurse -Force
6. [Host側] scp で Host -> Guest へ転送
scp -r C:\Temp\gpup-files root@<vm_ip>:~/
7. [Guest側] dxgkrnl-dkms の前提パッケージを入れる
scp でホスト側からコピーしたstagingディレクトリがあるか確認しておきます。
cd /root
find . -maxdepth 2 -type d | sort
stagindディレクトリ(gpup-files)の中に、driverstore,lxss-lib,wsl-libがあればOK。
.
./.cache
./gpup-files
./gpup-files/driverstore
./gpup-files/lxss-lib
./gpup-files/wsl-lib
./.ssh
確認後、 dxgkrnl-dkms の前提パッケージをインストールします。
sudo apt update
sudo apt install -y curl git dkms dwarves build-essential linux-headers-$(uname -r)
uname -r
8. [Guest側] dxgkrnl-dkms を導入
curl -fsSL https://content.staralt.dev/dxgkrnl-dkms/main/install.sh | bash -es
スクリプトの実行が完了したら、ここで再起動します。
reboot
9. [Guest側] WSL ライブラリを適切な位置に配置
再起動後、以下を実行します。
mkdir -p /usr/lib/wsl/lib
cp -a /root/gpup-files/wsl-lib/. /usr/lib/wsl/lib/
cp -a /root/gpup-files/lxss-lib/. /usr/lib/wsl/lib/
chmod 755 /usr/lib/wsl/lib
DriverStore もいったんコピーします。
sudo mkdir -p /opt/hostdriverstore
sudo cp -a /home/<ubuntu_user>/gpup-files/driverstore/. /opt/hostdriverstore/
※DriverStoreのコピー先は一度作業用(/opt/hostdriverstore)に移しています。
あとで再度移動しますが、こうしておくとこの後のトラシューがしやすくなり、
かつ"Driverが見当たらない"エラーまで見えればほぼ完了したも同然の状態と判断できるためです。
10. [Guest側] dxgkrnl の動作確認
ls -l /dev/dxg
dmesg | grep -i -E 'dxg|dxcore|hyperv|vmbus'
dkms status
期待値:
-
/dev/dxgが存在する -
dmesgにdxgkrnlの登録ログが出る -
dkms statusにdxgkrnlが出る
例:
rw-rw-rw- 1 root root 10, 263 Apr 19 23:10 /dev/dxg <- /dev/dxgが存在する
[ 0.000000] Hypervisor detected: Microsoft Hyper-V
:
[ 1.972837] hv_vmbus: registering driver dxgkrnl <- dxgkrnlが登録されている
dxgkrnl/6.6-a07f9ea8a, 6.8.0-110-generic, x86_64: installed <- dxgkrnlがinstalledになっている
11. [Guest側] ライブラリ修正
Host側からコピーしたライブラリ群は、symlink関連が足りていなかったりします。
そのため、以下の手順で手動で修正します。
11-1. /usr/lib/wsl/lib を ld.so の検索対象に追加
echo '/usr/lib/wsl/lib' | tee /etc/ld.so.conf.d/ld.wsl.conf
11-2. libcuda.so 系 symlink を整理
cd /usr/lib/wsl/lib
rm -f libcuda.so libcuda.so.1
ln -s libcuda.so.1.1 libcuda.so.1
ln -s libcuda.so.1 libcuda.so
11-3. libnvidia-ml.so symlink を作成
rm -f /usr/lib/wsl/lib/libnvidia-ml.so
ln -s /usr/lib/wsl/lib/libnvidia-ml.so.1 /usr/lib/wsl/lib/libnvidia-ml.so
11-4. nvidia-smi に実行権限を付与
コピーした状態では実行権限がないため、付与しておきます。
chmod +x /usr/lib/wsl/lib/nvidia-smi
11-5. ldconfig を実行
ldconfig
12. [Guest側] DriverStore を正しい場所へ配置
ここで nvidia-smi を実行します。
※PATHをセットしていなければ、 /usr/lib/wsl/lib/nvidia-smi で直パス指定実行でも可
ここまでの手順が正常に完了していれば、 nvidia-smi が
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver.
Failed to properly shut down NVML: Driver Not Loaded
というように、Driver Not Loaded = Driver不足の状態になります。
もしここでライブラリ関連 .so がないというエラーの場合は、手順11とエラーで表示されたライブラリのsymlinkがあるか、確認してください。
Driverの移動
/opt/hostdriverstore に置いていた NVIDIA ディレクトリを、/usr/lib/wsl/drivers に配置し直します。
mkdir -p /usr/lib/wsl/drivers
find /opt/hostdriverstore -type d | grep 'nv.*inf_amd64'
cp -a /opt/hostdriverstore/nv*.inf_amd64_* /usr/lib/wsl/drivers/
ここも丸ごとコピーします。
権限を調整
sudo chmod -R 0555 /usr/lib/wsl
libD3D12Core.so の大文字シンボリックリンクを追加
cd /usr/lib/wsl/lib
sudo ln -sf /usr/lib/wsl/lib/libd3d12core.so /usr/lib/wsl/lib/libD3D12Core.so
これはD3D12 実装が /usr/lib/wsl/lib を case-insensitive 前提で扱う不具合対策です。
再度 ldconfig
ldconfig
再起動
reboot
13. [Guest側] lspci と nvidia-smi で確認
再起動後、まず vGPU が見えていることを確認します。
lspci -v | grep -A20 -Ei '3d|display|microsoft|dxg'
期待値の例:
3D controller: Microsoft Corporation Basic Render Driver
...
Kernel driver in use: dxgkrnl
次に nvidia-smi を実行します。
LD_LIBRARY_PATH=/usr/lib/wsl/lib /usr/lib/wsl/lib/nvidia-smi
成功例:
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI ... |
| Driver Version: ... CUDA Version: ... |
| GPU Name ... |
| 0 NVIDIA GeForce GTX 1660 Ti ... |
+-----------------------------------------------------------------------------------------+
ここでGPUが見えれば、 Hyper-V Ubuntu 24.04 VM 上で GPU-PV を通じて NVIDIA GPU が認識されている 状態になります。
14. よくある詰まりポイント
14-1. Get-VMGpuPartitionAdapter の InstancePath が空
- VM 起動前だと空のことがある
- 一度 VM を起動してから再確認する
- それでも空なら
-InstancePathを明示して再追加する
14-2. nvidia-smi 実行時に libnvidia-ml.so が見つからない
-
/usr/lib/wsl/libを ld.so に登録していない -
libnvidia-ml.so -> libnvidia-ml.so.1の symlink が無い -
nvidia-smiに実行権限が付いていない
14-3. Driver Not Loaded になる
-
/dev/dxgが存在しない -
dxgkrnlが正しくロードされていない - DriverStore が
/usr/lib/wsl/driversに置かれていない -
libD3D12Core.soの大文字リンクが無い
14-4. ldconfig で libcuda.so.1 is not a symbolic link と出る
- 共有ライブラリの symlink 構造がコピー時に崩れている
-
libcuda.so/libcuda.so.1/libcuda.so.1.1の構成を修正する
15. 動作確認用のチェックコマンドまとめ
Host 側
Get-VMHostPartitionableGpu | Format-List Name,ValidPartitionCounts,PartitionCount
Get-VMGpuPartitionAdapter -VMName $VMName | Format-List *
Guest 側
ls -l /dev/dxg
dmesg | grep -i -E 'dxg|dxcore|hyperv|vmbus'
dkms status
lspci -v | grep -A20 -Ei '3d|display|microsoft|dxg'
LD_LIBRARY_PATH=/usr/lib/wsl/lib /usr/lib/wsl/lib/nvidia-smi
16. 注意事項
- この構成は 公式に明確な完成手順が公開されているものではなく、実験的な構成です
- Windows Update / NVIDIA Driver Update / Ubuntu kernel update により動作が崩れる可能性があります
- とくに
dxgkrnl-dkmsは、カーネル更新後に再ビルド確認が必要です - Guest 側には 通常の Linux 用 NVIDIA ドライバを入れないでください。NVIDIA の WSL ガイドでも、WSL 系構成では Windows 側ドライバを使う前提です。