作者:郑晓,龙欣,弹性计算异构计算项目组
让各位久等了,阿里小二这就开始上新菜:“GPU分片虚拟化”。
对于“分片”的理解,相信大家已经不陌生了。此处的分片从两个维度上来定义:其一,是对GPU在时间片段上的划分,与CPU的进程调度类似,一个物理GPU的计算engine在几个vGPU之间共享,而调度时间片一般都在1ms-10ms左右,其二,是对GPU资源的划分,主要是指对GPU显存的划分,以NVIDIA为例,一个物理GPU带有16GB的显存,那么按照16个vGPU来划分,每个vGPU得到1GB的显存。由于安全隔离的要求,每个vGPU独享分配给它的显存,不会与其他vGPU共享。
技术上讲GPU分片虚拟化,就是指基于VFIO mediated passthrough framework的GPU虚拟化方案。该方案由NVIDIA提出,并联合Intel一起提交到了Linux kernel 4.10代码库,该方案的kernel部分代码简称mdev模块。随后Redhat Enterprise,centos最新的发行版花了不少力气又backporting到了3.10.x kernel。所以如果目前采用最新的Redhat 发行版(企业版或者centos7.x)等都已经自带mdev模块。而如果采用ubuntu17.x 以后版本的话,不但自带mdev功能,连Intel GPU驱动(i915)也已经更新到支持vGPU。无需任何代码编译就可以直接体验vGPU虚拟机功能。
那么什么叫mediated passthrough呢? 它与pass through的区别是什么呢? 一句话解释:把会影响性能的访问直接passthrough给虚拟机,把性能无关,功能性的MMIO访问做拦截并在mdev模块内做模拟。太过细节的东西详见后续篇章。
GPU分片虚拟化框架
GPU分片虚拟化的方案被NVIDIA与Intel两家GPU厂家所采用。NVIDIA GRID vGPU系列与Intel的GVT-g(XenGT or KVMGT)。
当然光有内核的支持还不够,需要加上qemu v2.0 以后版本,加上Intel或者NVIDIA自带的GPU mdev驱动(也就是对GPU MMIO访问的模拟),那么GPU分片虚拟化的整个路径就全了。而GPU厂家的mdev驱动是否开源取决于自己。按照一贯的作风,Intel开源了其绝大部分代码,包括最新的基于mdev的GPU热迁移技术,而NVIDIA也保持其一贯作风:不公开。
GPU分片虚拟化看起来整个框架就如下图一样(以KVMGT作为例子):
(图片来源:https://01.org/sites/default/files/documentation/an_introduction_to_intel_GVT-g_for_external.pdf)
可以从上图看到vGPU的模拟是通过kvmGT(Intel)或者NVIDIA-vgpu-vfio(NVIDIA)来完成。该模块只模拟对MMIO的访问,也就是功能性,不影响性能的GPU寄存器。而对GPU aperture和GPU graphic memory则通过VFIO的passthrough方式直接映射到VM内部。
值得注意的是一般Passthrough的方式都依赖IOMMU来完成GPA到HPA的地址转换,而GPU的分片虚拟化完全不依赖IOMMU,也就是说其vGPU的cmd提交(内含GPA地址)并不能直接运行于GPU硬件之上,至少需要有一个GPA到HPA的翻译过程。该过程可以通过host端的cmd扫描来修复(KVMGT),NVIDIA GRID vGPU每一个context有其内部page table,会通过修改page table来实现。
由于NVIDIA GRID vGPU代码闭源,我们将着重介绍Intel的GVT-g方案。
Intel GVT-g的介绍
说起GVT-g我大概可以讲上三天三夜。当然大伙这儿也未必想听。捡简洁的说起:
Kernel 与 mdev驱动源码:
https://github.com/intel/GVT-linux
qemu:
https://github.com/intel/IGVTg-qemu
setup文档:
https://github.com/intel/GVT-linux/wiki/GVTg_Setup_Guide
我们可以在任何一个带集成显卡Intel SKL/BDW的机器上运行GVT-g虚拟化的方案。GVT-g的GPU虚拟化方案也被用到了嵌入式,车载系统等领域(ARCN hypervisor)。
干货来了J 对于想了解GPU的运作,以及软硬件规范的,Intel其实已经开源了其大部分标准。
https://01.org/linuxgraphics/documentation/hardware-specification-prms
截个屏,对于想了解GPU内部部分设计与运行机制的人来说,光看看这个列表就会莫名的兴奋。
GVT-g由于是基于Intel的集成显卡,所以对运行环境的硬件要求非常低。任何Intel的带GPU的ATOM,Mobile Core或者Xeon E3等等CPU都能支持vGPU虚拟化(HSW,BDW,SKL系列CPU)。
又同时GVT-g完全免费,用户不需要花费额外的费用来支持vGPU的应用。
也正是这些优点,使得GVT-g可以被广泛的运用到任何对终端有虚拟化与显示要求的场景。比如XenClient,比如ARCN等等。
GVT-g的优点之一在于对其本地显示的良好支持。
GVT-g在内部虚拟了一个类似display pipeline的组件,来接管GPU display port上连接的显示器。所以vGPU内部framebuffer的信息可以被GVT-g快速的显示在物理GPU连接的显示器上。其显示FPS可以到达惊人的60FPS。完全达到了物理显示器的效果。更为强悍的是,vGPU通过对这些port和EDID的模拟可以在虚拟机内部支持多屏显示,其显示效果达到了完全与物理机状态下难分难解的地步。
其framebuffer的传输路径可谓九曲十八弯…但效果还不错。60fps妥妥的。
内嵌一段视频,来描述两个VM是如何共享同一个物理显示器,并能做到流畅切换:
https://01.org/sites/default/files/downloads/iGVT-g/iGVT-g-demokvmgt.zip
GVT-g的Media transcoding能力
Intel GPU对media decoding/encoding的硬件支持是其一大特色。GVT-g在vGPU虚拟化的过程中也加入了对media decoding/encoding的支持。其虚拟化后的vGPU的编解码吞吐能力可以达到惊人的99%物理GPU的吞吐量(HSW GPU 2014年)。仗着当年vGPU media transcoding 99%物理性能的优势,GVT-g团队在当年深圳举行的IDF上提出了Intel GVT-g对media cloud的未来设想。并在2015的巴塞罗那世界移动大会上联合华为做了一个GVT-g对Media Cloud的展台。其架构设想如下图(图中绿色方块为Media Cloud的发力点,截图来自GVTg官网)
https://01.org/sites/default/files/documentation/intel_graphics_virtualization_for_media_cloud.pdf
随后由于Intel GPU软硬件设计人员在下一代GPU中的设计没有全面考虑分片虚拟化场景,在一定程度上破坏了GVT-g在media transcoding上面的优势。目前在BDW和SKL上面的vGPU编解码效率已经不尽人意,失去了其优势。
不得不感叹一下,曾梦想仗剑走天涯….如今已凉凉
GVT-g技术的渲染能力
直接从Intel GVT的官网抠数据(https://01.org/sites/default/files/documentation/an_introduction_to_intel_GVT-g_for_external.pdf)
vGPU基本上对于Graphic rendering的能力是物理GPU的80%以上,一般在90%左右,回忆一下我们在第三章中介绍的AMD的SRIOV类型GPU虚拟化下vGPU的渲染能力可以达到97%左右。同时本身Intel GPU物理渲染能力与AMD/NVIDIA的同时代GPU比较也远远处于下风。所以对于强调大计算力的3D渲染场景的vGPU应用,Intel GPU的应用比较受限。
从技术的角度来看,GVT-g对于vGPU的性能损耗主要开销在于对其中断相关MMIO的模拟。比如对于AMD的SRIOV方案,其VM中对vGPU的MMIO访问完全没有虚拟化开销,不会有trap发生。即便不采用SRIOV方案,一般来说,硬件设计很多时候会考虑到对虚拟化的要求,并做出有利于虚拟化框架的改动。类似这种中断相关对性能敏感的MMIO是需要特殊设计以减少在虚拟化下的损耗。而像Intel GPU这样完全不考虑虚拟化开销的硬件设计,使得GVT-g在软件层面无论如何优化都无法达到潜在对手的高度。为什么说是潜在对手呢?因为对于NVIDIA来说,GVT-g与Intel GPU根本就算不上是一个对手。
GVT-g的GPGPU能力
GVT-g vGPU只做到了可以运行OpenCL,而对performance等并没有做任何优化。Intel GPU硬件在computing和深度学习方面本就不是强项。
GVT-g的Live Migration
GVT-g的vGPU在软件层次做到了极致。其早在2015年末就开始了对vGPU的热迁移支持。并在2016年对外公布。而GRID vGPU只在最近才有消息透露其在Citrix的某些产品上支持vGPU的热迁移,并只支持部分GPU型号。而AMD的SRIOV方案至今没有热迁移方面的公开消息。
vGPU的热迁移细节太过技术化,此处不多做介绍,但是当年第一个支持vGPU的VM渲染实时迁移的效果还是让人印象深刻的。其视频是基于KVM的vGPU迁移过程。
从视频截图中可以看出,其所有迁移过程在小于1秒的时间内完成并显示在新机器上了。(Demo的实际整体迁移时间为300ms左右)
https://www.youtube.com/watch?v=y2SkU5JODIY
GVT-g的调度
实话说GVT-g的调度并没有AMD SRIOV vGPU做的好。其调度粒度虽然是在1ms时间片的维度上做调度和vGPU切换。但是由于GPU软硬件对preempt功能的支持尚未完备,实际调度往往需要等当前vGPU的任务结束才能开始。在渲染大帧的情况下vGPU调度信息一般的统计显示,其基本上在5-10ms左右的间隔做vGPU切换。回忆一下AMD的SRIOV是严格6ms一次。而NVIDIA的GRID vGPU有多种调度策略,由于闭源,没有更多的信息可以拿到其调度信息。有心得读者可以在虚拟机下通过rebuild NVIDIA Guest Linux驱动研究一下。
GVT-g得局限性
当然悲催的是,也正是由于GVT-g是基于Intel的集成显卡,即便是免费附加增值服务,GVT-g在数据中心也很少被采用。第一本身的GPU性能无法与AMD/NVIDIA同类产品竞争,第二数据中心追求的是高密度运用,集成显卡无论如何都无法做到一机多卡的情况,在机房机架,寸土寸金的地方,大家都会考虑成本。Intel也作过一些尝试,把几个Xeon E3的CPU做到一块PCIE板卡上面增加其计算密度,然而其功耗和售价都无法与其他对手竞争。同时这种设计也使得软件系统复杂难维护。
NVIDIA GRID vGPU的介绍
闭源系统,没什么好介绍的。值得一提的是NVIDIA GRID vGPU是正式商用的方案。其技术在VMWare,XenServer,Redhat等大厂已经久经考验。
GRID vGPU在VDI上的运用
GRID vGPU在VDI的运用要早于GVT-g和AMD的SRIOV。早期GRID已经与VMWare合作堆出了一些列remote display的方案。GRID vGPU擅长remote display,GVT-g擅长local display,各有优点。
GRID vGPU渲染能力
对比GVT-g,GRID vGPU在图形渲染方面的虚拟化损耗非常小几乎与AMD SRIOV的类似,可以达到其passthrough状态下的99%左右。而GVT-g却在90%左右。
GRID vGPU通用计算能力
虽然没有多少人会在一个分片GPU虚拟化的VM内部作深度学习计算,但GRID vGPU的计算性能也已经可以达到其passthrough状态下的80%以上。其目前vGPU 1:1分片(一个物理GPU只分一个vGPU)情况下,各项性能指标几乎已经与passthrough GPU的方案不相上下。完全可以取代GPU passthrough的方案。但对多vGPU的支持,目前GRID vGPU无法支持。这是其对比GPU passthrough方案最大的弊端。NVIDIA显然不会坐视不理,GRID vGPU将来一定会考虑多vGPU的场景并支持P2P。GRID vGPU另外一个对比passthrough GPU的好处就是可以在Host端对vGPU关键性能指标的监控。还记得我们在本系列第二章介绍GPU passthrough方案的时候提到的:GPU passthrough方法的固有缺点吗?GPU passthrough情况下host端对vGPU无法进行有效监控,而这在GRID vGPU的场景下完全不成问题。
GRID vGPU分片虚拟化的方案相对GPU passthrough来说部署比较困难,由于闭源,其并不像Intel GVT-g一样一切开源并整合到kernel代码库中,一般厂商需要使用该技术还得作不同程度的kernel适配和调试。发布周期至少半年以上。
各个GPU虚拟化方案的一些实现细节异同
Mediated passthrough (mdev)
我们再次来回顾一下什么叫mediated passthrough。首先应该查看kernel document:
https://github.com/torvalds/linux/blob/master/Documentation/vfio-mediated-device.txt
之前已经提到Mediated是指对MMIO 访问的拦截和emulation,对DMA transfer的提交作GFN到PFN的地址转换。
NVIDIA在2016年的KVM forum上面已经很详细的介绍了这些细节。
GPU command的提交方式
三个GPU虚拟化的方案在GPU command(batch buffer)的提交方式上是由本质区别的。GVT-g与GRID vGPU作为分片虚拟化的代表,其任何vGPU的cmd提交都会被拦截到host端作emulation。并通过host的处理以后由host代替vGPU提交到物理GPU。AMD SRIOV方案其本质上也是一种GPU分片虚拟化,并且其与mdev的区别就是分片方式是:通过SRIOV的标准还是通过mdev软件方式实施,而对SRIOV vGPU的emulation则在Host端的GPU硬件,Firmware,GIM驱动共同完成。
而GPU passthrough方式下,vGPU的cmd直接由虚拟机内部提交。无需再绕道Host端。由此 passthrough下,无法对虚拟机内部vGPU的运作做出监控。
简单点讲:GVT-g与GRID vGPU的提交方式为一类,SRIOV与GPU passthrough方式为另一类。
IOMMU
分片虚拟化不需要IOMMU硬件的支持。其只需要VFIO模块添加type1 IOMMU的驱动,来通知host将要进行的DMA传输的GFN,VA等信息,并在Host端的mdev设备驱动层完成GFN到PFN的翻译处理。可以理解为软件层面上的IOMMU操作。
而AMD SRIOV与GPU passthrough方式下,IOMMU是必备组件。尤其IOMMU硬件完成GFN到PFN的地址转换。
简而言之,GVT-g,GRID vGPU是一伙,SRIOV,GPU passthrough是一伙。
至此,“浅谈GPU虚拟化技术“系列文章完结。谢谢大家拜读。尽情等待未来“深入GPU虚拟化技术“系列….哈