背景和目标
- 提高资源利用率:让多个任务或用户可以共享同一GPU,而不是每个任务或用户都需要独占一个GPU。
- 降低成本:提高GPU利用率可以帮助降低单位任务的计算成本。
- 提高性能:通过合理的调度策略,可以减少任务之间的冲突,提高整体性能。
- 提供公平性:在多用户或多任务的环境下,需要保证每个用户或任务都能公平地获取到GPU资源。
- 保证任务的隔离性:虽然让多个任务共享一个GPU可以提高资源利用率,但也需要保证任务之间的隔离性,防止一个任务影响到其他任务的运行。
技术介绍
共享
...
Labels:
nvidia.com/gpu.count=4
nvidia.com/gpu.product=Tesla-T4-SHARED
nvidia.com/gpu.replicas=4
Capacity:
nvidia.com/gpu: 16
...
Allocatable:
nvidia.com/gpu: 16
...
隔离
目前GPU隔离主要分为三种:
- 显存隔离:指将 GPU 的显存资源进行隔离,按部署服务的配置文件中所声明的资源定义分配给对应服务,每个服务所分配的显存资源之间互不影响。
- 算力隔离:指将 GPU 的计算能力进行隔离,按比例分配给共享 GPU 的任务上。
- 故障隔离:fatal exception发生时会影响其他应用。
技术方案
英伟达方案
NVIDIA GPU 硬件结合 CUDA 编程模型,提供了许多不同的并发机制,以提高 GPU 的利用,用户可以根据自身需求选择不同的技术方案。
CUDA 多进程服务
MPS —— 它通过将多个进程的 CUDA Context,合并到一个 CUDA Context 中,省去了 Context Switch 的开销,也在 Context 内部实现了算力隔离。如前所述,MPS 的致命缺陷,是把许多进程的 CUDA Context 合并成一个,从而导致了额外的故障传播。所以尽管它的算力隔离效果极好,但长期以来工业界使用不多,多租户场景尤其如此。
Time Slicing
英伟达的Time Slicing是一种基于时间片的GPU共享调度策略,这种策略能让多个任务在同一个GPU上进行,而不是每个任务都独占一个GPU。这种策略的核心原理就是将时间分割成一系列的小片段,然后将这些时间片轮流分配给不同的任务。
多实例 GPU ( MIG )
迄今为止讨论的机制要么依赖于使用 CUDA 编程模型 API (如 CUDA 流)对应用程序的更改,要么依赖于 CUDA 系统软件(如时间切片或 MPS )。
使用 MIG ,基于 NVIDIA 安培体系结构的 GPU ,例如 NVIDIA A100 ,可以为 CUDA 应用程序安全划分多达七个独立的 GPU 实例,为多个应用程序提供专用的 GPU 资源。这些包括流式多处理器( SMs )和 GPU 引擎,如复制引擎或解码器,为不同的客户端(如进程、容器或虚拟机( VM ))提供定义的 QoS 和故障隔离。
当对 GPU 进行分区时,可以在单个 MIG 实例中使用之前的 CUDA 流、 CUDA MPS 和时间切片机制。
vGPU
NVIDIA vGPU 使具有完全输入输出内存管理单元( IOMMU )保护的虚拟机能够同时直接访问单个物理 GPU 。除了安全性之外, NVIDIA v GPU 还带来了其他好处,如通过实时虚拟机迁移进行虚拟机管理,能够运行混合的 VDI 和计算工作负载,以及与许多行业虚拟机监控程序的集成。值得注意的是,使用vGPU需要license,购买license的费用需要考虑在技术选型里面。
英伟达各技术对比
内核劫持
实现GPU共享调度的隔离性,还可以通过劫持内核驱动的方式实现。需要一个内核态的GPU共享模块,它位于Nvidia驱动层之上,这样在公有云环境中相对更加安全。cGPU的资源隔离是通过劫持对驱动的调用实现的,并通过设置任务占用的时间片长度来调控任务占用的计算能力。具体如何精确控制上下文切换的时间细节不明。由于Nvidia驱动不是开源的,要获取驱动相关的方法名和ioctl参数结构,需要进行一些逆向工程。这种实现方式对用户来说是无感知的。
vCUDA
劫持CUDA API同样是一种可行的方案,比如开源的vCUDA项目。其系统架构与NVIDIA的GRID架构相似,通过引入一个负责管理GPU的Manager组件,该组件能够调控容器的GPU计算能力和显存资源,确保用户无法超出其申请的显存使用,同时保持GPU的平均使用率在申请值范围内。这一设计仅涉及CUDA层的改动,因此,用户的程序无需重新编译,就能运行在基于vCUDA的GPU共享环境中。但是它也有一些问题,一是需要替换CUDA库,并确保版本一致,二是在部分使用场景下,可能会出现兼容性问题。
技术示例
实现共享调度最简单的方式是使用英伟达的time-slicing技术。要使用该技术提交time-slicing配置configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: time-slicing-config
data:
any: |-
version: v1
flags:
migStrategy: none
sharing:
timeSlicing:
renameByDefault: false
failRequestsGreaterThanOne: false
resources:
- name: nvidia.com/gpu
replicas: 4
将gpu扩展成4个副本。然后安装GPU operator
$ helm install gpu-operator nvidia/gpu-operator \
-n gpu-operator \
--set devicePlugin.config.name=time-slicing-config
最后验证节点信息是否生效
kubectl describe node <node-name>
最后可看到扩展后的GPU资源
...
Labels:
nvidia.com/gpu.count=4
nvidia.com/gpu.product=Tesla-T4-SHARED
nvidia.com/gpu.replicas=4
Capacity:
nvidia.com/gpu: 16
...
Allocatable:
nvidia.com/gpu: 16
...