Davide Rossetti, Pak Markthub
March 23, 2022
新特性
持久性 GPU 映射
GPU 发起通信
结论
本演讲由Davide Rossetti和Pak Markthub共同呈现。
本团队自GTC 2015以来一直以虚拟形式参与GTC大会,包括:
* GTC 2015
* GTC 2016
* GTC 2017
* GTC 2018
* GTC 2019
* GTC 2021
* GTC 2022(第二次虚拟演讲)
相关录音和资料可在www.nvidia.com/on-demand获取。
本节将概述GPUDirect技术。
GPUDirect技术主要包括四种类型:
GPUDirect SHARED SYSMEM
GPUDirect P2P
GPUDirect RDMA² (GDR)
GPUDirect ASYNC
GPUDirect 技术概览如下:
技术交互图示:
图例:
* 紫色箭头:Shared sysmem
* 绿色箭头:P2P
* 蓝色箭头:RDMA
* 黄色箭头:Async
动机:
* 背景:传统的卸载计算模型涉及使用GPU DMA引擎进行数据拷贝(in/out)、启动/同步计算。
* 加速直接数据路径是为了:
* 降低延迟
* 提高带宽
* 支持新的使用场景(后续将详细介绍)
GPUDirect 技术是Magnum IO的一部分。Magnum IO是一个分层架构,其中GPUDirect位于最底层。
Magnum IO架构层级:
Magnum IO涉及基础技术和基于这些技术构建的库。
库 (libraries):
* NVSHMEM
* NCCL
* UCX
* GDRCopy
* GPUDirect Storage
* libgdsync
* SHARP
技术 (technologies):
* GPUDirect P2P
* GPUDirect RDMA
* GPUDirect Async
* nvidia-peermem¹ / nv_peer_mem
* PeerDirect
¹ nvidia-peermem取代nv_peer_mem。
GPUDirect 技术在多个垂直领域、硬件和软件栈中广泛部署:
¹ https://aws.amazon.com/about-aws/whats-new/2020/11/efa-supports-nvidia-gpudirect-rdma/
下表展示了GPUDirect各项技术在不同NVIDIA硬件系列中的支持情况:
脚注:
下表展示了GPUDirect各项技术在不同平台和互联结构中的支持情况:
脚注:
* ¹ Tegra统一内存。在Xavier上,cudaHostAlloc返回的内存与PCIe和GPU是连贯的。
下表展示了GPUDirect各项技术在不同操作系统中的支持情况:
脚注:
* ¹ 需要SLI模式。
下表展示了GPUDirect各项技术在不同虚拟化环境中的支持情况:
脚注:
* ¹ 在1:1配置中。
* ² 支持Vmware ESXi 7.0 HV或更新版本。
* ³ https://docs.nvidia.com/grid
下表展示了GPUDirect RDMA技术在不同平台和内存分配器中的支持情况:
脚注:
* ¹ 需要具备按需分页和CAPI支持的第三方设备。
* ² 在iGPU管理的内存中映射到cudaHostAlloc内存。
* ³ 系统内存不支持自动迁移。
* ⁴ CUmemAllocationProp中的显式opt-in标志。
NVIDIA H100 GPU 特性带来了多项更新和改进:
* GPU 驱动程序中的 PeerDirect 支持(更新)。
* 为预启动的 GPU 工作启用 GPUDirect RDMA(更新)。
* 持久性 GPU 映射。
* GPU 启动的通信。
GPUDirect P2P (点对点)
* 第四代 NVLink。
* NVLink 带宽增加 50%。
* 450+450 GB/s。
* 更高效率。
* NVswitch SHARP。
GPUDirect RDMA
* PCIe 带宽翻倍。
* PCIe x16 Gen5 链路。
* 每方向有效峰值带宽约为 48 GB/s。
nv_peer_mem2。nvidia-peermem 分发。nv_peer_mem 存在冲突。以下伪代码展示了相关操作:
# cd MLNX_OFED_LINUX-5.2-2.2.0-rhel8.2-x86_64/
# ./mlnxofedinstall
...
# cd NVIDIA-Linux-x86_64-XY/kernel
# make modules
...
CC [M] /root/NVIDIA-Linux-x86_64-XY/kernel/nvidia-peermem/nvidia-peermem.o
LD [M] /root/NVIDIA-Linux-x86_64-XY/kernel/nvidia-peermem.ko
...
cc /root/NVIDIA-Linux-x86_64-XY/kernel/nvidia-peermem.mod.o
LD [M] /root/NVIDIA-Linux-x86_64-XY/kernel/nvidia-peermem.ko
改进的鲁棒性:
nvidia-peermem / nv_peer_mem。向后兼容性:
nvidia-peermem r470.82+、r510+ 中已知的回归。一个小的修复即将推出。
以下表格展示了 PeerDirect 的支持状态:
脚注:
¹ feature backported to selected 5.1+ branches
² need "peerdirect_support=1" kernel module param
³ Issue #2302010 at https://docs.nvidia.com/networking/display/OFEDv512580/Bug+Fixes
新的 API 包括:
* cudaFlushGPUDirectRDMAWritesOptionHost
* cudaFlushGPUDirectRDMAWritesOptionMemOps
* cudaDevAttrGPUDirectRDMAFlushWritesOptions
* cudaDevAttrGPUDirectRDMAWritesOrdering
* cudaGPUDirectRDMAWritesOrderingNone
* cudaGPUDirectRDMAWritesOrderingOwner
* cudaGPUDirectRDMAWritesOrderingAllDevices (<= Ampere)
* H100 (新的优化)
cudaDeviceFlushGPUDirectRDMAWrite (cudaFlushGPUDirectRDMAWritesTarget target, cudaFlushGPUDirectRDMAWritesScope scope)cudaFlushGPUDirectRDMAWritesTargetCurrentDevicecudaFlushGPUDirectRDMAWritesToOwnercudaFlushGPUDirectRDMAWritesToAllDevices步骤:
* CPU: 启动 GPU 工作。
* CPU: 轮询 flag1。 (H100 上不需要)
* NIC: 写入数据。
* NIC: 写入 flag1。
* CPU: cudaDeviceFlushGPUDirectRDMAWrite GPU1。 (H100 上不需要)
* CPU: 写入 flag2。
* GPU1: 观察 flag2 并本地获取数据。
步骤(优化后):
* CPU: 启动 GPU 工作。
* NIC: 写入数据。
* NIC: 写入 flag1。
* GPU1: 观察 flag1 并本地获取数据。
步骤:
* CPU: 在 GPU2 上启动工作。
* CPU: 轮询 flag1。
* NIC: 写入数据。
* NIC: 写入 flag1。
* CPU: cudaDeviceFlushGPUDirectRDMAWrite GPU1。
* CPU: 写入 flag2。
* GPU2: 观察 flag2 并获取数据。
gpu1_data 和 flag1 内存注册对象之间存在握手。cudaFlushGPUDirectRDMAWritesTargetCurrentDevice,cudaFlushGPUDirectRDMAWritesToAllDevices,因为 GPU1 数据由 GPU2 消费。// 在远程主机上,伪代码
ibv_post_send(gp, (RDMA_WRITE, gpui_data_mr.rkey,
gpui_data_ptr, localdata));
ibv_post_send(gp, (RDMA_WRITE, flag1_mr.rkey, flag1_ptr,
0x1));
// 在 CPU 工作线程上
int dev_ordering = 0;
cudaDeviceGetAttribute(&dev_ordering,
cudaDevAttrGPUDirectRDMAWritesOrdering, gpui);
cudaSetDevice(gpui);
...
wait_value(flag1, 0x1);
if ((int)cudaGPUDirectRDMAWritesOrderingAllDevices >
(int)dev_ordering)
{
cudaFlushGPUDirectRDMAWrite(
cudaFlushGPUDirectRDMAWritesTargetCurrentDevice,
cudaFlushGPUDirectRDMAWritesToAllDevices);
}
set_value(flag2, 0x1);
// 在 GPU2 上
__device__ void _user_krn() {
wait_value(flag2, 0x1);
fetch(gpui_data, &localbuf);
calculate(localbuf);
}
这是一个关键的架构图,展示了常规映射的工作原理:
流程:
1. 应用程序在用户空间中调用 cuMemAlloc 进行内存分配,并在内核空间中通过 ibv_reg_mr 注册内存区域。
2. 这些请求通过 nv_peer_mem / nvidia_peermem 模块处理。
3. nv_peer_mem / nvidia_peermem 调用 nvidia_p2p_get_pages 来获取页面,并设置回调函数。
4. NIC 驱动程序调用 nvidia_p2p_dma_map_pages 来映射 GPU DMA 地址。
5. NVIDIA 驱动程序负责 Pin (锁定) 并暴露 DMA 地址。
6. 最终,NIC 和 GPU 通过 DMA 进行硬件层面的通信。
这是一个关键的架构图,展示了常规映射失效的过程:
问题:如果失效需要等到适当的拆卸 (tear down) 完成怎么办?
失效流程:
1. 应用程序调用 cuMemFree 释放内存,并通过 ibv_dereg_mr 取消注册内存区域。
2. 一个 free_callback 被触发并发送给 NVIDIA 驱动程序。
3. nv_peer_mem / nvidia_peermem 向 NIC 驱动程序发送 mapping invalidation 请求。
4. NIC 驱动程序向硬件 (NIC) 发送进一步的 mapping invalidation 请求。
5. DMA 连接在硬件层面被移除。
6. NVIDIA 驱动程序向硬件 (GPU) 发送 free 命令。
nvidia_p2p_get_pages(va=ptr, callback=free_callback);free_callback 在物理 GPU 内存分配被释放时触发。
cuMemFree、cuCtxDestroy 或在应用程序拆卸期间。Pinned (锁定) 生命周期 = PCIe 映射和 GPU 内存生命周期 ≤ 应用程序的生命周期。
nvidia_p2p_get_pages(va=ptr, callback=NULL);PCIe BAR 映射和相关 GPU 内存的生命周期被扩展,直到调用 nvidia_p2p_put_pages。
支持 GPU 启动的高性能通信的重要组成部分 (下一主题)。
目前支持裸金属和直通 PCIe GPU。
从 NVIDIA 驱动版本 510.47.03 开始可用。
nv_peer_mem v1.3 及更高版本支持此功能。本节介绍 GPU 发起通信。
CPU 代理的反向卸载:
GPU 发起通信概述。
GPU 发起通信与 CPU 代理性能对比:
路线图。
反向卸载通信技术
在 DGX-A100 上通过 IB 在 2 个 GPU 之间进行测试
在 DGX-A100 上通过 IB 在 2 个 GPU 之间进行 8B 消息大小测试
在 2 个 DGX-A100 上通过 IB 进行测试
在 2 个 DGX-A100 上通过 IB 进行 64B All-to-All 测试
在 2 个 DGX-A100 上通过 IB 进行 1k x 1k 64 位元素矩阵转置