1. NVIDIA GPUDirect Storage 入门#

NVIDIA® Magnum IO GPUDirect® Storage 入门信息。

2. 简介#

NVIDIA® GPUDirect® Storage (GDS) 实现了 GPU 内存和存储之间直接内存访问 (DMA) 传输的直接数据路径,从而避免了通过 CPU 的反弹缓冲区。此直接路径增加了系统带宽,并减少了 CPU 的延迟和利用率负载。

本指南的目的是帮助用户通过使用示例应用程序来评估和测试 GDS 的功能和性能。这些应用程序可以在您设置和安装 GDS 之后以及在您运行已修改为利用 GDS 的自定义应用程序之前运行。

有关 GDS 的更多信息,请参阅以下指南

要了解有关 GDS 的更多信息,请参阅以下文章

3. GDS 安装#

启用 GDS 有两种方法:使用 GDS NVIDIA 内核驱动程序 (nvidia-fs.ko) 和更新 NVMe 驱动程序补丁,或者从 12.8 版本开始(当满足 Linux 内核和 GPU 版本/驱动程序要求时)可以选择使用 P2PDMA 模式,该模式无需修补 NVMe 驱动程序,也无需安装 nvidia-fs 驱动程序。有关更多信息,请参阅 GPUDirect Storage 安装和故障排除指南

4. 使用 GDSIO 演示 GDS#

GDSIO 是一种基准测试工具,旨在利用 NVIDIA 的 GPUDirect Storage (GDS) 技术。与流行的 FIO 实用程序类似,GDSIO 允许用户配置各种参数,例如块大小、线程、读/写模式和接口。但是,GDSIO 专门用于测量 GPU 内存到存储传输的性能。

使用 GDSIO,用户可以评估吞吐量和延迟指标,从而可以在不同的数据传输模式之间进行有意义的比较。下面,我们提供示例来说明如何使用 GDSIO 入门。

4.1. 示例#

示例 1:基本 GPU 到存储写入

最简单的 GDSIO 命令执行 GPU 到存储写入操作。以下命令将 8 KB (-s 8K) 的数据从 GPU 0 (-d 0) 写入到文件 /mnt/gds/test。数据以两个 4 KB 块 (-i 4K) 写入,-I 1 标志指定单次迭代。

/usr/local/cuda/gds/tools/gdsio -x 0 -d 0 -s 8K -i 4K -f /mnt/gds/test -I 1

IoType: WRITE XferType: GPUD Threads: 1 DataSetSize: 8/8(KiB) IOSize: 4(KiB) Throughput: 0.001081 GiB/sec, Avg_Latency: 14.000000 usecs ops: 2 total_time 0.007057 secs

此操作测量 GPU 到存储传输性能。报告的吞吐量、延迟和总执行时间提供了对直接数据传输效率的深入了解。

示例 2:比较 GDS 模式与 CPU 介导的传输

要比较 GPU Direct 传输 (GPUD) 与传统的 GPU ↔ CPU ↔ 存储传输,只需切换到 -x 2 模式

/usr/local/cuda/gds/tools/gdsio -x 2 -d 0 -s 8K -i 4K -f /mnt/gds/a -I 1

IoType: WRITE XferType: CPU_GPU Threads: 1 DataSetSize: 8/8(KiB) IOSize: 4(KiB) Throughput: 0.001127 GiB/sec, Avg_Latency: 40.000000 usecs ops: 2 total_time 0.006769 secs

此比较通过将其与 CPU 介导的传输的增加的延迟和略微降低的吞吐量进行对比,突出了 GDS 的效率。

示例 3:GPU 写入的批处理模式

批处理模式 (-x 6) 将多个小写入操作分组到一个提交中以提高效率。在此示例中,我们以 10 个条目 (-w 10) 的批次写入 8 KB (-s 8K),每个条目大小为 4 KB (-i 4K)。此配置产生两个批次,总共有 20 个 I/O 操作(2 个批次 × 每个批次 10 个 I/O)。

