
1 概览指南
1.1 引言
GPUDirect® Storage(GDS)为GPU内存与存储之间的直接内存访问(DMA)传输提供了一条直接数据通路,从而避免了通过CPU进行中转缓冲。使用这条直接通路可以缓解系统带宽瓶颈,并降低延迟和CPU的利用率负载。
本指南旨在帮助您为GDS启用文件系统,并就文件系统的特性及其与GDS的关系提供一些见解。本指南还概述了GDS的功能、注意事项和软件架构。这篇内容为需要修改内核的GDS用户深入阅读《cuFile API参考指南》中的技术细节奠定了基础。
1.1.1 相关文档
有关GDS的更多信息,请参阅以下指南:
- 设计指南
- cuFile API参考指南
- 发行说明
- 基准测试与配置指南
- 最佳实践指南
- 安装与故障排除指南
- O_DIRECT要求指南
如需进一步了解GDS,请参阅以下博客:
- GPUDirect Storage:存储与GPU内存之间的直接通路
- Magnum IO博客
1.1.2 对开发者的优势
GDS为应用开发者提供以下优势:
- 在GPU内存与存储之间启用直接通路。可缓解带宽瓶颈、降低延迟,并减少CPU在数据传输方面的负载。
- 降低性能影响以及对CPU处理存储数据传输的依赖。
- 对于完全迁移至GPU的计算流水线而言,这是计算优势之上的性能倍增器,使得在存储与GPU之间移动的数据由GPU而非CPU来完成首次和末次访问。
- 支持与其他基于操作系统的文件访问方式互操作,从而可以通过传统文件IO将数据传输到设备或从设备传出,再由使用cuFile API的中间件或应用程序进行访问。
cuFile API及其实现提供以下优势:
- 一系列API,为CUDA应用提供对本地或分布式文件及块存储的最佳性能访问。
- 在GPU之间传输时,相对于现有标准Linux文件IO,具有更高的性能和更低的CPU负载。
- 通过消除对内存分配和数据移动进行精细专家管理的需要,提高了易用性。
- 相对于现有的隐式文件-GPU数据移动方法(需要在CPU和GPU之间及之上进行更复杂的内存和数据移动管理),API序列更为简单。
- 适用于多种存储类型的通用性,涵盖各种本地和分布式文件系统、块接口和命名空间系统,包括标准Linux和第三方解决方案。
- 对于GPU应用而言,是独立于内存类型进行文件I/O的主要API。
- 能够定位通过cudaMalloc、cuMemAlloc或cuMemCreate/cuMemMap分配到GPU的内存,或通过cudaHostAlloc、cudaMallocHost分配到CPU的内存。
- GDS对等模式不支持可迁移内存(通过cudaMallocManaged分配)或系统分配内存(malloc、栈等),在支持UVM的系统上(如Grace-Hopper)。GDS将通过兼容路径使用内部GPU/CPU中转缓冲对这些内存分配进行IO。
cuFile API的Stream子集提供以下优势:
- 异步卸载操作相对于CUDA流有序。
- 计算后IO:GPU内核先产生数据,然后传输到IO。
- IO后计算:数据传输完成后,GPU内核可以继续执行。
- 跨流并发:使用不同的CUDA流可以实现并发执行和多个DMA引擎的并发使用。
1.1.3 预期用途
cuFile功能可用于以下方式:
- 当存储与GPU内存之间的IO成为性能瓶颈时,cuFile实现可提升吞吐量。这种情况出现在计算流水线已从CPU迁移至GPU的场景中,此时在存储传输之前或之后首次和末次访问数据的代理在GPU上执行。
- cuFile API目前是显式的,用于在存储与完全适合可用GPU物理内存的缓冲区之间进行读写。
- cuFile API适合粗粒度流式传输,而非细粒度随机访问。
- 对于细粒度访问,进行内核转换和经过操作系统的底层软件开销可以被摊销。
1.2 功能概览
本节提供GDS的功能概览,涵盖基本用法、通用性、性能考量以及解决方案等内容。本文档适用于从CPU发出的cuFile API。
1.2.1 显式与直接
GDS是以性能为中心的解决方案,因此端到端传输的性能取决于延迟开销和最大可达到带宽。
以下是GDS中使用的一些术语:
显式编程请求
立即调用存储与GPU内存之间传输的显式编程请求,是主动的。
隐式请求
由内存引用引发的对存储的隐式请求,该引用导致从GPU到CPU的缺页,并可能从CPU到存储,是被动的。
注意
**被动活动往往引入更多开销。由于是显式和主动的,GDS通过其显式cuFile API最大化性能。**
避免额外拷贝并采用最高带宽路径时,延迟更低。不使用GDS时,必须通过CPU中的中转缓冲进行额外拷贝,这会引入延迟并降低有效带宽。
注意
**GDS带来的延迟改善在小传输时最为明显。**
使用GDS时,虽然存在例外情况,但可以实现零拷贝方法。此外,当不再需要通过CPU进行拷贝时,即使由于PCIe拓扑结构必须经过CPU根端口,数据通路也不包括CPU内存。在某些系统上,通过PCIe交换机或充当PCIe交换机的NIC在本地或远程存储之间建立直接通路,其峰值带宽至少是经过CPU的数据通路的两倍。使用cuFile API访问GDS技术可实现显式和直接传输,从而提供更低的延迟和更高的带宽。
对于GPU内存与存储之间的直接数据传输,文件必须以O_DIRECT模式打开。如果文件未以此模式打开,内容可能会缓存在CPU系统内存中,这与直接传输不兼容。有关详细信息,请参阅《GPUDirect Storage O_DIRECT要求指南》。
注意
**从CUDA Toolkit 12.2(GDS版本1.7.x)开始,即使文件以非O_DIRECT模式打开,对于页对齐缓冲区且大小和偏移对齐的情况,cuFile库也会采用GDS驱动的O_DIRECT路径进行GPU内存与存储之间的传输。**
显式拷贝与使用mmap的对比
以下代码示例比较了显式拷贝与使用mmap并在必要时引发隐式缺页的代码序列。
此代码示例使用显式拷贝:
```
int fd = open(file_name,...)
void *sysmem_buf, *gpumem_buf;
sysmem_buf = malloc(buf_size);
cudaMalloc(gpumem_buf,buf_size);
pread(fd,sysmem_buf,buf_size);
cudaMemcpy(sysmem_buf, gpumem_buf,buf_size,H2D);
doit<<> // 无缺页;
```
此代码示例使用mmap:
```
int fd = open(file_name, O_DIRECT,...)
void *mgd_mem_buf;
cudaMallocManaged(mgd_mem_buf,buf_size);
mmap(mgd_mem_buf,buf_size,...fd,...)
doit<<> // 对mgdmem_buf的引用引发缺页
```
在第一个示例中,使用pread将数据从存储移动到CPU中转缓冲sysmem_buf,然后使用cudaMemcpy将数据移动到GPU。在第二个示例中,mmap使托管内存由文件支持。从GPU对托管内存的引用如果不在GPU内存中,将引发缺页回到CPU,然后到存储,从而导致隐式传输。
GDS 支持在存储附近的代理设备(NIC 或 NVMe 驱动器)与 GPU 内存之间进行 DMA 传输。传统的 POSIX 读写 API 只能操作位于 CPU 系统内存中的缓冲区地址。相比之下,cuFile API 操作的是位于 GPU 内存中的缓冲区地址。因此,两者看起来非常相似,但存在一些差异。
比较 POSIX API 与 cuFile API
以下代码示例比较了 POSIX API 和 cuFile API。POSIX 的 pread 和 pwrite 需要 CPU 系统内存中的缓冲区,并需要一次额外的拷贝;而 cuFile 的 read 和 write 只需要注册文件句柄。
此代码示例使用 POSIX API:
```
int fd = open(...)
void *sysmem_buf, *gpumem_buf;
sysmem_buf = malloc(buf_size);
cudaMalloc(gpumem_buf, buf_size);
pread(fd, sysmem_buf, buf_size);
cudaMemcpy(sysmem_buf,
gpumem_buf, buf_size, H2D);
cuStreamSynchronize(0);
doit<<>>
```
此代码示例使用 cuFile API:
```
int fd = open(file_name, O_DIRECT,...)
CUFileHandle_t *fh;
CUFileDescr_t desc;
desc.type=CU_FILE_HANDLE_TYPE_OPAQUE_FD;
desc.handle.fd = fd;
cuFileHandleRegister(&fh, &desc);
void *gpumem_buf;
cudaMalloc(gpumem_buf, buf_size);
cuFileRead(&fh, gpumem_buf, buf_size, ...);
doit<<>>
```
cuFile 的核心功能包括:
- 在存储与 GPU 内存之间进行显式数据传输,其形式与 POSIX 的 pread 和 pwrite 非常相似。
- 在 CUDA 流中执行 IO,使其既异步,又相对于同一流中的其他命令保持有序。
GDS 提供的直接数据通路依赖于已启用 GDS 的文件系统驱动程序的可用性。这些驱动程序运行在 CPU 上,并实现用于建立直接数据通路的控制路径。
1.2.2 性能优化
在存在显式和直接地在存储与GPU内存之间移动数据的可行通路之后,还有进一步优化性能的机会。
1.2.2.1 实现性能增强
GDS提供用户接口,抽象了实现细节。通过该实现中的性能优化,存在随时间增强并针对每个平台和拓扑进行调整的权衡。
下图显示了其中一些性能优化的列表:

