谢谢你的等待。阿里小二开始端上一道新菜:“GPU碎片化虚拟化”。
相信大家对“碎片化”的理解都很熟悉。这里的分片是从两个维度来定义的:一是GPU在时间段上的划分。类似于CPU的进程调度,一个物理GPU的计算引擎在几个VGPu之间共享,调度时间片一般在1 ms-10 ms左右,其次是GPU资源的划分,主要指GPU视频内存的划分。以NVIDIA为例,如果一个物理GPU有16GB的视频内存,那么按照16个VGs,由于安全隔离的要求,每个vGPU都享有自己的视频内存,不会与其他VGpu共享。
从技术上讲,GPU碎片化虚拟化是指基于VFIO介导的直通框架的GPU虚拟化方案。该方案由NVIDIA提出,与Intel一起提交给Linux内核4.10代码库。这个方案的核心代码简称mdev模块。然后,centos的最新版本Redhat Enterprise在向3.10.x内核的反向移植方面做了大量工作。所以如果目前采用最新的Redhat发行版(企业版或者centos7.x),那么它们都有自己的mdev模块。如果采用ubuntu17.x版本17.x,不仅有mdev功能,还更新了Intel GPU驱动(i915)支持vGPU。直接体验vGPU虚拟机功能,无需任何代码编译。
那么什么是媒介传递呢?它和穿越有什么区别?用一句话解释:将直接影响性能的访问传递给虚拟机,截取与性能无关的功能性MMIO访问,并在mdev模块中模拟它们。太详细的细节见后续章节。
GPU分片虚拟化框架
NVIDIA和Intel GPU厂商都采用GPU碎片化虚拟化方案。NVIDIA GRID vGPU系列和英特尔GVT-g(XenGT或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 _简介_英特尔_ gvt-g _ for _ external.pdf)
从上图可以看出,vGPU的仿真是由kvmGT(Intel)或者NVIDIA-vgpu-vfio(NVIDIA)完成的。本模块只模拟对MMIO的访问,即GPU注册有功能,对性能没有影响。另一方面,GPU光圈和GPU图形内存通过VFIO的直通模式直接映射到VM内部。
值得注意的是,一般的Passthrough方法是依靠iomu完成从GPU到HPA的地址转换,而GPU碎片虚拟化完全不依靠iomu,也就是说其vGPU(包括GPU地址)的cmd提交不能直接在GPU硬件上运行,至少需要一个从GPU到HPA的转换过程。这个过程可以通过主机端的cmd扫描(KVMGT)来修复。NVIDIA GRID vGPU的每个上下文都有自己的内部页表,可以通过修改页表来实现。
随着英伟达网格vGPU代码的关闭,我们将专注于英特尔的GVT-g解决方案。
Intel GVT-g的介绍
我可以谈论GVT三天三夜。当然,大家可能都不想在这里听到。接下来简明谈一谈:
内核和mdev驱动程序源代码:
https://github.com/intel/GVT-linux
qemu:
https://github.com/intel/IGVTg-qemu
设置文档:
https://github.com/intel/GVT-linux/wiki/GVTg_Setup_Guide
我们可以在任何带有集成显卡英特尔SKL/BDW的机器上运行GVT g虚拟化。GVT-g的GPU虚拟化方案还被用于嵌入式系统、车载系统等领域(ARCN虚拟机管理程序)。
干货来了。j对于想了解GPU运行情况和软硬件规格的人来说,英特尔其实已经开源了
其大部分标准。
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/watchv=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上面已经很详细的介绍了这些细节。
http://www.linux-kvm.org/images/5/59/02x03-Neo_Jia_and_Kirti_Wankhede-vGPU_on_KVM-A_VFIO_based_Framework.pdf
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是一伙。