之前在一篇文章
中介绍了NvidiaGPU架构的演进历史及其在AI任务中的优化,重点探讨了Nvidia通过提升GPU结构、内存系统(如HBM、L1/共享缓存)以及GPU间互联技术(如NVLink、NVSwitch)来满足大模型时代对大数据处理和分布式计算的需求。
如上图所示, AI任务对于GPU资源的利用方式,以任务视角切入GPU资源的调度,从宏观到微观可以划分为:
云边端:
云-边-端、多云及混合组网下任务分配情况。不同任务分配对于整体架构的要求 GPU集群资源调度:任务并行、串行;时间和空间的平衡。
多机多卡调度:
多机器组网情况下,资源调度对于机器高速网络的拓扑需求。
单机多卡调度:
资源调度对于GPU、CPU、PCIE、GDDR等组网感知。
单卡调度:
单卡独占分配,单卡多任务分配,多任务隔离/共享。
此篇文章会基于GPU基础,从GPU算力角度出发,探寻在面对AI时代带来的‘大参数、大数据、大并行运算’场景下,客户如何利用云原生带来的高效GPU算力管理能力,实现高GPU更高利用率,以便实现最佳效益。其中部分挑战,目前也没好的单一技术办法,或者是客户的AI的业务需要从整体平台架构上去考虑解决途径。
目前客户的整体技术架构朝着多云/边缘云方向发展,一方面是客户技术发展带来的结果,另一方面是业务需求带来的必然结果。那么对于AI任务来说,之前在单一云,或者单一节点上,只需要考虑任务的
一次调度
,即任务从开始到结束只需要被调度一次。但是在‘云-边-端’架构体系下,任务需要经历
多次调度
,即任务会随着端侧具体的业务场景需要,会从云、边、端来回迁移。
下面举个典型的案例,在
汽车自动驾驶
场景中:
云:
客户使用的云侧的集中AI能力。整个架构中AI计算能力最强,延迟最高。
边:
客户区域化中心AI能力(可能部分客户没有区域化中心),AI能力次之,延迟次之。
端:
每一台汽车的AI能力。AI能力最弱,延迟最低。由此可见,从云-边-端,对于汽车来说延迟是逐步增加的,可能是几百ms-几十ms-几ms。
-
当汽车驾驶员没有开启自动驾驶能力时,相关的比如地图、游戏、音乐、智能助手等任务会运行在汽车芯片上。
-
当开启自动驾驶后,如果本地运算能力不够。自动驾驶任务肯定要优先运行在汽车芯片上,其他的任务会被迁移调度到边缘/云侧。
-
当自动任务驾驶任务结束后,云/边缘的任务又要被调度回汽车芯片。
从计算core微观上看,core处理程序遵循着分时调度的原则,单个线程占用的资源不会超过一个core。但是从宏观角度上看,一个任务所占用的资源可以是少于一个core,也可以多个core,甚者多台机器或服务器。比如AI任训练务的特征‘大数据、大参数、大并行运算’往往需要大量的core参与数据搬运、数据训练等。所以任务可以分为
串行和并行
。
串行处理
意味着按顺序逐一执行任务,通常适用于计算资源有限而任务尺寸较大的情况。这种方式通过增加计算时间来减少对计算资源的需求。
并行处理
则是同时执行多个任务片段,利用更多的计算资源来缩短总的计算时间,这被称为并行加速。当面对长时间运行的任务时,可以通过将其拆解为多个短任务并在不同的计算资源上并行执行,以此达到节省时间的效果。
现阶段一方面GPU资源很紧俏,非常难购买,即使购买到,GPU卡之间的拓扑结果、多台机器之间的拓扑结果对任务的训练时间也有很大的影响;另一方面企业的AI任务多种多样,也不可能专门为每一种AI任务单独适配GPU卡分配。
所以更多的期望是将有限的GPU资源池化后,由统一的平台实现这些GPU资源面对不同的AI任务,实现不同的资源调度,以便实现GPU资源利用率和AI任务预期结果的双赢的记过。
随着AI训练带来的参数量和数据量的增长,单机器的训练能力已经不满足AI任务的需求,训练模式逐渐被集群训练所取代,Nvidia除了推出GPU卡外,也推出了了比如GB200这种多机器的组合集群。
尽管从AI集群上看,是个单一的训练任务,但是其实内部会被拆分成多个子服务运行在不同的GPU服务器上的GPU卡上。
这里的核心挑战在于如何管理和优化这些小任务之间的交互,当不同任务所需要的数据存储在其他机器上时,如何快速的搬运这些数据时提高整体AI训练的关键。
对于阿里云的GPU机器,比如gn8v,ebmgn8v等提供一机一卡/一机两卡/一机四卡/一机八卡等多种规格应对不同的AI任务对算力的需求。但是这些卡数的增加不是算力上的纯粹增加,其实还涉及到AI任务对于GPU资源调度的分配情况。如果同一个AI任务在无NVLINK情况下,任务分配到同一个CPU下的多个GPU卡,和分配到不同CPU下的GPU卡相比是减少了CPU的接入和切换的。如果不同CPU下GPU之间有数据交互链路,其实跨CPU调度其实影响不大。
所以在多机多卡情况下,机器的GPU、CPU、网络、内存等拓扑链路对于调度分配是很重要的。
现代计算已经从单机模式进化到集群计算,并进一步扩展至跨集群、跨数据中心乃至云边端协同和融合计算。一方面一个大型的资源系统可能运行着来自不同业务部门不同的业务任务,另一方面单个GPU卡的core心越来越多,在GPU-to-GPU的带宽受限情况下,如何让不同业务方的任务并行/独享运行,并能
对不同的任务做好数据缓存间的隔离和资源QoS保障,也是需要考虑的方面。
抛开任务管理层面,也就是把上一节的‘云-边-端’和‘GPU集群任务调度’暂且不讨论,原因是这两部分已经不单单是某个产品,或某一个技术能实现的,这个需要客户从最开始的业务架构的规划、到AI任务管理平台,再到硬件层面的拓扑架构等多方面的技术整合和选型,才能满足所需的AI任务的预期管理。本节主要聚焦在为了满足业务的不同GPU资源使用的诉求,
单卡调度、单机多卡调度和多机多卡调度所发展出来的基础技术。
3.2.1 MPS(单卡多线程并行)
多进程服务(MPS)是对 CUDA 应用编程接口(API)的一种替代性实现,并且与原有的二进制代码兼容。MPS 的运行时架构旨在透明地支持协作式的多进程 CUDA 应用,主要是消息传递接口(MPI)任务。MPS时Nvidia在Pascal架构
引入的,并在Volta架构中进一步的完善。Volat-MPS相比较之前的MPS,主要在以下几个方面做了提升:
-
直接提交任务至 GPU:Volta MPS 客户端可以直接向 GPU 提交任务,无需通过 MPS 服务器。
-
独立的 GPU 地址空间:每个 Volta MPS 客户端拥有独立的 GPU 地址空间,不与其他客户端共享。
-
有限的执行资源分配以保证服务质量 (QoS):Volta MPS支持有限的执行资源分配,以确保服务质量。
MPS优势
-
提高GPU利用率:
MPS使不同进程的内核和内存复制操作可以在GPU上并发执行,提升GPU利用率并加快任务完成速度。
-
减少GPU上下文存储:
MPS服务器为所有客户端共享一份GPU存储和调度资源,减少了资源占用。
-
减少GPU上下文切换:
通过共享调度资源,MPS消除了进程间切换的开销,提高了效率。
适用应用场景
MPS特别适用于那些单个进程不足以饱和GPU的应用。通过在同一节点上运行多个进程,MPS增强了并发性。适用于每网格块数较少的应用;若应用因每网格线程数少而GPU占用率低,使用MPS可提升性能。在强扩展场景中,MPS能有效利用剩余的GPU容量,让不同进程的内核并发执行,优化计算效率。
限制
相关限制
A. 系统限制
操作系统支持:
MPS 仅支持 Linux 操作系统。在非 Linux 操作系统上启动 MPS 服务器将导致启动失败。
Tegra 平台支持:
仅支持 Volta MPS 在 Tegra 平台上运行。
GPU计算能力要求:
MPS 需要计算能力版本为 3.5 或更高的 GPU。如果在应用 CUDA_VISIBLE_DEVICES环境变量后可见的任何一个 GPU 的计算能力低于 3.5,MPS 服务器将无法启动。
统一虚拟寻址 (UVA):
CUDA 的 UVA 功能必须可用,默认情况下,任何在计算能力版本为 2.0 或更高的 GPU 上运行的 64 位 CUDA 程序都启用了 UVA。如果 UVA 不可用,MPS 服务器将无法启动。
页锁定主机内存限制:
MPS 客户端可以分配的页锁定主机内存量受限于 tmpfs 文件系统 (/dev/shm) 的大小。
独占模式限制:
独占模式限制应用于 MPS 服务器,而不是 MPS 客户端。Tegra 平台不支持 GPU 计算模式。
用户限制:
一个系统上只能有一个用户拥有活跃的 MPS 服务器。
用户排队机制:
MPS 控制守护进程会将来自不同用户的 MPS 服务器激活请求排队,不管GPU独占设置如何,也会导致用户之间对 GPU 的串行独占访问。
行为归因:
系统监控和会计工具(例如 nvidia-smi、NVML API)将所有 MPS 客户端的行为归因于 MPS 服务器进程。
B. GPU计算模式限制
nvidia-smi支持设置三种Compute Mode:
-
PROHIBITED:GPU对所有Compute应用都不可用
-
EXCLUSIVE_PROCESS:GPU一次只分配给一个Context(CPU进程),单个CPU进程的线程可以同时向 GPU提交工作
-
DEFAULT:多个CPU进程可以同时使用 GPU。每个进程的各个线程可以同时向 GPU 提交工作。
使用 MPS 实际上会使 EXCLUSIVE_PROCESS 模式对所有 MPS 客户端表现得像 DEFAULT 模式一样。MPS 总是允许多个客户端通过 MPS 服务器使用 GPU。
在使用 MPS 时,建议启用 EXCLUSIVE_PROCESS 模式,以确保只有一个 MPS 服务器使用该 GPU。这提供了额外的保障,确保 MPS 服务器是该GPU上所有 CUDA程序的唯一入口。
C. 应用限制
NVIDIA编解码SDK不支持:NVIDIA视频编解码SDK在Volta架构之前的MPS客户端上不受支持。
仅支持64位应用:只有64位应用程序被支持。
CUDA驱动API版本要求:如果应用程序使用CUDA驱动API,则必须使用CUDA 4.0或更高版本的头文件。
不支持动态并行:如果模块使用了动态并行特性,CUDA模块加载将会失败。
UID一致性要求:MPS服务器仅支持与服务器具有相同用户ID(UID)的客户端运行。如果服务器和客户端的UID不同,客户端应用程序将无法初始化。
流回调不支持:在Volta架构之前的MPS客户端上不支持流回调。调用任何流回调API将返回错误。
CUDA图不支持:Volta MPS 之前的Client上,MPS 不支持具有主机节点的 CUDA Graph。
页锁定主机内存限制:MPS Client应用能够请求的page-locked host memory数量受tmpfs文件系统限制(/dev/shm)
MPS客户端终止的影响:在未同步所有未完成GPU工作的情况下终止MPS客户端(例如通过Ctrl-C、程序异常如段错误、信号等),可能会使MPS服务器和其他MPS客户端处于未定义状态,导致挂起、意外失败或数据损坏。
CUDA IPC支持:由MPS Client创建的CUDA Context与没有使用MPS 创建的CUDA Context之间的CUDA IPC通信在Volta MPS是支持的
参考网站:
https://docs.nvidia.com/deploy/mps/index.html
3.2.2 MIG(单卡单显存多租户线程物理隔离)
使用MIG,每个实例的处理器在整个内存系统中都有独立的路径——片上交叉开关端口、L2缓存库、内存控制器和DRAM地址总线都唯一分配给一个实例。这确保了单个用户的工作负载可以以可预测的吞吐量和延迟运行,具有相同的L2缓存分配和DRAM带宽,即使其他任务正在冲击自己的缓存或饱和其DRAM接口。MIG可以分割可用的GPU计算资源(包括流式多处理器或SM和GPU引擎,如复制引擎或解码器),以提供定义的服务质量(QoS),并为不同的客户端(如虚拟机、容器或进程)提供故障隔离。
从NVIDIA安培一代开始的gpu(即具有计算能力>= 8.0的gpu)支持MIG。下表提供了支持的gpu列表:
GPU在MIG中分为GI和CI单元,其中CI单元是GI单元的subset,共享GI单元的共享内存和带框。而GI之间的算力在物理层面是隔离的。而GI是 GPU 切片和 GPU 引擎(DMA、NVDEC 等)的组合。GI内的任何内容总是共享所有内存和其GPU,但其SM切片可以进一步细分为CI。GI提供内存级别的QoS,每个GPU slice包含专用的GPU内存资源,这些资源限制了可用容量和带宽,并提供内存QoS。每个GPU内存切片获得总物理层面GPU 内存资源的 1/8,每个 GPU SM 切片获得总物理层面SM数量的1/7。CI包含父GI的SM切片和其它GPU引擎(DMA、NVDEC 等)的子集,其共享内存和引擎。比如下图是A100卡可以划分的MIG类型。
相关特性:
-
提高资源利用率:MIG允许从NVIDIA Ampere架构开始的GPU被安全地分割成最多七个独立的GPU实例,用于CUDA应用程序,为多个用户提供独立的GPU资源以实现最佳的GPU利用率。
-
多租户物理隔离:对于具有多租户使用案例的云服务提供商(CSP),MIG确保一个客户不会影响其他客户的工作或调度,同时提供增强的隔离。
相关限制:
A. 系统限制 操作系统支持:MIG 仅支持由 CUDA 支持的 Linux 操作系统发行版。
支持配置:裸金属、容器、
GPU需要重置:在 A100/A30 上设置 MIG 模式需要 GPU 重置(因此需要超级用户权限)。
配置持久化:MIG配置是持久性的,不会随着系统重启而被重置。
驱动限制:所有持有驱动程序模块句柄的守护进程需要在启用 MIG 之前停止。
权限配置:切换 MIG 模式需要 CAP_SYS_ADMIN 能力。其他 MIG 管理,如创建和销毁实例,默认需要超级用户,但可以通过调整 /proc/ 中 MIG 能力的权限委托给非特权用户。
B. 应用限制
图形不支持:不支持图形API(例如OpenGL、Vulkan等)。
不支持G2C:不支持GPU到GPU的P2P(无论是PCIe还是NVLink)。
物理隔离:CUDA应用程序将计算实例及其父GPU实例视为单个CUDA设备。
跨实例调用限制:不支持跨GPU实例的CUDA IPC。跨计算实例的CUDA IPC是支持的。
MPS支持:CUDA MPS在MIG之上支持。唯一的限制是最大客户端数(48)会根据计算实例的大小按比例降低。
GDR支持:当从GPU实例使用时,支持GPUDirect RDMA。
参考文档:
https://docs.nvidia.com/datacenter/tesla/pdf/NVIDIA_MIG_User_Guide.pdf
3.2.3 阿里云cGPU(单卡算力和显存分配)
GPU容器共享技术cGPU是阿里云基于内核虚拟GPU隔离的容器共享技术。即多个容器共享一张GPU卡,从而实现业务的安全隔离,提高GPU硬件资源的利用率并降低使用成本,可以实现
显存或算力
两个维度的隔离和组合。
适用应用场景
兼容性好:
适配标准的Docker和Containerd工作方式,无缝兼容k8s。
操作简单:
无需重编译AI应用,运行时无需替换CUDA库。
资源灵活划分:
物理
GPU
的资源可以进行任意划分。
GPU实例规格无限制:
GPU裸金属实例,
虚拟化
实例,vGPU实例等各种GPU实例。
应用场景丰富:
支持在离线混部业务、支持CUDA AI和渲染应用场景。
功能强大:
高优先级抢占功能和较高可运维能力,支持热升级、支持多卡划分功能。
共享GPU调度的文件可以在系统的procs中找到,路径是/proc/cgpu_km
├── 0 #GPU序号
│ ├── aaa7d95f0dbf #被调用在此的容器ID
│ │ ├── highprio #容器优先级
│ │ ├── id
│ │ ├── meminfo #显存和剩余显存大小
│ │ ├── memsize #容器内的显存大小
│ │ └── weight #容器获取显卡最大算力的权重,默认值为1
│ ├── free_weight #该GPU分配pod的权重
│ ├── major
│ ├── max_inst #用于设置容器的最大数量,取值范围为1~25
│ ├── policy #cGPU算力调度策略
│ └── prio_ratio #高优先级容器最大可以抢占的算力。取值范围:20~99。
├── 1
│ ├── free_weight
│ ├── major
│ ├── max_inst
│ ├── policy
│ └── prio_ratio
├── default_memsize #如果没有设置ALIYUN_COM_GPU_MEM_CONTAINER参数
├── inst_ctl
├── upgrade #控制热升级
└── version #cgpu设备版本号
ALIYUN_COM_GPU_MEM_DEV
|
设置GPU实例上每张显卡的总显存大小。
该参数值与实例规格有关,显存大小按GiB取整数。
对于ecs.gn6i-c4g1.xlarge实例,配备1张NVIDIA Tesla T4显卡,在GPU实例上执行nvidia-smi可查看总显存大小。
|
ALIYUN_COM_GPU_MEM_CONTAINER
|
设置容器内可见的显存大小,与
ALIYUN_COM_GPU_MEM_DEV
结合使用。例如:
在一张总显存大小为15 GiB的显卡上,设置
ALIYUN_COM_GPU_MEM_DEV=15
和
ALIYUN_COM_GPU_MEM_CONTAINER=1
,即效果表示为容器分配1 GiB的显存。设置为0或未设置表示禁用cGPU。
|
cGPU服务加载cgpu_km的模块时,会按照容器最大数量(max_inst)为每张显卡设置时间片(X ms),用于为容器分配GPU算力。
Policy
|
说明
|
平均调度(policy=0)
|
在创建容器时,为容器分配时间片。cGPU服务会从Slice 1时间片开始调度,提交任务到物理GPU,并执行一个时间片(X ms)的时间,然后切换到下一个时间片。每个容器获得的算力相同,都为1/max_inst。
|
抢占调度(policy=1)
|
在创建容器时,为容器分配时间片。cGPU服务会从Slice 1开始调度,但如果没有使用某个容器,或者容器内没有进程打开GPU设备,则跳过调度,切换到下一个时间片。
|
权重抢占调度(policy=2)
|
如果在创建容器时设置ALIYUN_COM_GPU_SCHD_WEIGHT大于1,则自动使用权重抢占调度。cGPU服务按照容器数量(max_inst)将物理GPU算力划分成max_inst份,但如果ALIYUN_COM_GPU_SCHD_WEIGHT大于1,cGPU服务会将多个时间片组合成一个更大的时间片分配给容器。
|
固定算力调度(policy=3)
|
通过指定ALIYUN_COM_GPU_SCHD_WEIGHT和max_inst的占比,固定算力的百分比。
|
算力弱调度(policy=4)
|
为容器分配时间片,隔离性弱于抢占调度。
|
原生调度(policy=5)
|
只用来做显存的隔离。原生调度表示NVIDIA GPU驱动本身的调度方式。
|
3.3.1 PCIE&NVLink&NVSwitch(单机多卡组合)
PCIE设备在单机内可以实现多个设备的数据传输,比如上图就是一个典型的8卡机器内的,GPU通过PCIE实现设备之间的互联,但是NIC、NVME、GPU是共享一个PCIE的总带宽的。如果涉及跨CPU的GPU之间通信,则会被CPU之间的链路限制。比如图示的GPU0-GPU1会收到PCIE0的影响,GPU3-GPU5会经过两个CPU之间的交互。
所以资源调度使用的GPU间拓扑架构对任务整体表现是具有很大影响的。
除了PCIE可以实现将单机的GPU卡互联,实现算力的切换掉配,但是PCIE的带宽是多个设备共享,并且最新的gen5 双向带宽只有64GB/s,远远小于大模型时代数据搬运的需求。NVLink Nvidia开发的是一种双向 GPU-GPU 直接互连技术,其5.0版本可提供高达 1800 GB/s 的带宽,比 PCIe 5.0 高出14倍。它连接了英伟达的 Grace CPU 和 Hopper GPU,显著增强了处理大规模AI模型的能力。作为先进的互联标准,NVLink 不仅优化了总线设计和通信协议,还通过点对点架构和串行传输技术提高了数据交换效率。NVSwitch,作为一个独立的 NVLink 芯片,支持最多18个 NVLink 连接,进一步提升了多GPU环境中数据流通的速度和并行处理复杂任务的效率。
但是虽然GPU之间绕过了PCIE网卡的限制,但是GPU之间的通信能力,取决于NVLink的数量,如图所示GPU0-GPU6只有1条NVLink,GPU3-GPU5之间有2条。在Ampere架构之后,Nvidia引入了NVSwitch,使单个机器内任何GPU卡之间的带宽链路获得了一致性,并且在Hopper架构中将NVLink引入到了机器之间,实现了服务器组的多GPU卡联通的一致性。
这也是为什么客户AI任务需要了解底层GPU拓扑架构,不同的架构也需要适配不同的算力调度分配。
3.3.2 阿里云cGPU(多卡算力和显存分配)