在现代高性能计算 (HPC) 和人工智能 (AI) 领域,数据量的爆炸式增长与模型复杂度的不断提升,使得数据传输效率日益成为系统性能的关键瓶颈。传统架构中,GPU 与其他设备(如网卡、存储)的数据交互通常需要 CPU 作为“中转站”,这不仅引入了额外延迟,也消耗了宝贵的 CPU 计算资源。
为解决这一核心矛盾,NVIDIA 推出了 GPUDirect 系列技术。这是一组旨在加速 GPU 与其他 PCIe 设备(如网络接口卡 NIC、存储设备以及其他 GPU)之间直接通信的技术集合。本文将深入剖析其中两项关键技术:GPUDirect RDMA 与 GPUDirect Storage (GDS),并探讨其在构建高效能计算系统中的应用。
2. GPUDirect RDMA 技术
官方文档参考:GPUDirect RDMA Documentation
GPUDirect RDMA (Remote Direct Memory Access) 是一项允许第三方 PCIe 设备(如高性能网卡、存储适配器等)直接访问 NVIDIA GPU 显存的技术。该技术最早随 Kepler 架构 GPU 和 CUDA 5.0 引入,其核心目标是消除 GPU 与第三方设备通信时不必要的 CPU 介入与系统内存拷贝。
2.1 技术背景与痛点
在未启用 GPUDirect RDMA 的传统架构中,GPU 通过网络发送数据需经历“GPU 显存 -> 系统内存 (CPU 参与) -> 网卡”的冗长路径:
- 数据拷贝:数据从源 GPU 显存拷贝到源主机的系统内存。
- 网络传输:CPU 参与控制,网卡 (NIC) 从系统内存读取数据并通过网络发送。
- 接收与拷贝:目标主机网卡将数据写入系统内存,再由 CPU 拷贝到目标 GPU 显存。
这一过程带来了显著的性能瓶颈:
- 高延迟:数据在 PCIe 总线上往返传输,且需要 CPU 处理中断和上下文切换。
- 带宽瓶颈:数据流经系统内存,受限于 CPU 内存带宽,无法充分利用高速网络(如 InfiniBand)或 高速网卡 的潜力。
- CPU 负载高:CPU 必须参与数据搬运和缓冲区管理,无法专注于其核心计算任务。
2.2 工作原理详解
GPUDirect RDMA 利用了标准 PCIe 总线的点对点 (P2P) 功能,使第三方设备能够通过 PCI BAR (Base Address Register) 直接对 GPU 显存进行读写操作。
2.2.1 核心机制
当两个 PCIe 设备(例如 GPU 和 NIC)共享同一个上游 PCIe 交换器或根复合体 (Root Complex) 时,它们可以通过物理地址直接通信。
- PCI BARs 映射:GPU 驱动将其显存的一定区域通过 PCI BARs 暴露在系统的物理地址空间中。
- P2P 直接访问:NIC 可以像访问系统内存一样,直接向这些映射好的 GPU 物理地址发起 PCIe 读写事务。

