在上期,我们讨论了AMD主导的基于SRIOV的GPU虚拟化方案。我们也发现了,由于GPU本质上不是CPU的一个外设,而是一个高度并行,具备成千上万个核的计算机,而SRIOV只是提供了对外的PCI-E接口的虚拟化,并没有提供GPU计算核心与内存分配给不同VM的能力,因此,GPU的SRIOV虚拟化方案存在着一些固有的缺陷。
小H想知道如何解决这些缺陷,跑去图书馆查阅资料。路过武侠小说书柜的时候,忍不住多看了一眼——
令狐冲由于偷偷用GPU服务器打游戏,被发配到思过崖,负责较为边缘化的虚拟化系统的运维。这天,令狐冲发现陆大有在玩《实况足球》,画面精美流畅。他问:
“整个思过崖没有一块GPU,你是怎么做到玩这个游戏还如此流畅的?”
“我可以用公有云上虚拟化的GPU玩,”陆大有笑了。“令师兄,你有所不知,现在公有云的GPU服务器竞价实例很便宜,公司给你发的一个月300代金券还有富余,足够忙里偷闲打游戏的需要了。”
令狐冲瞪大了眼睛。这是怎么做到的呢?
令狐冲百思不得其解,直到有一天他走进思过崖后的山洞,看见洞穴的岩壁上刻了一堆英文,令狐冲的英文水平勉强能认出virtio, queue, backend driver等字眼。幸好,借助Google翻译和ChatGPT等工具,令狐冲大概看明白了。
很快,令狐冲理解了怎么借鉴virtio来实现GPU虚拟化的原理。但玩了一会儿《实况足球》,令狐冲不禁悲从中来——
“再下去要输越南了,泰国队输完输越南,再输缅甸,接下来没人输了。输给缅甸就留在KK园区不用回来了”
“阿根廷有梅西,巴西有罗尼,意大利有托蒂,法国有亨利。咱中国出了一个足球的大帝,却差了十万八千多里”(用《青花瓷》的曲调唱)
小H在愤怒中醒来,由于口水流得图书馆桌上到处是,被责令留下来打扫卫生。
原来,NVidia在继vCUDA之后,在2014年推出了vCUDA的替代品——GRID vGPU。
GRID vGPU是一种半虚拟化的GPU分片方案,与Virtio有一点点类似,所谓的“分片”,指的是时间上的分片,也就是时分复用。
GRID vGPU的实现如下图:
图中,VM中的CUDA应用调用的是原生的CUDA库,但GuestOS中的GPU驱动并不是访问GPU物理的BAR(Base Address Register),而是访问虚拟的Virtual BAR。
在进行计算工作时,GuestOS的GPU驱动会将保存待计算Workload的内存地址(GPA,Guest Physical Address)通过MMIO CSR(Configuration and Status Registers)传递给HostOS中的GPU驱动,从而让HostOS的GPU驱动拿到GPA并转换为HPA(Host Physical Address),写入物理GPU的MMIO CSR,也就是启动物理GPU的计算任务。
物理GPU在计算完成后,会发送一个MSI中断到HostOS的驱动,HostOS的驱动根据Workload反查提交这个Workload的vGPU实例,发送中断到对应的VM中。VM的GuestOS处理该中断,知道计算Workload已完成,上报CUDA和应用,vGPU计算过程处理完毕。
vGPU方案也称为MPT(Mediated Pass Through,受控直通)方案。该方案的思路是,虚拟一些敏感资源和关键资源(如PCI-E配置空间和MMIO CSR),而GPU显存的MMIO则进行直通,并在HostOS上增加一个能够感知虚拟化的驱动程序,以进行硬件资源的调度。这样,VM中就可以看到一个PCI-E设备,并安装原生的GPU驱动。
我们可以类比VirtIO的架构:
图中,Hypervisor为虚拟机提供了一个Virtio-net设备,在宿主机上对应vhost-net后端,而vhost-net最终调用物理网卡把数据包发送出去。这实际上是对宿主机物理网卡的时分复用。
而GRID vGPU本质上与virtio是同一类技术,该方案的优势在于,继承了vCUDA的调度灵活性,且不需要替换原有的CUDA API库,解决了上一代vCUDA的兼容性问题。
MPT方案的缺陷在于,宿主机上的驱动为硬件厂商所控制(不开源),而该物理GPU驱动为整个调度能力实现的核心。对比Virtio+vSwitch的网络虚拟化方案,我们发现,Virtio+vSwitch的整个技术栈都是开源的。因此,我们也在寻求其他全栈开源的GPU虚拟化方案。
——注:用GPU服务器竞价实例打游戏不是方老师发明的,是一个朋友想出来的