一般来说,windows系统中最常使用的虚拟机就3个:vmware workstation,virtualbox和微软系统自带的hyper-v。后面与前两者最大的区别就是能调用物理显卡的性能。
我在这篇博文会详述如何设置windows虚拟机的显卡虚拟化,并会随之对一些遇到的问题答疑。
调用方式
hyper-v中调用显卡的方式有两种:
显卡(设备)直通:即DDA,又可以叫passthrough。这种方法能利用显卡的全部性能,但只能被单个虚拟机独享,直通之后,连物理机也无权访问显卡。
显卡虚拟化:即GPU分区。这种方法物理机和多个虚拟机都能同时使用显卡,虽然性能肯定会打点折扣,但总比在虚拟机里无法使用显卡要强得多。
显卡虚拟化好处
能在虚拟机中流畅玩游戏、视频编辑、直播推流、AI模型训练与推理等。
显卡支持
绝大部分主流的核显与独显都能支持,核显方面如Intel i3 8100的UHD 630, AMD Ryzen 3 2200G的Vega 8, 独立方面如Nvidia RTX 4060。
操作系统支持
物理机系统windows 10 1809及更旧版本的应该不支持(具体到哪一个细微版本我也不清楚)。反正windows我推荐window 10 22h2或更新版本,windows server推荐windows server 2022或更新版本。
所以无论是物理机还是虚拟机都安装推荐版本的话,以后就会省掉很多不必要的麻烦。
获取可虚拟化的显卡
显卡(物理上)支持虚拟化,并不代表就能被虚拟化到hyper-v中的虚拟机。正如上面提到的,物理机的版本有要求(主要是wddm模型的版本要达到要求)。同时,显卡的驱动要正确安装(而不是微软自带的基本显示驱动)
可通过powershell命令获取可用于虚拟化的显卡列表
如果物理机系统是win10,可通过
Get-VMPartitionableGpu
如果物理机系统是win11或windows server 2022,可通过:
Get-VMHostPartitionableGpu
系统环境
我这次用于测试的物理机系统为windows server 2022数据中心版,虚拟机为windows 10 22h2,显卡为nvidia GT1030。
虚拟化步骤
确定gpu设备id
从物理机的【设备管理器】中找到显卡gt1030,从其属性中的【详细信息】找到【设备实例路径】值,如下图所示:
设备实例路径的值如下:PCI\VEN_10DE&DEV_1D01&SUBSYS_00007377&REV_A1\4&36A45E2B&0&0008
其中DEV_后面的1D01部分即为设备id
所以显卡GT1030的设备id为1D01
获取GPU分区路径
通过以下命令获取可虚拟化的显卡信息列表:
Get-VMHostPartitionableGpu
具体如下:
查找设备id为1D01的显卡,也即Name属性中含有DEV_1D01部分的显卡信息,获取整个Name属性的值,也即:\\?\PCI#VEN_10DE&DEV_1D01&SUBSYS_00007377&REV_A1#4&36a45e2b&0&0008#{064092b3-625e-43bf-9eb5-dc845897dd59}\GPUPARAV
添加gpu到虚拟机
以管理员方式打开一个powershell窗口,输入以下内容创建两个变量以备之后使用,其中$vm是具体虚拟机的名称,$gpu_path是上述获取到的Name属性:
$vm = "win10"
$gpu_path = "\\?\PCI#VEN_10DE&DEV_1D01&SUBSYS_00007377&REV_A1#4&36a45e2b&0&0008#{064092b3-625e-43bf-9eb5-dc845897dd59}\GPUPARAV"
继续输入以下命令,以将gpu分区添加到该虚拟机中:
Add-VMGpuPartitionAdapter -VMName $vm -InstancePath $gpu_path
成功将gpu分区添加到虚拟机后,在虚拟机中的设备管理器即可看到该显卡并具体型号信息,如下图所示:
这里有几点注意:
(1) 有叹号是正常的现象,因为目前还没有拷贝驱动到虚拟机中。
(2) 如果这里新增的显卡没有显示具体型号,而只是显示Render Driver之类的,大概率是你的虚拟机系统版本有点低,不要再继续试了,直接换系统!!!
设置gpu详细参数
这些参数基本可以说是固定的了,如果你要我详细说明哪个参数影响什么地方,我也说不清楚,所以不要管,直接怼上去就是了。
先关闭虚拟机,然后继续在powershell中执行以下命令:
Set-VMGpuPartitionAdapter -VMName $vm -MinPartitionVRAM 80000000 -MaxPartitionVRAM 100000000 -OptimalPartitionVRAM 100000000 -MinPartitionEncode 80000000 -MaxPartitionEncode 100000000 -OptimalPartitionEncode 100000000 -MinPartitionDecode 80000000 -MaxPartitionDecode 100000000 -OptimalPartitionDecode 100000000 -MinPartitionCompute 80000000 -MaxPartitionCompute 100000000 -OptimalPartitionCompute 100000000Set-VM -GuestControlledCacheTypes $true -VMName $vm
Set-VM -LowMemoryMappedIoSpace 1Gb -VMName $vm #规定显存
Set-VM -HighMemoryMappedIoSpace 32GB -VMName $vm # 千万不要设少于8G, 这样会老是报error code 43错误
复制gpu驱动
这一步是将物理机的gpu驱动复制到虚拟机中,
物理机的驱动存放在:
C:\Windows\System32\DriverStore\FileRepository
虚拟机的驱动应存放在:
C:\Windows\System32\HostDriverStore\FileRepository
备注(1):正常情况下,只需要复制FileRepository目录下的nvidia驱动相关的子目录到虚拟机中对应的文件夹即可,但考虑到经常有朋友定位错误具体的驱动子目录(特别是intel和amd核显的驱动),所以我建议整个FileRepository目录复制过来。
备注(2): 由于无法直接复制驱动到虚拟机中C:\Windows\System32\HostDriverStore\FileRepository中,所以应该先复制驱动目录到虚拟机的桌面,然后再移动到实际的驱动目录中。
So现在正式开始(启动虚拟机):
复制FileRepository目录
将物理机的C:\Windows\System32\DriverStore\FileRepository目录复制虚拟机的桌面,待复制完成后,再移动到C:\Windows\System32\HostDriverStore\FileRepository
所以虚拟机中的FileRepository最终如下:
复制nvapi64.dll文件
备注:对于nvidia显卡才需要做这一步,其他显卡可忽略
将物理机的C:\Windows\System32\nvapi64.dll复制到虚拟机中C:\Windows\System32目录中。方法同上,不再赘述。
检查驱动状态
重启虚拟机,进入到设备管理器中,如果显卡前面不再含有感叹号,即已成功打上驱动,gpu虚拟化操作完成,如下图所示:
注意事项
由于gpu分区技术的原理,物理机和虚拟机的显卡需要保持一致。所以不要更新物理机的显卡驱动,也不要试图在虚拟机中重装显卡驱动。
问题答疑
(1) 为什么我的虚拟机中任务管理器没有显示gpu选项?
答:当虚拟机已经做好了gpu分区,其任务管理器中是否会显示gpu同时取决于物理机和虚拟机中的系统版本。据观察所得,物理机及虚拟机皆得win11 24h2或更新版本)
例子1:物理机 和虚拟机都是win11 24h2专业工作站版,虚拟机中能正常显示gpu使用率,如下图所示:
例子2:物理机为win10 22h2专业工作站版,虚拟机为win11 24h2专业工作站版,虚拟机中不能查看gpu使用情况
从虚拟机移除显卡
执行以下powershell命令即可:
Remove-VMGpuPartitionAdapter -VMName $vm
问题处理
(1) 在执行Add-VMGpuPartitionAdapter命令时,报错:GPU Partition (实例 ID 397F9507-2453-44FC-A80A-AC37129A0352): 无法开机,因为发生了错误“系统资源不足,无法完成请求的服
务。”。
“win10”无法添加资源。(虚拟机 ID A2598E46-B180-4B7D-B364-76F3C3377FF6)
“win10”GPU Partition (实例 ID 397F9507-2453-44FC-A80A-AC37129A0352): 无法打开电源,因为发生错误“系统资源不足,无法完
成请求的服务。”(0x800705AA)。(虚拟机 ID A2598E46-B180-4B7D-B364-76F3C3377FF6)
无法分配不符合当前设置组策略的可分区 GPU 设备。
如下图所示
解决办法:在注册表中的HKEY_LOCAL_MACHINE:\SOFTWARE\Policies\Microsoft\Windows\HyperV下加入RequireSecureDeviceAssignment和RequireSupportedDeviceAssignment,其值均设为0即可
然后重新执行该命令即可。