4、GDS架构解析:GPU、网络、存储之间的数据通路,以及CUDA、驱动、库的角色

4.1 核心原理:三段式数据通路与“零拷贝”的本质

GDS(GPUDirect Storage)并非一个单一硬件,而是一条软件定义的端到端数据通路。其核心思想是:让存储设备中的数据通过DMA引擎直接写入GPU显存,或从GPU显存直接读出到存储介质,全程不经过CPU内存(Host Memory)作为中转站。这条通路可拆解为三个关键段:

  • 存储端到GPU端(Storage-to-GPU):NVMe SSD或存储阵列通过PCIe交换机(或NVMe over Fabrics网络)将数据以RDMA或DMA方式送达GPU的显存地址。
  • GPU内部路径(GPU Internal Path):数据进入GPU后,由GPU的DMA引擎(Copy Engine)负责将数据从PCIe接收缓冲区搬运到指定的显存区域(如CUDA可访问的全局内存),此过程不消耗SM(流式多处理器)计算资源。
  • GPU到网络/存储(GPU-to-Network/Storage):反向操作时,GPU显存中的数据通过同一DMA引擎直接发出,经PCIe交换机到达网卡(NIC)或存储控制器,完成发送。

下图展示了GDS架构中GPU、网络、存储之间的物理连接与数据流方向,以及CUDA运行时、驱动和库在其中的分层位置。

GDS 数据通路与软件栈角色 存储端 NVMe SSD / 存储阵列 (NVMe over Fabrics) DMA引擎 网络端 RDMA网卡 (NIC) InfiniBand / RoCE RDMA引擎 GPU 端 GPU 显存 (HBM) CUDA全局内存 DMA Copy Engine PCIe 交换机 / CPU Root Complex 高速互联通道 (PCIe Gen4/Gen5) DMA RDMA DMA 软件栈(主机侧) CUDA 库 (cuFile) libcufile.so 提供API CUDA 驱动 管理GPU DMA引擎与内存映射 内核模块 (nvidia-peermem) 建立GPU与NIC/存储的DMA映射 ① 读:存储→PCIe→GPU显存 ② 写:GPU显存→PCIe→网络/存储 存储DMA 网络RDMA GPU DMA CUDA库 驱动 内核模块

4.2 方法流程:一次GDS读操作的完整旅程

以GPU从远程存储(NVMe over Fabric)读取一个训练样本文件为例,GDS的调用流程如下:

  1. 应用调用cuFileRead():CUDA应用调用cuFileRead()接口,传入目标GPU显存地址(由cudaMalloc分配)和文件偏移。
  2. cuFile库解析文件系统:libcufile库识别文件路径,若文件位于支持GDS的存储系统(如GPFS、Lustre或NVMe阵列),则绕过传统VFS路径,直接构造RDMA或NVMe命令。
  3. 驱动建立DMA映射:CUDA驱动调用nvidia-peermem内核模块,将GPU显存的物理地址(GPA)注册为可被外部设备访问的DMA目标。
  4. 存储端发起DMA写:存储控制器或网卡根据收到的命令,直接将数据块通过PCIe交换机写入GPU显存地址,不经过CPU内存。
  5. GPU DMA引擎完成搬运:数据到达GPU的PCIe接收缓冲区后,GPU的Copy Engine自动将其搬运到CUDA全局内存中,并触发cudaStreamSynchronize事件通知应用数据就绪。

整个过程中,CPU仅负责发起命令和接收完成通知,不参与数据搬运。传统路径中CPU需要先从存储读到内存,再通过cudaMemcpy拷贝到GPU,GDS将这两步合并为一步DMA操作。

4.3 案例/场景:多GPU训练中的梯度检查点保存

在大规模分布式训练中,周期性保存模型检查点(Checkpoint)是典型I/O密集型操作。假设有8张A100 GPU,每张GPU需要保存2GB的梯度数据到共享存储集群。

对比项 传统方式(CPU中转) GDS方式
数据路径 GPU显存→CPU内存→存储 GPU显存→存储(直连)
CPU内存占用 需要16GB临时缓冲区 0(完全旁路)
PCIe带宽占用 GPU→CPU和CPU→存储各占一次 仅一次GPU→存储
端到端延迟 约120ms 约45ms
CPU利用率 高(需执行memcpy和文件系统调用) 极低(仅命令下发)

实测中,使用GDS后检查点保存时间缩短了60%~70%,且CPU占用率从85%降至15%以下,释放的计算资源可用于数据预处理或异步日志记录。

4.4 误区/复盘:GDS使用中的常见陷阱

误区1:认为GDS对所有存储都生效。GDS要求存储端支持NVMe PRP(Physical Region Page)或RDMA注册内存操作。普通SATA SSD或未配置NVMe over Fabrics的存储无法触发GDS路径,数据会静默回退到传统拷贝。

误区2:忽略GPU显存对齐要求。cuFile要求显存地址按4KB对齐,且文件偏移也需对齐。若使用cudaMalloc默认分配(256B对齐),可能导致GDS调用失败或性能骤降。正确做法是使用cuFileBufRegister注册显存缓冲区,并确保偏移量对齐。

复盘建议:在部署GDS前,使用cuFileCheck工具验证存储系统兼容性。实际项目中,曾出现因网卡固件版本过旧导致RDMA注册失败,最终回退到传统路径而性能无提升的案例。务必检查nvidia-peermem模块是否加载(lsmod | grep nvidia_peermem),并确认存储端已启用GDS支持。

此外,GDS并非万能:对于小文件(<64KB)随机读场景,DMA映射开销可能超过收益,此时传统pread+cudaMemcpy反而更快。建议仅在单次I/O超过256KB时启用GDS路径。