2.2.2 驱动层交互
GPUDirect RDMA 的实现依赖于 NVIDIA 内核驱动与用户态 CUDA 库的协同工作:
- 地址区分:用户态 CUDA 库提供 API,帮助上层通信库(如 MPI, NCCL)区分某个指针是指向 CPU 内存还是 GPU 显存。
- 页面锁定 GPU 内存:
- 对于 CPU 内存,Linux 内核使用
get_user_pages() 进行锁定。
- 对于 GPU 显存,NVIDIA 内核驱动提供了专用 API(如
nvidia_p2p_get_pages)来锁定 GPU 显存页面,并将其物理地址列表返回给网卡驱动。
- 网卡驱动使用这些物理地址编程其 DMA 引擎,从而建立起直接的数据传输通道。
2.3 性能优势
GPUDirect RDMA 通过在 GPU 和第三方设备间建立直达的数据通道,消除了不必要的系统内存拷贝和 CPU 干预,实现了极致的通信性能。
- 零拷贝:完全消除了 GPU 显存到系统内存的缓冲拷贝。
- 超低延迟:数据直接在设备间传输,端到端延迟可显著降低。
- CPU 完全卸载:CPU 仅需负责建立连接和控制流,数据路径完全被旁路,得以解放算力。
2.4 开发者视角:代码与 API
虽然上层应用通常通过 CUDA-aware MPI 或 NCCL 隐式使用 GPUDirect RDMA,但其底层驱动涉及以下关键步骤:
// 伪代码示例:展示 NIC 驱动如何注册 GPU 显存以进行 RDMA
// 实际上,这通常由 InfiniBand Verbs (libibverbs) 库在用户态封装
// 1. 用户态分配 GPU 显存
void *d_buffer;
cudaMalloc(&d_buffer, size);
// 2. 注册内存区域
// libibverbs 会检测指针类型。如果是 GPU 指针,它将调用 NVIDIA 内核驱动接口
// 来获取 GPU 页面的物理地址,并将其写入网卡的页表。
struct ibv_mr *mr = ibv_reg_mr(pd, d_buffer, size,
IBV_ACCESS_LOCAL_WRITE |
IBV_ACCESS_REMOTE_WRITE |
IBV_ACCESS_REMOTE_READ);
if (!mr) {
// 注册失败,可能因硬件不支持或未加载 nvidia-peermem 模块
fprintf(stderr, "GPUDirect RDMA registration failed\n");
}
// 3. 执行 RDMA 操作
// 网卡硬件 DMA 引擎直接通过 PCIe 总线访问 d_buffer 的物理地址
ibv_post_send(qp, &wr, &bad_wr);
注意:启用此功能通常需要加载 nvidia-peermem(或旧版 nv_peer_mem)内核模块,该模块充当 NVIDIA 驱动与 InfiniBand/RDMA 核心驱动之间的桥梁。
3. GPUDirect Storage (GDS) 技术
官方文档参考:GPUDirect Storage Documentation
随着 AI、HPC 及数据分析领域数据集规模持续增长,数据加载时间开始对应用整体性能产生显著影响。高速 GPU 常常因等待缓慢的 I/O 而处于空闲状态,尤其是在将数据从存储加载到 GPU 显存的过程中。
GPUDirect Storage (GDS) 旨在建立一条在本地或远程存储(如 NVMe SSD)与 GPU 显存之间的直接数据通路。该技术避免了通过 CPU 内存中的“中转缓冲区”进行额外拷贝,使存储设备的 DMA 引擎能够将数据直接传入/传出 GPU 显存,全程无需 CPU 参与数据搬运。
3.1 技术背景与痛点
传统存储 I/O 路径中,将数据从磁盘读到 GPU 显存是一个低效的多阶段过程:
- 内核态缓冲:存储设备通过 DMA 将数据写入操作系统内核的页面缓存。
- 用户态拷贝:CPU 将数据从内核空间拷贝到用户空间的应用程序缓冲区。
- 主机到设备拷贝:CPU 再次将数据从用户缓冲区拷贝到 GPU 显存。
这种“反弹缓冲区”机制存在三大问题:
- CPU 瓶颈:CPU 必须参与每一次内存拷贝,随着 NVMe SSD 速度提升,CPU 逐渐成为 I/O 瓶颈。
- 延迟增加:多次内存拷贝和上下文切换显著增加了端到端延迟。
- PCIe 带宽浪费:数据在 PCIe 总线上来回传输,实际占用了双倍带宽。
3.2 工作原理详解
GDS 引入了全新的 I/O 架构,允许存储控制器直接对 GPU 显存进行 DMA 操作。
3.2.1 核心组件:cuFile API
GDS 提供了一套名为 cuFile 的用户态 API,它类似于 POSIX 文件操作 API,但专为 GPU 显存设计。
- libcufile:GDS 的核心库,负责拦截 cuFile I/O 请求,并智能选择最佳传输路径(直通或回退)。
- nvidia-fs.ko:一个内核模块,负责处理文件系统元数据、页面锁定及 DMA 映射。它与 ext4、xfs 等标准文件系统协同工作,但绕过了内核页面缓存。
3.2.2 DMA 路径选择
当应用调用 cuFileRead 时:
- 页面锁定:
nvidia-fs 模块锁定目标 GPU 显存页面。
- DMA 映射:将 GPU 物理地址提供给 NVMe 驱动程序。
- 直接传输:NVMe 控制器启动 DMA,通过 PCIe P2P 机制直接将数据写入 GPU 显存。
如果硬件或配置不支持 P2P,GDS 会自动回退到传统缓冲模式,但仍会尝试优化。

