Hyper-V虚拟机的物理设备直通(Discrete Device Assignment, DDA)与显卡直通实践

在Windows Server 2016中,微软为Hyper-V虚拟机加入了物理设备直通(Discrete Device Assignment, DDA)的功能,允许虚拟机完全控制宿主机上的某些硬件(包括但不限于GPU,网络适配器等)。

年初的时候老板火急火燎撒钱买了一台四路1080Ti服务器给实验室用作深度学习使用,结果火急火燎地买回来才发现很多深度学习框架对多GPU支持并不好,于是只能分开使用。想我也是经历过共用服务器的混乱,于是提议建立四个虚拟机,然后把整块物理GPU直接分配给各自虚拟机互不干扰,因为之前偶然看到过从Windows Server 2016开始,微软为Hyper-V虚拟机加入了物理设备直通(Discrete Device Assignment, DDA)的功能,允许虚拟机完全控制宿主机上的某些硬件(包括但不限于GPU,网络适配器等)。一开始以为应该也挺简单的,但实际上还是踩了很多坑才最终弄好。

关于Discrete Device Assignment的详细信息,可以查看微软虚拟化博客四连:

Description and background

Machines and devices

GPUs

Guests and Linux

本文以这些相关官方博文为基础记录了直通显卡的一般流程,适合对DDA技术感兴趣的朋友入门尝鲜。此外,我封装了一个简单的带GUI的工具:

https://github.com/chanket/DDA/releases

GUI工具测试系统为Windows Server 2016,据评论区反馈,最新的Windows Server 2019不能使用该工具。


显卡直通与RemoteFX的区别

DDA直通显卡是将整张显卡的控制权限移交给虚拟机,而类似RemoteFX技术则是将宿主机上的显卡虚拟化后为虚拟机提供一定的3D加速支持。简单来说:


要求

物理设备直通对系统的硬件和软件都有一定的要求,除了需要宿主机的操作系统为Windows Server 2016 TP4以上版本外,还需要以下要求:

微软没有提供DDA的相关操作的GUI工具,关键操作只能通过PowerShell完成,这可能对不太熟悉Powershell的用户来说比较煎熬。

下面,我们以Tesla V100为例,将其从宿主机直通到目标虚拟机Test中。


步骤一:获取设备路径(Location Path)

设备路径在物理设备直通的过程中相当于设备的唯一描述符。下面的Powershell展示了如何获取名称以NVIDIA开头的设备的设备路径。

#获取所有名称以NVIDIA开头的设备
$pnpdevs = Get-PnpDevice -PresentOnly | Where-Object {$_.FriendlyName -like "NVIDIA*"}
#输出LocationPath
foreach ($pnpdev in $pnpdevs) {
       $locationpath = ($pnpdev | get-pnpdeviceproperty DEVPKEY_Device_LocationPaths).data[0]
       $pnpdev.FriendlyName + ": " + $locationpath
}

在我的机器上,可以得到下面的输出:

NVIDIA Tesla V100-SXM2-16GB: PCIROOT(0)#PCI(0300)#PCI(0000)#PCI(0C00)#PCI(0000)
NVIDIA Tesla V100-SXM2-16GB: PCIROOT(0)#PCI(0300)#PCI(0000)#PCI(0800)#PCI(0000)
NVIDIA Tesla V100-SXM2-16GB: PCIROOT(80)#PCI(0200)#PCI(0000)#PCI(0800)#PCI(0000)
NVIDIA Tesla V100-SXM2-16GB: PCIROOT(80)#PCI(0200)#PCI(0000)#PCI(0C00)#PCI(0000)

这个过程也可以通过设备管理器完成,如图所示:


步骤二:禁用设备

要被直通的物理设备将会被虚拟机独占使用,因此,操作系统需要确保宿主机没有其它应用在使用被直通的设备,因此在直通前禁用设备。

我们可以使用Disable-PnpDevice命令,通过设备的InstanceId来禁用设备。例如,在上文Powershell中获取$pnpdev对象后,继续执行:

