GPU虚拟化就是将一个物理GPU切分为多个虚拟CPU以供不同虚拟机使用(GPU切分)
NVIDIA vGPU方案(软切分)方案组成
硬件:显卡需要支持GPU虚拟化
软件:虚拟化层和VM中分别有两类不同的驱动来实现
授权:通过授权来限制或者部分限制vGPU卡的使用
性能指标
GPU架构,架构越新代表制程更先进和更大的晶体管规模
CUDA核心:越大越好
显存:显存是虚拟机独占的
英伟达本身硬件是不做切分做工,通过虚拟化层和虚机中的驱动来完成切分
vGPU资源调度机制GPU的主要资源:
CUDA核心,
显存,
BAR(Base Address Register 是一种寄存器,用于指示设备(如显卡)在物理内存中的基地址,BAR通常用来配置设备的I/O端口或内存映射,并告诉系统在哪里可以找到设备的寄存器、缓冲区或其他资源。),
channel(内存通道,通信通道等)
虚拟机的独占资源: 显存,虚拟BAR,channel
虚拟机共享资源:计算核心,所有虚拟机分时共享(自己时间片内享受到所有的计算资源)
三种调度策略
Best effort (抢占),任务量大的分的资源多
Equal share:无论有没有任务,只要开机就能拿到相应的计算资源
Fixed Share:无论有没有任务,有没有开机,都预留给VM
vGPU资源切分说明一般一个GPU只能跑一种profile,包括显存容量和授权模式(可能是因为硬件设计或者稳定性,兼容性的考虑)
比如8核,只能切成2222或者44,不能224
虚机漂移,只能在相同GPU型号之间实现,也不是所有虚拟机都支持
部分显卡支持GPU直通,允许虚拟机直接访问物理GPU,而不是通过虚拟层介入。这种直通模式也被称为GPU Passthrough。
在传统的虚拟化环境中,虚拟机通常使用虚拟的图形适配器,而不是直接访问物理GPU。这样的虚拟适配器通过宿主操作系统的图形驱动程序提供图形输出。然而,对于某些工作负载,特别是需要高性能图形加速的应用程序(如游戏、计算机辅助设计等),虚拟适配器的性能可能不足以满足要求。
GPU直通模式通过将整个物理GPU分配给虚拟机,使得虚拟机能够直接控制GPU,获得接近原生性能的图形加速。这样,虚拟机中的应用程序就能够利用GPU进行计算和图形处理,而不受虚拟适配器的性能限制。
单张GPU可分配的vGPU是32个,(分片,如果太多可能轮询时间就太长,延迟就明显)
授权检测多种授权类型
需要独立的授权服务器,开机占用授权,关机释放授权
AMD MxGPU(硬切分)它允许将物理GPU资源划分为多个逻辑部分,每个部分可以分配给一个独立的虚拟机。这样,每个虚拟机就能够独享一定比例的GPU性能,而不会受到其他虚拟机的影响。
以下是AMD MxGPU的一些切分方案和特点:
硬件资源切分: MxGPU通过硬件支持,将物理GPU切分为多个虚拟GPU。每个虚拟GPU拥有自己的显存、计算单元等硬件资源。这种硬件级的切分有助于提供较好的性能隔离,确保一个虚拟机的工作不会影响其他虚拟机。
vGPU Profiles: MxGPU引入了不同的vGPU profiles,每个profile对应不同的GPU性能级别和硬件资源。这允许管理员根据实际需求为虚拟机选择适当的性能水平,以满足不同用户或工作负载的需求。
动态分配: AMD MxGPU支持动态分配GPU资源。这意味着管理员可以在运行时动态调整每个虚拟机的GPU性能水平,以适应不同的工作负载和用户需求。
GPU共享: AMD MxGPU还支持GPU共享,允许多个虚拟机在需要时动态共享未使用的GPU资源。这种灵活性有助于提高整个系统的资源利用率。
AMD MxGPU的切分方案为虚拟化环境提供了一种有效管理和分配GPU资源的方法,尤其适用于需要在虚拟化环境中运行图形密集型工作负载的场景。
方案组成硬件:搭载的显卡支持GPU虚拟化
软件:非常小,不通过驱动进行切分
无需授权:基于硬件实现,不需要软件授权
SR-IOV(Single Root I/O Virtualization)是一种用于虚拟化的技术,旨在提高网络和存储设备在虚拟化环境中的性能。该技术允许物理设备在多个虚拟机之间进行硬件级别的切分,而不会牺牲性能。(PF -> VF -> IOMMU直通)
资源调度原理PF拓展出的每个VF就是一个实例,相当于一个独立的PCIE设备,对主板而言,有多少VF就有多少个物理卡
独享资源:显存独占,有独立的PCI配置
共享资源:流处理(存疑),也查到用户在所有时间占用部分计算资源
不想英伟达,需要经过很多层,通过IOMMU(i/o memory unit)可以将物理设备地址对应到不同的虚机中。也就是说物理设备在划分为相应的VF之后,每个VF只能寻址虚机0所涉及的地址范围,无法访问其他虚机地址(安全),同时不需要经过中间那么多层的翻译和信息传递,CPU消耗也较小。
硬件虚拟化的价值虚拟化对硬件损耗小,不需要VMM(虚拟化层)翻译,节省CPU资源
每个虚拟机获得的性能更平均,更稳定
安全性更好(IOMMU)
限制说明单块GPU切分的桌面数必须是偶数(一张卡有两个GPU,但是只能有一个配置文件)
整个服务器无论有几张卡,都只能有一个配置
硬件切分 vs 软件切分 硬件虚拟化软件虚拟化为什么需要GPU虚拟化:
资源共享:GPU性能过强,资源浪费
资源隔离:显存,算力隔离
隔离场景
容器
虚机
应用场景
虚拟桌面
渲染
AI计算
用户层虚拟化本地API拦截和APIforwarding
在用户态实现一个函数,然后实现底层库的所有API
libwarapper拦截所有函数调用,然后对参数进行解析,然后用参数去调用实际的底层库,然后把结果返回给APP。(编译器可以使用静态或者动态链接)
静态链接(Static Linking) 程序所依赖的库和模块会在编译和链接时直接复制到可执行文件的二进制代码中。这样生成的可执行文件体积比较大,但运行时不需要外部的共享库。
动态链接(Dynamic Linking) 程序所依赖的库和模块不会被复制到可执行文件中,而是在编译时只 embed 引用路径。运行时通过这些路径引用(linking)外部的共享库文件。这样生成的可执行文件体积比较小,但需要外部的共享库支持。
远程API forwarding
可以实现 GPU 池化:即多个 GPU 可以组成调用池,由多个 client 来调用,可以做到让不具备 GPU 的机器能实现 GPU 的功能。
传输过程中可能需要进行序列化和反序列化
远程API调用(Remote API Forwarding)的一般过程是:
客服端程序(虚拟机中的应用程序)通过特定语言(如REST)调用预定义的API接口。
调用请求送到客服端操作系统的接口模块。
接口模块将请求进行封装编码,通过网络发送给虚拟化管理程序。
虚拟化管理程序(通常在服务端)接收请求,解析请求参数,执行相应动作。
执行完成后,虚拟化管理程序将结果编码封装成应答包。
将应答包通过网络发送给客服端操作系统。
接口模块在客服端操作系统接收到应答包,进行解码解析。
将执行结果返回给发起调用的客服端应用程序。
这样通过网络进行编码解码、传输的调用请求与应答,构成了客服端应用程序与服务端虚拟化管理程序之间的远程API调用机制。
相比半虚拟化,远程API调用增加了网络通信的开销,但是对客服端操作系统无需修改,更易实现与语言无关的访问接口。两者各有优劣。
半虚拟API forwarding
APP 和 libwrapper 运行在虚机中;
在虚机内核里面要实现virtio的前端
host端需要实现virtio的后端
通过这两个前后端进行通信,然后由host端调用真实的功能
virtio通过共享内存的方式在guest和host端共享数据,减少了数据拷贝
运行过程:
客服端操作系统(Guest OS)通过特定的指令或者函数调用发起对虚拟化层的请求。这些特定的调用就是半虚拟化API,如hypercall、VMCALL等。
这些半虚拟化API调用会被客服端OS中的接口层(Paravirtualized Interface Layer)拦截。接口层预先定义了这些调用和参数之间的映射关系。
接口层将获取到的来自客服端OS的请求参数,根据事先定义的映射协议,翻译并封装为hypervisor可以识别的格式。
然后调用vminstruction等机制,触发VMexit或异常,将请求发送给底层的虚拟机监控器(VMM)或者hypervisor。
hypervisor接收到请求后,解析请求参数,执行相应的操作,并返回响应结果。
接口层再次拦截返回结果,并根据映射关系翻译成客服端OS可以识别的格式。
最后将结果返回给发起请求的客服端OS或应用程序。
通过这种协作的流程,实现了在不完全模拟硬件的情况下,使客服端OS可以与虚拟化层进行交互和请求处理。从而获得较高的执行效率。
hypervisor,也称为虚拟机监控器(VMM),运行在host端,即物理服务器上。它允许在一台物理机器上运行多个虚拟机,实现硬件资源的虚拟化和分配。
具体来说,hypervisor的位置是在硬件和guest操作系统之间,它直接在物理服务器硬件上运行。针对不同类型的虚拟化技术,hypervisor的实现方式会有所不同:
在完全虚拟化(Full Virtualization)中,hypervisor实现了对处理器、内存和设备的模拟,用于为上层的guest操作系统提供一个完全虚拟化的平台。
在像KVM这种基于主机的虚拟化(Hosted Hypervisor)中,hypervisor运行在主机操作系统内核中,利用内核的虚拟化特性。
在半虚拟化(ParaVirtualization)技术下,hypervisor与guest操作系统通过预定义的虚拟化API进行交互。
而对于像Docker这样的容器虚拟化,其底层也依赖于主机的hypervisor或容器引擎来进行资源分配、隔离等。
所以,总的来说,hypervisor属于虚拟化层,运行在物理主机端,用于管理虚拟机以及与之对接的硬件资源。它在客服端操作系统之下,主机硬件之上。
半虚拟化 vs 远程API调用
半虚拟化远程forwarding正常驱动方式
app调用底层库,底层库调用驱动,驱动调用硬件。其中底层库与驱动是通过设备文件来访问的,因此拦截的关键点是设备文件。
内核层GPU驱动拦截:实现一个内存拦截模块,他是运行在driver上面 。就是拦截了app到底层driver的调用。
正常驱动方式是app调用底层库,底层库调用驱动,驱动调用硬件。其中底层库与驱动是通过设备文件来访问的,因此拦截的关键点是设备文件。
内核拦截模块实际调用driver
返回的时候内核拦截模块在进行解析
拦截的不是API,拦截的是系统调用,因此需要了解底层库调用GPU驱动的系统调用的含义(需要文档或者逆向)
适合容器应用,不适合虚机,因为容器共享宿主操作系统的内核,而虚拟机通常运行独立的操作系统内核。在虚拟机中,由于每个虚拟机都有自己的内核,GPU驱动拦截可能需要更多的复杂性和性能开销。容器中的内核共享可以简化GPU驱动的管理和性能优化
内核拦截模块只需要拦截必要的系统调用(想做显存隔离就只拦截分配和释放显存的调用,算力就找算力调用)
内核层GPU半虚拟化(虚机场景)
正常调用结果是虚机内到GPUDriver,由于无法直接接触硬件,因此需要通过从guest切换到远程/本地的hypervisor,然后通过驱动代理访问真实的Driver,
APP 和底层库都在 VM 里;
结合硬件虚拟化支持类似 vGPU 功能
GPU硬件虚拟化硬件虚拟化基础
CPU硬件虚拟化
IOMMU
全虚拟化/透传GPU
GPUDriver不需要做任何修改
GPU直接透传给虚机,性能损耗最小
相当于把整块GPU给虚机,无法实现GPU资源共享,不属于GPU虚拟化
NVIDIA vGPU(软件切分)
通过内核层虚拟化,独享的,算力是时间片全部占用
中间过程较多,损耗比较大,软件收费
其中显存是固定切分的
NVIDIA MIG(硬件切分)
可以直接把 GPU 切分多分,每一份资源硬件隔离;
每一 MIG 的切分,可以当作一个 GPU 来使用,同时可以结合容器来部署
NVIDIA MIG vGPU
算力,显存都直接按照MIG进行硬件切分然后分配给VM
MIG直接将MIG实例分配给用户,MIG vGPU则引入了虚拟化软件层,允许多个虚拟机共享同一GPU,提供了更大的灵活性,但是也需要额外的开销
AMD MxGPU
通过SRIOV的方式将GPU切分为PF(Physical Function)和VF(Virtual Function)
PF(Physical Function):
PF 是硬件设备的实际物理功能。对于网络适配器,PF 通常是指整个物理网卡的功能,而对于 GPU,PF 则是指整个物理显卡的功能。
PF 负责直接与物理硬件进行通信,控制设备的实际硬件资源,如网络适配器的端口、传输协议、GPU 的计算单元等。
在虚拟化环境中,PF 通常由虚拟化管理程序(如 Hypervisor)直接控制,而不是被分配给虚拟机使用。
VF(Virtual Function):
VF 是对 PF 的虚拟划分,它是 PF 的一个逻辑部分。VF 允许将单个物理设备虚拟化为多个逻辑设备,以便在多个虚拟机之间共享物理设备。
每个 VF 具有自己的配置信息、MAC 地址、虚拟资源等。VF 可以被分配给虚拟机,使虚拟机能够直接访问部分物理设备的功能,而不需要通过 PF 进行中介。
VF 的创建和配置通常由虚拟化管理程序完成,虚拟机可以像访问独立的物理设备一样访问 VF。
GPU虚拟化-技术比较