写点什么

详解 GPU 虚拟化技术

作者:Finovy Cloud
  • 2022 年 6 月 14 日
  • 本文字数:5555 字

    阅读完需:约 18 分钟

详解GPU虚拟化技术

GPU 英文名称为 Graphic Processing Unit,GPU 中文全称为计算机图形处理器,1999 年由 NVIDIA 公司提出。


一、GPU 概述


GPU 这一概念也是相对于计算机系统中的 CPU 而言的,由于人们对图形的需求越来越大,尤其是在家用系统和游戏发烧友,而传统的 CPU 不能满足现状,因此需要提供一个专门处理图形的核心处理器。

GPU 作为硬件显卡的“心脏”,地位等同于 CPU 在计算机系统中的作用。同时 GPU 也可以用来作为区分 2D 硬件显卡和 3D 硬件显卡的重要依据。2D 硬件显卡主要通过使用 CPU 来处理特性和 3D 图像,将其称作“软加速”。


3D 硬件显卡则是把特性和 3D 图像的处理能力集中到硬件显卡中,也就是“硬件加速”。目前市场上流行的显卡多半是由 NVIDIA ATI 这两家公司生产的。


1.1、为什么需要专门出现 GPU 来处理图形工作,CPU 为啥不可以?


GPU 是并行编程模型,和 CPU 的串行编程模型完全不同,导致很多 CPU 上优秀的算法都无法直接映射到 GPU 上,并且 GPU 的结构相当于共享存储式多处理结构,因此在 GPU 上设计的并行程序与 CPU 上的串行程序具有很大的差异。GPU 主要采用立方环境的材质贴图、硬体 T&L、顶点混合、凹凸的映射贴图和纹理压缩、双重纹理四像素 256 位的渲染引擎等重要技术。


由于图形渲染任务具有高度的并行性,因此 GPU 可以仅仅通过增加并行处理单元和存储器控制单元便可有效的提高处理能力和存储器带宽。


GPU 设计目的和 CPU 截然不同,CPU 是设计用来处理通用任务,因此具有复杂的控制单元,而 GPU 主要用来处理计算性强而逻辑性不强的计算任务,GPU 中可利用的处理单元可以更多的作为执行单元。因此,相较于 CPU,GPU 在具备大量重复数据集运算和频繁内存访问等特点的应用场景中具有无可比拟的优势。


1.2、GPU 如何使用?


使用 GPU 有两种方式,一种是开发的应用程序通过通用的图形库接口调用 GPU 设备,另一种是 GPU 自身提供 API 编程接口,应用程序通过 GPU 提供的 API 编程接口直接调用 GPU 设备。


1.2.1、通用图形库


通过通用的图形库的方式使用 GPU,都是通过 OpenGL 或 Direct3D 这一类现有的图形函数库,以编写渲染语言(Shading Language)的方法控制 GPU 内部的渲染器(Shader)来完成需要的计算。


目前业界公认的图形编程接口主要有 OpenGL 和 DirectX 这两种接口。OpenGL 是当前可用于开发可交互、可移植的 2D 与 3D 图形应用程序的首选环境,也是当前图形应用最广泛的标准。OpenGL 是 SGI 公司开发的计算机图形处理系统,是图形硬件的软件接口,GL 为图形库(Graphics Library),OpenGL 应用程序不需要关注所在运行环境所处的操作系统与平台。


只要在任何一个遵循 OpenGL 标准的环境下都会产生一样的可视化效果。与 OpenGL 类似,DirectX (Directe Xtension)也是一种图形 API。它是由 Microsoft 创建的多媒体编程接口,并已经成为微软视窗的标准。为适应 GPU 应用的需求,DirectX 则根据 GPU 新产品功能的扩充与进展及时地定义新的版本,它所提供的功能几乎与 GPU 提供的功能同步


1.2.2、GPU 自身编程接口


GPU 自身提供的编程接口主要由提供 GPU 设备的两家公司提供,分别是括 NVIDIA 的 CUDA 框架和 AMD(ATI)公司于 2006 年提出了 CTM(Close To Metal)框架(备注,最初是 ATI 公司生产 GPU 设备,后被 AMD 收购)。AMD 的 CTM 框架现在已不在使用,主要是 AMD(ATI)于 2007 年推出了 ATI Stream SDK 架构,2008 年 AMD(ATI)完全转向了公开的 OpenCL 标准,因此 AMD(ATI)公司目前已没有独立的、私有的通用计算框架。