disable-pnpdevice -InstanceId $pnpdev.InstanceId -Confirm:$false

这个过程同样可以通过设备管理器完成,如图所示:


步骤三:下线(Dismount)设备

这一步操作会将已经禁用的设备从操作系统中移除,使其变成可分配的状态。这一步只能通过Powershell完成。根据上面获得到的设备路径(Location Path),例如,"PCIROOT(0)#PCI(0300)#PCI(0000)#PCI(0C00)#PCI(0000)",运行下面的命令:

Dismount-VmHostAssignableDevice -locationpath "PCIROOT(0)#PCI(0300)#PCI(0000)#PCI(0C00)#PCI(0000)" -force

这一步是最可能出现错误的。许多硬件上的不兼容都会在这个步骤报错。

成功执行此步操作后,宿主机上的设备管理器将无法查看到该设备。


步骤四:分配设备

假设前面的步骤都已完成,这个时候就已经可以将下线后的设备分配给虚拟机了。这一步依然只能通过Powershell完成。将GPU分配到名称为Test的虚拟机中的命令如下所示:

Add-VMAssignableDevice -LocationPath "PCIROOT(0)#PCI(0300)#PCI(0000)#PCI(0C00)#PCI(0000)" -VMName Test

如果到这一步依然没有任何错误,那么设备已经成功直通到了虚拟机上。你可以通过下面的Powershell检查:

Get-VMAssignableDevice -VMName Test

在我的机器上,可以得到下面的输出:

InstanceID       : PCIP\VEN_10DE&DEV_1DB1&SUBSYS_121210DE&REV_A1\6&3D280D5&0&00600018
LocationPath     : PCIROOT(0)#PCI(0300)#PCI(0000)#PCI(0C00)#PCI(0000)
ResourcePoolName : Primordial
Name             : 虚拟 PCI Express 端口设置
Id               : Microsoft:C3B8CA0E-F6DA-417C-B6D6-DD9D68F7D899\EAEE9BF9-B29B-4D2E-970B-325F02812E83
VMId             : c3b8ca0e-f6da-417c-b6d6-dd9d68f7d899
VMName           : Test
VMSnapshotId     : 00000000-0000-0000-0000-000000000000
VMSnapshotName   :
CimSession       : CimSession: .
ComputerName     : TRAIN
IsDeleted        : False
VMCheckpointId   : 00000000-0000-0000-0000-000000000000
VMCheckpointName :

GPU额外步骤一:合并缓存写入

对于GPU相比于一般的外部设备速度很快,这使得如果我们允许对CPU合并对GPU显存的写入操作以提升性能。以Test虚拟机为例,运行下面的Powershell:

Set-VM Test -GuestControlledCacheTypes $true

GPU额外步骤二:扩大内存映射IO空间(Memory Mapped IO Space)大小

GPU需要的MMIO空间通常较大,当一个虚拟机分配到的设备所需要的MMIO空间综合超过了Hyper-V为其默认提供的大小时,在虚拟机操作系统中就会提示“没有足够的系统资源”的错误。

你可以在设备管理器右键设备-属性中看到设备所需的MMIO空间,如图所示:

根据内存范围,我们可以算出一张V100所需的MMIO大小为16MB+16384MB+32MB,其中,32位地址空间内需求16MB,64位地址空间内需求16384MB+32MB=16416MB。目前一个新建的Hyper-V虚拟机默认只为32位和64位地址空间分别提供了128MB和512MB的MMIO空间大小,这导致V100直接分配到虚拟机中是无法使用的。

32位和64位地址空间的MMIO大小可以通过下面的Powershell来分别修改,以Test虚拟机为例:

Set-VM Test -LowMemoryMappedIoSpace upto3000MB
Set-VM Test -HighMemoryMappedIoSpace upto33000MB

在这里,我为V100保留了17000MB的HighMemoryMappedIoSpace,保持LowMemoryMappedIoSpace不变。


结果展示

在虚拟机中安装NVIDIA驱动后,可以看到V100为正常的可用状态。

 

称谓(*)
邮箱
留言(*)