![]() |
Electoric sheep dream by fastSDCPU |
SandyおじさんPC(※今は厳密にはIvy)は実験用に使用しています。
今回、このPCを有効活用すべく、GPUが使用できるHyper-V仮想マシンを稼働させようと目論見ました。
GPU-Pって何?
このような記事にたどり着いている時点でご存じの方がほとんどとは思いますが、一応説明させていただくと、ホストPCが搭載しているGPUをパーティション化(分割)してゲストPCからも使えるようにするというMicrosoftのHyper-Vに搭載されている素晴らしい機能のことです。
何が素晴らしいの?
普通仮想マシンのグラフィック機能はショボいです。
パーティション化の対象にするGPUの性能にもよりますが、これがゲームが動くレベルになるのです。それからParsecという低遅延リモートデスクトップアプリケーションが仮想マシンで使用可能になります。
普通のパソコンでは、明確に「GPUを搭載していないPC」であっても、実際にはGPUが存在しないわけではなく、CPU内臓グラフィックス(intel HD GraphicsやIrisなど)という形で存在はしています。
CPU内臓グラフィックスは性能は高くないものの、仮想マシンのグラフィック性能よりは性能が高く、CPU内臓グラフィックス性能を基準に動作環境が設定されているアプリケーションもあります。
仮想マシンが、グラフィック要素も扱える普通のパソコンになるという表現がわかりやすいかもしれません。
試す
ホスト環境(こちらの記事のPCです)
- Windows10Pro
- Geforce GTX1050
- IvyBridge(Core i5-3470)
- B75M-PLUS マザーボード
Hyper-vゲスト仮想マシンは作成済みでWindows10Proが入っている状況です。
ゲスト環境
- 仮想マシン名前 Win10Pro
- Windows10Pro
※GPU-P関連コマンドはホストがWindows10と11では微妙に異なるところがあるのでご注意ください。
GPU情報の取得
まずPowerShellを起動してGPUの情報を得ます。
搭載しているGPUはGeforceなので、調べる名前を
"*GeForce*"
とします。
PS C:\windows\system32> Get-PnpDevice -PresentOnly | Where-Object { $_.Status -eq "OK" -and $_.Class -eq "Display" -and $_.FriendlyName -like "*GeForce*" } | Select-Object -First 1| Format-Table -AutoSize -Wrap
結果
Status Class FriendlyName InstanceId ------ ----- ------------ ---------- OK Display NVIDIA GeForce GTX 1050 PCI\VEN_10DE&DEV_1C81&SUBSYS_146919DA&REV_A1\4&BAB4994&0&0008
結果に出ているInstanceIdが必要です
PCI\VEN_10DE&DEV_1C81&SUBSYS_146919DA&REV_A1\4&BAB4994&0&0008
次のコマンドで必要なため、\を#に置き換える加工をします。
PCI#VEN_10DE&DEV_1C81&SUBSYS_146919DA&REV_A1#4&BAB4994&0&0008
次にGPUパーティションの情報を得ます
GPUパーティション情報を得る
先に調べたInstanceIdを指定して調べます。
PS C:\windows\system32> Get-VMPartitionableGpu | Where-Object { $_.Name -like "\\?\PCI#VEN_10DE&DEV_1C81&SUBSYS_146919DA&REV_A1#4&BAB4994&0&0008#*" } | Select-Object -First 1
結果
Name : \\?\PCI#VEN_10DE&DEV_1C81&SUBSYS_146919DA&REV_A1#4&bab4994&0&0008#{064092b3-625e-43bf-9eb5-dc 845897dd59}\GPUPARAV ValidPartitionCounts : {32} PartitionCount : 32 TotalVRAM : 1000000000 AvailableVRAM : 1000000000 MinPartitionVRAM : 0 MaxPartitionVRAM : 1000000000 OptimalPartitionVRAM : 1000000000 TotalEncode : 18446744073709551615 AvailableEncode : 18446744073709551615 MinPartitionEncode : 0 MaxPartitionEncode : 18446744073709551615 OptimalPartitionEncode : 18446744073709551615 TotalDecode : 1000000000 AvailableDecode : 1000000000 MinPartitionDecode : 0 MaxPartitionDecode : 1000000000 OptimalPartitionDecode : 1000000000 TotalCompute : 1000000000 AvailableCompute : 1000000000 MinPartitionCompute : 0 MaxPartitionCompute : 1000000000 OptimalPartitionCompute : 1000000000 CimSession : CimSession: . ComputerName : TEMP01 IsDeleted : False
GPUパーティション情報が得られます。Windows11の場合はこの文字列を使って取り付けコマンドを発行しますが、Windows10の場合は指定が不可能なので確認しただけです。
\\?\PCI#VEN_10DE&DEV_1C81&SUBSYS_146919DA&REV_A1#4&bab4994&0&0008#{064092b3-625e-43bf-9eb5-dc845897dd59}\GPUPARAV
Windows11ならば-InstancePathでこの文字を使ってどのGPUなのかを指定可能です、Windows10の場合は1つのGPU決め打ちとなるため、GPUパーティション情報の確認作業は実は必須ではなかったりします。
取り付けコマンド
PS C:\windows\system32>Add-VMGpuPartitionAdapter -VMName "Win10Pro"
ドライバー配置ディレクトリの作成(ゲストのストレージ)
あとでドライバーファイルを置くため、仮想マシンを起動してExplorerで次のディレクトリを作成しておく
D:\Windows\System32\HostDriverStore\FileRepository
仮想マシンはシャットダウンします。
仮想マシンで使うGPUドライバを探す
GPU-Pの面倒なところがホストが使ってるドライバと同じものを使用する必要があるというところ。
場所はホストの
C:\WINDOWS\System32\DriverStore\FileRepository
に入ってることはわかってるので、先に作ったゲストの(D:\Windows\System32\HostDriverStore\FileRepository )へ全コピーしてもいいのではあるが、大量にあるためそれなりに時間がかかるし、ディスクも無駄。
対象のドライバーだけコピーするのがよろしい。
ドライバーを探すコマンド
PS C:\windows\system32>Get-CimInstance -ClassName Win32_VideoController -Property * | Format-Table InstalledDisplayDrivers -AutoSize -Wrap
結果
InstalledDisplayDrivers ----------------------- igdumd64.dll,igd10umd64.dll,igd10umd64.dll C:\WINDOWS\System32\DriverStore\FileRepository\nv_dispig.inf_amd64_50916785244854f2\nvldumdx.dll, C:\WINDOWS\System32\DriverStore\FileRepository\nv_dispig.inf_amd64_50916785244854f2\nvldumdx.dll, C:\WINDOWS\System32\DriverStore\FileRepository\nv_dispig.inf_amd64_50916785244854f2\nvldumdx.dll, C:\WINDOWS\System32\DriverStore\FileRepository\nv_dispig.inf_amd64_50916785244854f2\nvldumdx.dll
※上記例は本来はつながって表示されますが、見やすく改行してあります。
つまり場所は
C:\WINDOWS\System32\DriverStore\FileRepository\nv_dispig.inf_amd64_50916785244854f2
だ
ドライバーファイルのコピー
ホストのWindows標準の「ディスクの管理」アプリから仮想マシンのvhdファイルへ接続をし
C:\ProgramData\Microsoft\Windows\Virtual Hard Disks
にあるvhdをマウント(仮想マシンの作り方によって場所は違うかも)
するとホストのエクスプローラーからゲストPCのディスクが扱えるようになるので、
あらかじめ作っておいたゲストのディレクトリ
D:\Windows\System32\HostDriverStore\FileRepository
へ
C:\WINDOWS\System32\DriverStore\FileRepository\nv_dispig.inf_amd64_5091
をまるごとコピーする
マウントしたVHDをマウント解除し、ゲストを起動するがGPUは生えてはいるが使えない。
ゲストを一度シャットダウンして
GPU-Pの詳細設定をする(細かいことはよくわからない)PowerShell上で実行してます。
Set-VMGpuPartitionAdapter -VMName "Win10Pro" -MinPartitionVRAM 100000000 Set-VMGpuPartitionAdapter -VMName "Win10Pro" -MaxPartitionVRAM 100000000 Set-VMGpuPartitionAdapter -VMName "Win10Pro" -OptimalPartitionVRAM 100000000 Set-VMGpuPartitionAdapter -VMName "Win10Pro" -MinPartitionEncode 100000000 Set-VMGpuPartitionAdapter -VMName "Win10Pro" -MaxPartitionEncode 100000000 Set-VMGpuPartitionAdapter -VMName "Win10Pro" -OptimalPartitionEncode 100000000 Set-VMGpuPartitionAdapter -VMName "Win10Pro" -MinPartitionDecode 100000000 Set-VMGpuPartitionAdapter -VMName "Win10Pro" -MaxPartitionDecode 100000000 Set-VMGpuPartitionAdapter -VMName "Win10Pro" -OptimalPartitionDecode 100000000 Set-VMGpuPartitionAdapter -VMName "Win10Pro" -MinPartitionCompute 100000000 Set-VMGpuPartitionAdapter -VMName "Win10Pro" -MaxPartitionCompute 100000000 Set-VMGpuPartitionAdapter -VMName "Win10Pro" -OptimalPartitionCompute 100000000 Set-VM -GuestControlledCacheTypes $true -VMName "Win10Pro" Set-VM -LowMemoryMappedIoSpace 1Gb -VMName "Win10Pro" Set-VM -HighMemoryMappedIoSpace 2GB -VMName "Win10Pro"
設定変えたらゲストが起動不能になる。
The upper MMIO region (0x00000017dffff000) is above the supported physical address range
MMIOで調べると、intel-VTがONである必要がある話とか、64bitOSではAbove 4g Decodingが有効である必要があったりするなど出てくるので、確認するが自分の環境では問題ない。
それからCSMというUEFIがBIOSとの互換性を持つ機能が有効になっていて、これもOFFにする必要があるようだが、CSMがONだったのでOFFにするとwindowが起動しない。
どうやら、自分の環境ではCSMを活用しており、使ってるディスクがMBRっぽい
CSMを解除するとディスクが見つからなくなってしまい、困る。
仕方ないので、MBR->GPT変換をする
アプライドネットさんのサイトで、MBRをGPTにデータを失わず、しかも標準ツールでできると知り試す。
https://shop.applied-net.co.jp/blog/cate_news/23507/
チェック
C:\WINDOWS\system32>mbr2gpt /validate /disk:0 /allowFullOS MBR2GPT: Attempting to validate disk 0 MBR2GPT: Retrieving layout of disk MBR2GPT: Validating layout, disk sector size is: 512 bytes MBR2GPT: Validation completed successfully
変換
C:\WINDOWS\system32>mbr2gpt /convert /disk:0 /allowFullOS MBR2GPT will now attempt to convert disk 0. If conversion is successful the disk can only be booted in GPT mode. These changes cannot be undone! MBR2GPT: Attempting to convert disk 0 MBR2GPT: Retrieving layout of disk MBR2GPT: Validating layout, disk sector size is: 512 bytes MBR2GPT: Trying to shrink the OS partition MBR2GPT: Creating the EFI system partition MBR2GPT: Installing the new boot files MBR2GPT: Performing the layout conversion MBR2GPT: Migrating default boot entry MBR2GPT: Adding recovery boot entry MBR2GPT: Fixing drive letter mapping MBR2GPT: Conversion completed successfully Call WinReReapir to repair WinRE MBR2GPT: Failed to update ReAgent.xml, please try to manually disable and enable WinRE. MBR2GPT: Before the new system can boot properly you need to switch the firmware to boot to UEFI mode!
すごい、ディスク初期化が必要だと思ったが、データを失うことなくできてしまった。
CSMを無効にしても、起動できるようになり、しかし仮想マシンは変わらず。
MMIOが・・・といわれる。
GPU-Pの詳細設定の数値の問題かと考え、いろいろ試す。
Set-VM -HighMemoryMappedIoSpace 512Mb -VMName "Win10Pro"
この512Mbを1Mでも超える(例:513Mbなど)と起動不能になるらしい。
かといって512Mbに下げてもGPUが動作するわけでもなく、コード43で動かない
いろいろ調べてるいると こちらの一番下のコメントで
「ハードウェアが古いんじゃね?」
と言われており、 他も調べてみるとネットの方々たちはRyzen PCでやったら何の問題なかったと語っており、自分もRyzenとRadeon RX580でGPU-Pはできている。
同じ問題に直面している人たちのハードウェアがSandyやIvyで、なんならB75マザーで同じ人までいた。
B75マザーが同じ方
https://www.reddit.com/r/HyperV/comments/nfhrqx/hyperv_gpup_mmio_error/
まさにSandyBridgeの方
https://github.com/jamesstringerparsec/Easy-GPU-PV/issues/40
GPU-Pのメモリ設定が良くわかっていないし、私も別環境(Ryzen)ではうまくいっているため
真実はわかりませんが、ハードウェアの古さが問題である可能性は高い。
結論
GPU-Pの夢は見れなさそう・・。
知識不足や設定間違い等もあるかもしれません。
そして外国人にもSandyおじさんがたくさんいた。