2007 年 NVIDIA 公司发布 CUDA (Compute Unified Device Architecture)专用通用计算框架。使用 CUDA 进行通用计算编程不再需要借助图形学 API,而是使用与 C 语言以十分类似的方式进行开发。在 CUDA 编程模型中,有一个被称为主机(Host)的 CPU 和若干个被称作设备(Device)或者协处理器(Co-Processor)的 GPU。


在该模型中,CPU 和 GPU 协同工作,各司其职。CPU 负责进行逻辑性较强的事务处理和串行计算,而 GPU 则专注于执行线程化的并行处理任务。CPU、GPU 各自拥有相互独立的存储器地址空间主机端的内存和设备端的显存。一般采用 CUDA 框架自己进行编程的都是一些大型的应用程序,比如石油勘测、流体力学模拟、分子动力学仿真、生物计算、音视频编解码、天文计算等领域。


而我们一般企业级的应用程序由于开发成本以及兼容性等原因,大多数都是采用通用的图形库来进行开发调用 GPU 设备。


1.3、GPU 如何工作?


GPU 对于通用计算机和图形处理的内部组件主要有两部分: 顶点处理器(Vertex Processor)和子素处理器(Fragment Processor)。这种处理器具备流处理机的模式,即不具有大容量的快存/存储器可以读写,只是直接在芯片上利用临时寄存器进行流数据的操作。



当 GPU 用于图形处理时,此时 GPU 内部的顶点渲染、像素渲染以及几何渲染操作都可以通过流处理器完成。从图中可以看出,此时 GPU 内部的所有流处理器相当于一个多核的处理器,数据可以很方便地在不同的流处理器之间的输入和输出之间移动,同时 GPU 分派器和控制逻辑可以动态的指派流处理器进行相应的顶点,像素,几何等操作,因为流处理器都是通用的。


二、GPU 虚拟化


开始我们的正题,目前虚拟机系统中的图形处理方式有三种:一种是采用虚拟显卡的方式,另一种是直接采用物理显卡,最后是采用 GPU 虚拟化


2.1、虚拟显卡


第一种采用虚拟显卡是现在主流的虚拟化系统的选择,因为专业的显卡硬件价格不菲。目前采用虚拟显卡的这些技术包括:


  • 虚拟网络计算机 VNC (Virtual Network Computing)

  • Xen 虚拟帧缓存

  • VMware 虚拟图形显示处理器 GPU (Graphics Processing Unit)

  • 独立于虚拟机管理器的图形加速系统 VMGL (VMM-Independent Graphics Acceleration)


VNC(Virtual Network Computing)基本上是属于一种显示系统,也就是说它能将完整的窗口界面通过网络,传输到另一台计算机的屏幕上。Windows 服务器中包含的"Terminal Server"即是属于这种原理的设计。VNC 是由 AT&T 实验室所开发的,其采用 GPL(General Public License)授权条款,任何人都可免费取得该软件。VNC 软件要由两个部分组成:VNC server 和 VNC viewer。用户需先将 VNC server 安装在被远程操控的计算机上后,才能在主控端执行 VNC viewer 进行远程操控。


XEN 虚拟帧缓存是指 XEN 提供的一个虚拟的显示设备。该虚拟显示设备采用特权域的 VNC 服务器,因此该虚拟显示设备具有相似的 VNC 接口。客户机在 XEN 虚拟帧缓存中写入数据,然后通过 VNC 协议来传输已修改的图片,最后通知前端进行相应区域的更新。这个虚拟帧缓存设备的源码是来自开源的 Qemu。我们在 XenServer 上看见虚拟机的操作系统桌面界面,即是这种技术的显示。


虚拟网络计算机 VNC 和 XEN 虚拟帧缓存这两种模式至今在虚拟机中仍未提供一定的硬件图形加速能力。由于目前仍没有一个机制能使虚拟机进行访问图形硬件的能力,因此这些虚拟的显示设备都是通过使用 CPU 以及内存的方式对图形数据进行相应处理。并没有采用物理显示设备的功能。


然而 VMGL 这种模式已经实现了这种机制,这个机制通常被称为前端-后端虚拟化机制(Front-end virtualization)。VMGL 这种模式采用这个机制将需要图形处理的数据发送到一个拥有硬件图形加速功能的虚拟监控机上进行相应的图形数据处理。目前存在的比较主流可用于 GPU 应用程序开发的图形处理接口有两类:OpenGL 和 Direct3D