下一个使用 GDS 批处理模式的操作

  • 批处理模式 (-x 6) 将收集 10 个条目 (-w 10),每个条目大小为 4k (-i 4K) 到一个组中并提交写入。总共有两个批次来生成整个所需的写入大小 (-s 8K)。I/O 的总数为 20(2 个批次 * 每个批次 10 个 I/O)

    /usr/local/cuda/gds/tools/gdsio -x 6 -d 0 -s 8K -i 4K -D /mnt/gds/dir -I 1 -w 10
    
    IoType: WRITE XferType: GPU_BATCH Threads: 1 IoDepth: 10 DataSetSize: 80/80(KiB) IOSize: 4(KiB) Throughput: 0.010523 GiB/sec, Avg_Latency: 3476.650000 usecs ops: 20 total_time 0.007250 secs
    

    此操作演示了批处理的性能优势,显示了分组 I/O 操作的吞吐量提高。目录内容如下所示,显示 10 个文件,每个文件大小为 8K。

    ls -l /mnt/gds/dir
    
    total 80
    -rw-r--r-- 1 root root 8192 Dec  5 17:12 gdsio.0
    -rw-r--r-- 1 root root 8192 Dec  5 17:12 gdsio.1
    -rw-r--r-- 1 root root 8192 Dec  5 17:12 gdsio.2
    -rw-r--r-- 1 root root 8192 Dec  5 17:12 gdsio.3
    -rw-r--r-- 1 root root 8192 Dec  5 17:12 gdsio.4
    -rw-r--r-- 1 root root 8192 Dec  5 17:12 gdsio.5
    -rw-r--r-- 1 root root 8192 Dec  5 17:12 gdsio.6
    -rw-r--r-- 1 root root 8192 Dec  5 17:12 gdsio.7
    -rw-r--r-- 1 root root 8192 Dec  5 17:12 gdsio.8
    -rw-r--r-- 1 root root 8192 Dec  5 17:12 gdsio.9
    

有关 GDSIO 的更多信息,请访问 GDSIO 基准测试

5. 与 GDSIO 链接#

以下是使用 GDSIO 库执行 GPU 到存储写入的简单示例程序

#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <cuda_runtime.h>
#include <cufile.h>
int main() {

    CUfileHandle_t cfHandle;
    CUfileDescr_t cfDescr = {};
    const char *filename = "/mnt/gds/testfile";
    int fd = open(filename, O_CREAT | O_RDWR, 0664);
    if (fd < 0) {
        perror("File open failed");
        return 1;
    }

    // Set up GDS descriptor
    cfDescr.handle.fd = fd;
    cfDescr.type = CU_FILE_HANDLE_TYPE_OPAQUE_FD;
    CUfileError_t status = cuFileHandleRegister(&cfHandle, &cfDescr);
    if (status.err != CU_FILE_SUCCESS) {
        std::cerr << "cuFileHandleRegister failed: " << status.err << std::endl;
        close(fd);
        return 1;
    }

    // Alloc GPU memory and fill GPU memory with data
    void *devPtr;
    size_t bufferSize = 8192;
    cudaMalloc(&devPtr, bufferSize);
    cudaMemset(devPtr, 0xAB, bufferSize);

    // Perform the write
    ssize_t writtenBytes = cuFileWrite(cfHandle, devPtr, bufferSize, 0, 0);
    if (writtenBytes < 0) {
        perror("cuFileWrite failed");
    } else {
        std::cout << "Wrote " << writtenBytes << " bytes to the file." << std::endl;
    }
getBoolParameter()
    // Clean up
    cuFileHandleDeregister(cfHandle);
    close(fd);
    cudaFree(devPtr);
    return 0;
}

使用以下命令编译上面的示例

g++ -o gds_example gds_example.cc -I/usr/local/cuda/include -L/usr/local/cuda/lib64 -lcuda -lcufile -lcudart

有关 API 的更多信息,请参阅 cuFile API 参考指南

6. GDS 问题故障排除#

GPUDirect Storage 安装和故障排除指南 包含基本和高级故障排除的单独章节。

问题诊断速查表 涵盖了常见问题以及如何解决这些问题。

7. 声明#