图1.1:性能优化
在系统中,例如分别连接到CPU插槽CPU A和CPU B的GPU A和GPU B可能通过两条路径连接:
- GPU A → CPU A PCIe根端口 → CPU A经CPU互连到CPU B → CPU B沿另一条PCIe路径到GPU B。
- GPU A → 使用NVLink到GPU B。
类似地,通过中间交换机以PCIe方式连接的NIC有选择到GPU B的数据路径:
- NIC → CPU A PCIe根端口,CPU A经CPU互连到CPU B,CPU B沿另一条PCIe路径 → GPU B。
- NIC → GPU A中的暂存缓冲区,再经NVLink → GPU B。
中间缓冲区暂存
批量数据传输通过DMA拷贝引擎执行。并非所有通过系统的路径都能通过单阶段传输实现,有时传输会被分成多个阶段,沿途使用暂存缓冲区。在图中NIC-GPU A-GPU B的示例中,需要GPU A中的暂存缓冲区,使用GPU A或GPU B中的DMA引擎在GPU A的内存与GPU B的内存之间传输数据。
数据可能仅通过PCIe经过CPU传输,或通过NVLink直接在GPU之间传输。虽然DMA引擎可以跨越PCIe端点,但涉及NVLink的路径可能涉及通过缓冲区(GPU A)暂存。
动态路由
路径与暂存。前图中左半部分和右半部分端点之间的两条路径可用:红色PCIe路径或绿色NVLink路径。
高端微信群介绍 | |
创业投资群 | AI、IOT、芯片创始人、投资人、分析师、券商 |
闪存群 | 覆盖5000多位全球华人闪存、存储芯片精英 |
云计算群 | 全闪存、软件定义存储SDS、超融合等公有云和私有云讨论 |
AI芯片群 | 讨论AI芯片和GPU、FPGA、CPU异构计算 |
5G群 | 物联网、5G芯片讨论 |
第三代半导体群 | 氮化镓、碳化硅等化合物半导体讨论 |
存储芯片群 | DRAM、NAND、3D XPoint等各类存储介质和主控讨论 |
汽车电子群 | MCU、电源、传感器等汽车电子讨论 |
光电器件群 | 光通信、激光器、ToF、AR、VCSEL等光电器件讨论 |
渠道群 | 存储和芯片产品报价、行情、渠道、供应链 |

< 长按识别二维码添加好友 >
加入上述群聊

带你走进万物存储、万物智能、
万物互联信息革命新时代