在这两类图形处理接口中,OpenGL 是唯一一类能够在主流操作系统中跨平台操作的图形 API 接口。在虚拟机平台中,VMGL 是首个针对 OpenGL API 进行虚拟化的项目。VMGL 的工作原理是,它在客户端操作系统中部署了一个伪库(Fake Library)用来取代标准的 OpenGL 库,伪库(Fake Library)拥有与标准的 OpenGL 库相同的接口,在客户端操作系统中的伪库也实现了指向远程服务器的宿主机操作系统的远程调用。


这样一来,所有的本地 OPENGL 调用都将被解释为对远程服务器的一次服务请求,远程服务器的宿主机操作系统拥有真正的 OPENGL 库、显卡驱动和物理硬件 GPU,它负责完成 OPENGL 请求并将执行结果显示到屏幕上。由于 VMGL 在整个过程操作中都是完全透明的,因此调用 OPENGL 的应用程序不需要修改源代码也不需要进行二进制改写,无需为虚拟机平台作任何改动。


2.2、显卡直通


显卡直通也叫做显卡穿透(Pass-Through),是指绕过虚拟机管理系统,将 GPU 单独分配给某一虚拟机,只有该虚拟机拥有使用 GPU 的权限,这种独占设备的方法分配方式保存了 GPU 的完整性和独立性,在性能方面与非虚拟化条件下接近,且可以用来进行通用计算。但是显卡直通需要利用显卡的一些特殊细节,同时兼容性差,仅在部分 GPU 中设备可以使用。


Xen 4.0 增加了 VGA Passthrough 技术,因此 XenServer 也拥有了该技术,XenServer 的 Passthrough 就是利用英特尔设备虚拟化(Intel VT-d)技术将显示设备暴露给某一个客户虚拟机,不仅其它客户虚拟机不能访问,就连宿主虚拟机也失去了使用该 GPU 的能力。它在客户虚拟机中实现了显卡的一些特殊细节,如 VGA BIOS、文本模式、IO 端口、内存映射、VESA 模式等,以支持直接访问。使用 Xen Server 的 VGA Pass-Through 技术的 GPU 执行效率高,功能全,但只能被单一系统独占使用,失去了设备复用的功能。


VMware ESXi 中包括一个 VM Direct Path I/O 框架,使用该技术也可以将我们的显卡设备直通给某一虚拟机进行使用。


XenServer 和 VMware 使用的是不同的技术但是实现的效果都是一样的,即将物理显卡设备直通给其中的某一虚拟机使用,以达到虚拟机进行 3D 显示和渲染的效果。


由于显卡直通实际上是由客户操作系统使用原生驱动和硬件,缺少必要的中间层来跟踪和维护 GPU 状态,它不支持实时迁移等虚拟机高级特性。如 XenServer Passthrough 禁止执行 Save/Restore/Migration 等操作。VMware 的虚拟机中,一旦开启 VMDirectPath I/O 功能,其对应的虚拟机将失去执行挂起/恢复、实时迁移的能力。


2.3、显卡虚拟化(GPU 虚拟化)


显卡虚拟化就是将显卡进行切片,并将这些显卡时间片分配给虚拟机使用的过程。由于支持显卡虚拟化的显卡一般可以根据需要切分成不同的规格的时间片,因此可以分配给多台虚拟机使用。其实现原理其实就是利用应用层接口虚拟化(API remoting),API 重定向是指在应用层进行拦截与 GPU 相关的应用程序编程接口(API),通过重定向(仍然使用 GPU)的方式完成相应功能,再将执行结果返回应用程序。


我们现在使用 Citrix 的 3D 桌面虚拟化解决方案中,大部分是使用 NVIDIA 公司提供的显卡虚拟化技术,即是 vCUDA(virtual CUDA)技术,前面我们说过了 CUDA 框架,再此不在说明。vCUDA 采用在用户层拦截和重定向 CUDA API 的方法,在虚拟机中建立物理 GPU 的逻辑映像——虚拟 GPU,实现 GPU 资源的细粒度划分、重组和再利用,支持多机并发、挂起恢复等虚拟机高级特性。