3.3 核心优势
GDS 通过构建存储到 GPU 的“直通高速公路”,打破了传统 I/O 的带宽和延迟瓶颈。
- 带宽倍增:直接利用 PCIe P2P,吞吐量可接近存储设备或 PCIe 总线的物理极限,带宽可达传统 I/O 的 2-8 倍。
- 延迟最小化:消除了中间的内存拷贝步骤,I/O 延迟显著降低。
- CPU 卸载:CPU 仅处理控制流,不再参与繁重数据搬运,算力得以释放用于数据预处理或其他计算逻辑。
3.4 性能对比数据参考
| 指标 |
传统缓冲 IO |
传统直接 IO (O_DIRECT) |
GPUDirect Storage |
| 数据路径 |
存储 -> 内核缓冲 -> 用户缓冲 -> GPU |
存储 -> 用户缓冲 -> GPU |
存储 -> GPU |
| 内存拷贝次数 |
2 次 |
1 次 |
0 次 |
| CPU 参与度 |
高 (数据搬运 & 控制) |
中 (单次搬运 & 控制) |
低 (仅控制) |
| 带宽利用率 |
受限于 CPU 内存带宽 |
受限于 CPU 内存带宽 |
接近 PCIe/NVMe 极限 |
| 延迟 |
高 |
中 |
低 |
3.5 代码示例 (cuFile API)
使用 GDS 需包含 <cufile.h> 并链接 libcufile.so。以下是一个简化的读取流程:
#include <fcntl.h>
#include <unistd.h>
#include <cuda_runtime.h>
#include "cufile.h"
int main() {
const char* filename = "test_data.bin";
size_t size = 1024 * 1024 * 1024; // 1GB
void* d_buffer;
// 1. 初始化 cuFile 驱动
cuFileDriverOpen();
// 2. 分配 GPU 显存
cudaMalloc(&d_buffer, size);
// 3. 打开文件 (必须使用 O_DIRECT 标志以绕过 Page Cache)
int fd = open(filename, O_RDONLY | O_DIRECT);
// 4. 注册 cuFile 句柄
CUfileDescr_t cf_descr;
memset(&cf_descr, 0, sizeof(CUfileDescr_t));
cf_descr.handle.fd = fd;
cf_descr.type = CU_FILE_HANDLE_TYPE_OPAQUE_FD;
CUfileHandle_t cf_handle;
cuFileHandleRegister(&cf_handle, &cf_descr);
// 5. 直接读取数据到 GPU 显存
// 数据直接从 NVMe SSD 流向 GPU,不经过 CPU 内存
cuFileRead(cf_handle, d_buffer, size, 0, 0);
// ... 进行 GPU 计算 ...
// 6. 清理资源
cuFileHandleDeregister(cf_handle);
close(fd);
cudaFree(d_buffer);
cuFileDriverClose();
return 0;
}
4. GPUDirect 生态系统支持
GPUDirect 技术已建立起庞大的软硬件生态系统,从底层设备、中间件到上层框架均有广泛支持。
4.1 GPUDirect RDMA 生态
这是构建高性能分布式 GPU 集群的基石。
- 网络硬件:
- NVIDIA Mellanox ConnectX 系列:对 GPUDirect RDMA 有最完善的原生支持。
- AWS EFA:在 AWS 云环境中支持该技术。
- 通信库:
- NVIDIA NCCL:深度学习标准通信库,利用 GPUDirect RDMA 实现高效的集合通信。
- CUDA-aware MPI:主流 MPI 实现(如 OpenMPI, MVAPICH2)均支持。
- UCX:底层通信框架,为多种上层库提供加速支持。
4.2 GPUDirect Storage 生态
GDS 聚焦于存储 I/O 加速,得到了广泛集成。
- 支持的文件系统:
- 本地文件系统:ext4, xfs(需配合
nvidia-fs 模块)。
- 并行/分布式文件系统:Lustre, IBM Spectrum Scale, WekaFS, BeeGFS 等均提供支持,这对于构建 大规模 AI 训练集群 至关重要。
- 存储解决方案伙伴:NetApp, Dell EMC, Pure Storage 等厂商均已集成 GDS 支持。
4.3 上层 AI 框架集成
为了让开发者无感使用底层加速,主流框架和数据加载库进行了深度集成:
- NVIDIA DALI:深度学习数据加载库,原生支持 GDS,可显著加速数据预处理流水线。
- PyTorch / TensorFlow:其分布式训练模块底层依赖 NCCL(使用 GPUDirect RDMA);可通过插件或 DALI 集成支持 GDS。
- RAPIDS cuDF:支持使用 GDS 加速大规模数据文件的读取。
注意:具体支持版本和配置要求(如内核、驱动版本)请务必参考各厂商官方文档及 NVIDIA 的支持矩阵。
5. 总结
GPUDirect 系列技术是 NVIDIA 针对现代 HPC 和 AI 负载中“数据搬运瓶颈”提出的核心解决方案。它们共同目标是消除 CPU 在数据路径中的介入,实现设备间的 直接内存访问。
- 核心价值:
- GPUDirect RDMA 打破了计算节点间的通信壁垒,对于分布式训练至关重要,能显著提升多机多卡环境的扩展效率。
- GPUDirect Storage 打破了计算与存储间的 I/O 壁垒,对于大数据集训练和推理至关重要,解决了 GPU 因等待数据而空转的问题。
- 协同效应:在构建大规模 AI 集群时,两者互补共存。GDS 负责将海量数据高速“喂”入单个 GPU,而 GPUDirect RDMA 负责在 GPU 集群内部高速同步梯度和模型参数。
- 架构演进:GPUDirect 技术的普及标志着计算架构从“以 CPU 为中心”向“以数据为中心”的转变。CPU 退居为控制平面的指挥者,而繁重的数据流动则在 GPU、网卡和存储设备间通过高速互连直接完成,从而释放了整个 异构计算系统 的潜能。
希望本文能帮助你深入理解 NVIDIA GPUDirect 技术的原理与价值。如果你想了解更多关于 GPU 编程、高性能计算或 人工智能 的实践内容,欢迎访问云栈社区 与更多开发者交流探讨。