本文档仅供参考,不应被视为对产品的特定功能、状况或质量的保证。NVIDIA Corporation(“NVIDIA”)对本文档中包含的信息的准确性或完整性不做任何明示或暗示的陈述或保证,并且对本文档中包含的任何错误不承担任何责任。NVIDIA 对因使用此类信息或因使用此类信息而可能导致的侵犯专利或第三方的其他权利的后果或使用不承担任何责任。本文档不承诺开发、发布或交付任何材料(如下定义)、代码或功能。

NVIDIA 保留在任何时候对本文档进行更正、修改、增强、改进和任何其他更改的权利,恕不另行通知。

客户在下订单前应获取最新的相关信息,并应验证此类信息是最新且完整的。

NVIDIA 产品根据订单确认时提供的 NVIDIA 标准销售条款和条件进行销售,除非 NVIDIA 和客户的授权代表签署的单独销售协议(“销售条款”)另有约定。NVIDIA 特此明确反对将任何客户通用条款和条件应用于购买本文档中引用的 NVIDIA 产品。本文档未直接或间接形成任何合同义务。

NVIDIA 产品并非设计、授权或保证适用于医疗、军事、飞机、航天或生命支持设备,也不适用于 NVIDIA 产品的故障或故障可能合理预期会导致人身伤害、死亡或财产或环境损害的应用。NVIDIA 对在此类设备或应用中包含和/或使用 NVIDIA 产品不承担任何责任,因此,此类包含和/或使用由客户自行承担风险。

NVIDIA 不保证基于本文档的产品将适用于任何特定用途。NVIDIA 不一定对每个产品的所有参数进行测试。客户全权负责评估和确定本文档中包含的任何信息的适用性,确保产品适合客户计划的应用,并为该应用执行必要的测试,以避免应用或产品的默认设置。客户产品设计中的缺陷可能会影响 NVIDIA 产品的质量和可靠性,并可能导致超出本文档中包含的其他或不同的条件和/或要求。NVIDIA 对可能基于或归因于以下原因的任何违约、损害、成本或问题不承担任何责任:(i)以任何与本文档相反的方式使用 NVIDIA 产品或(ii)客户产品设计。

本文档未授予任何 NVIDIA 专利权、版权或其他 NVIDIA 知识产权下的任何明示或暗示的许可。NVIDIA 发布的有关第三方产品或服务的信息不构成 NVIDIA 授予使用此类产品或服务的许可,也不构成对此类产品或服务的保证或认可。使用此类信息可能需要从第三方获得第三方专利或其他知识产权下的许可,或者从 NVIDIA 获得 NVIDIA 专利或其他知识产权下的许可。

仅当事先获得 NVIDIA 书面批准,在不作更改的情况下复制,并且完全遵守所有适用的出口法律和法规,并附带所有相关的条件、限制和声明时,才允许复制本文档中的信息。

本文档以及所有 NVIDIA 设计规范、参考板、文件、图纸、诊断程序、列表和其他文档(统称为“材料”,单独或统称)均“按原样”提供。NVIDIA 对材料不作任何明示、暗示、法定或其他方面的保证,并明确否认所有关于不侵权、适销性和特定用途适用性的暗示保证。在法律未禁止的范围内,在任何情况下,NVIDIA 均不对因使用本文档而引起的任何损害(包括但不限于任何直接、间接、特殊、附带、惩罚性或后果性损害,无论因何种原因造成,也无论责任理论如何)承担责任,即使 NVIDIA 已被告知可能发生此类损害。尽管客户可能因任何原因而遭受任何损害,但 NVIDIA 对客户就本文所述产品承担的累计总责任应根据产品的销售条款进行限制。

8. OpenCL#

OpenCL 是 Apple Inc. 的商标,已获得 Khronos Group Inc. 的许可使用。

9. 商标#

NVIDIA、NVIDIA 徽标、CUDA、DGX、DGX-1、DGX-2、DGX-A100、Tesla 和 Quadro 是 NVIDIA Corporation 在美国和其他国家/地区的商标和/或注册商标。其他公司和产品名称可能是与其关联的各自公司的商标。