其 vCUDA 的实现原理大概包括三个模块:CUDA 客户端、CUDA 服务端和 CUDA 管理端。以 XenServer 为例,在物理硬件资源上运行着一个 VMM 用于向上提供硬件映像,在 VMM 上运行着若干个虚拟机。其中一个虚拟机为特权虚拟机(Host VM),即为 XenServer 中的 Domain 0,在虚拟机中运行的操作系统称为 Host OS。


Host OS 能够直接控制硬件,系统内安装着原生的 CUDA 库以及 GPU 驱动,使得 Host OS 可以直接访问 GPU 和使用 CUDA。其它的虚拟机属于非特权虚拟机(Guest VM),其上运行的操作系统(Guest OS)不能直接操纵 GPU。在这里我们将 CUDA 客户端称之为客户端驱动,CUDA 服务端称之为宿主机的驱动,CUDA 管理端称之为 GPU 管理器。


2.3.1、客户端


客户端驱动其实质就是我们安装在虚拟机比如 Windows 7 上的显卡驱动程序。主要的功能是在用户层提供针对 CUDA API 的库以及一个维护 CUDA 相关软硬件状态的虚拟 GPU(vGPU)。客户端驱动直接面向 CUDA 应用程序,其作用包括:


  • 1)拦截应用程序中 CUDA API 调用;

  • 2)选择通信策略,为虚拟化提供更高层语义的支持;

  • 3)对调用的接口和参数进行封装、编码;

  • 4)对服务端返回的数据进行解码,并返回给应用。


此外,客户端驱动在第一个 API 调用到来之前,首先到管理端索取 GPU 资源。每一个独立的调用过程都必须到宿主管理端驱动申请资源,以实现对 GPU 资源和任务的实时调度。


此外,客户端驱动同时设置了 vGPU 用来维护与显卡相关的软硬件状态。vGPU 本身实质上仅仅是一个键值对的数据结构,在其中存储了当前使用的地址空间、显存对象、内存对象等,同时记录了 API 的调用次序。当计算结果返回时,客户端驱动会根据结果更新 vGPU。


2.3.2、服务器端


服务端组件位于特权虚拟机(XenServer 术语:特权域)中的应用层。特权虚拟机可以直接与硬件交互,因此服务端组件可以直接操纵物理 GPU 来完成通用计算任务。


服务端面向真实 GPU,其作用包括:


  • 1)接收客户端的数据报,并解析出调用和参数;

  • 2)对调用和参数进行审核;

  • 3)利用 CUDA 和物理 GPU 计算审核通过的调用;

  • 4)将结果编码,并返回给客户端;

  • 5)对计算系统中支持 CUDA 的 GPU 进行管理。


此外,服务端运行的第一个任务是将自身支持 CUDA 的 GPU 设备的信息注册到管理端中。服务端应对客户端的请求时,为每个应用分配独立的服务线程。服务端统一管理本地 GPU 资源,按照一定的策略提供 GPU 资源,并将由于 API 调用修改的相关软硬件状态更新至 vGPU。


2.3.3、管理端


管理端组件位于特权域,在实现 CUDA 编程接口虚拟化的基础上,将 GPU 强大的计算能力和计算资源在更高的逻辑层次上进行隔离、划分、调度。在 CUDA 服务端使用计算线程和工作线程在一定程度上使同在一个物理机上的 GPU 间负载均衡,设置 CUDA 管理端组件在更高的逻辑层次上进行负载均衡,使在同一个 GPU 虚拟集群中的 GPU 负载均衡。


管理端组件调度的原则是尽量使在同一个物理机上的 GPU 需求自给,如果该物理机上具备满足条件的 GPU 资源,在一般情况下,该物理机上的虚拟机的 GPU 需求都重定向到该物理机的 CUDA 服务端。


管理端对 GPU 资源进行统一管理,采用集中、灵活的机制,实现:

  • 1)动态调度:当用户所占资源空闲时间超过一定阈值或者任务结束时,管理端回收该资源,当该用户再次发布计算任务时,重新为其任务分配 GPU 资源;

  • 2)负载平衡:当局部计算压力过大时,调整计算负载,通过动态调度时选择合适的 GPU 资源来分散计算负载;

  • 3)故障恢复:当出现故障时,将任务转移到新的可用 GPU 资源上。

用户头像

Finovy Cloud

关注

一家云基础设备服务供应商。 2022.03.31 加入

云服务器、GPU 服务器、物理主机、IDC 机房租赁等产品及服务。

评论

发布
暂无评论
详解GPU虚拟化技术_人工智能_Finovy Cloud_InfoQ写作社区