Please enable Javascript to view the contents

GPU 主机如何开启 GDS

 ·  ☕ 5 分钟

1. 什么是 GDS(GPUDirectStorage)

GDS 允许 RDMA 网卡直接访问 GPU 内存,有助于增加 GPU 应用读写文件的 IO 带宽,减少 IO 时延,并降低其 CPU 负载。

客户端在开启 GDS 特性后,文件将以 O_DIRECT 方式打开,客户端不会再缓存文件数据。应用层读写文件时,客户端通过 nvidia-fs.ko 将应用层的 GPU 内存地址转换成 DMA 地址,并将其发送到服务端,由服务端 RDMA 网卡负责对客户端的 DMA 地址读取或填充。

2. 使用要求

2.1 系统要求

  • OS

Ubuntu 20.04,Ubuntu 22.04,Ubuntu 24.04,RHEL 8, RHEL 9

  • CUDA Toolkit

  • GCC

2.2 存储要求

在使用 GDS 时,需要应用层调用 cuFile API 才能正常工作。只有有限的存储系统实现了对 GDS 的支持:

  • NVMe
  • NVMeOF
  • SCSI
  • ScaleFlux CSD
  • NVMesh
  • DDN EXAScaler
  • IBM Spectrum Scale
  • NFS
  • BeeGFS
  • WekaFS

这里有一份 2021 年底的支持列表可以参考: https://developer.nvidia.com/zh-cn/blog/accelerating-io-in-the-modern-data-center-magnum-io-storage-partnerships/

3. 安装 GDS

3.1 安装依赖项

  • 安装 cuda-keyring
1
2
3
4
5
export distro=ubuntu2004
export arch=x86_64
wget https://developer.download.nvidia.com/compute/cuda/repos/$distro/$arch/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
apt-get update
  • 安装 nvidia-fs
1
2
3
apt list --installed | grep nvidia-fs
apt-cache search nvidia-fs
apt-get install nvidia-fs-dkms nvidia-fs
  • 查看当前 Driver 版本
1
2
3
nvidia-smi | grep "Driver Version"

| NVIDIA-SMI 535.129.03             Driver Version: 535.129.03   CUDA Version: 12.2     |
  • 安装 libnvidia-nscq

安装之前需要检查一下是否已经安装,再去寻找与 Driver 版本匹配的版本。

1
2
3
apt list --installed | grep libnvidia_nscq
apt-cache search libnvidia-nscq
apt-get install libnvidia-nscq-535
  • 安装 fabricmanager

安装之前需要检查一下是否已经安装,再去寻找与 Driver 版本匹配的版本。

1
2
3
apt list --installed | grep fabricmanager
apt-cache search fabricmanager
apt-get install nvidia-fabricmanager-535

3.2 安装 GDS

  • 安装 GDS
1
2
3
apt list --installed | grep nvidia-gds
apt-cache search nvidia-gds
apt-get install nvidia-gds-12-2
  • 检查 GDS 状态
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/usr/local/cuda-12.2/gds/tools/gdscheck.py -p

 GDS release version: 1.7.2.10
 nvidia_fs version:  2.22 libcufile version: 2.12
 Platform: x86_64
 ============
 ENVIRONMENT:
 ============
 =====================
 DRIVER CONFIGURATION:
 =====================
 NVMe               : Supported
 NVMeOF             : Unsupported
 SCSI               : Unsupported
 ScaleFlux CSD      : Unsupported
 NVMesh             : Unsupported
 DDN EXAScaler      : Unsupported
 IBM Spectrum Scale : Unsupported
 NFS                : Unsupported
 BeeGFS             : Unsupported
 WekaFS             : Unsupported
 Userspace RDMA     : Unsupported
 --Mellanox PeerDirect : Enabled
 --rdma library        : Not Loaded (libcufile_rdma.so)
 --rdma devices        : Not configured
 --rdma_device_status  : Up: 0 Down: 0
 =====================
 CUFILE CONFIGURATION:
 =====================
 properties.use_compat_mode : true
 properties.force_compat_mode : false
 properties.gds_rdma_write_support : true
 properties.use_poll_mode : false
 properties.poll_mode_max_size_kb : 4
 properties.max_batch_io_size : 128
 properties.max_batch_io_timeout_msecs : 5
 properties.max_direct_io_size_kb : 16384
 properties.max_device_cache_size_kb : 131072
 properties.max_device_pinned_mem_size_kb : 33554432
 properties.posix_pool_slab_size_kb : 4 1024 16384
 properties.posix_pool_slab_count : 128 64 32
 properties.rdma_peer_affinity_policy : RoundRobin
 properties.rdma_dynamic_routing : 0
 fs.generic.posix_unaligned_writes : false
 fs.lustre.posix_gds_min_kb: 0
 fs.beegfs.posix_gds_min_kb: 0
 fs.weka.rdma_write_support: false
 fs.gpfs.gds_write_support: false
 profile.nvtx : false
 profile.cufile_stats : 0
 miscellaneous.api_check_aggressive : false
 execution.max_io_threads : 4
 execution.max_io_queue_depth : 128
 execution.parallel_io : true
 execution.min_io_threshold_size_kb : 8192
 execution.max_request_parallelism : 4
 properties.force_odirect_mode : false
 properties.prefer_iouring : false
 =========
 GPU INFO:
 =========
 GPU index 0 NVIDIA A800-SXM4-80GB bar:1 bar size (MiB):131072 supports GDS,IOMMU State: Disabled
 GPU index 1 NVIDIA A800-SXM4-80GB bar:1 bar size (MiB):131072 supports GDS,IOMMU State: Disabled
 GPU index 2 NVIDIA A800-SXM4-80GB bar:1 bar size (MiB):131072 supports GDS,IOMMU State: Disabled
 GPU index 3 NVIDIA A800-SXM4-80GB bar:1 bar size (MiB):131072 supports GDS,IOMMU State: Disabled
 GPU index 4 NVIDIA A800-SXM4-80GB bar:1 bar size (MiB):131072 supports GDS,IOMMU State: Disabled
 GPU index 5 NVIDIA A800-SXM4-80GB bar:1 bar size (MiB):131072 supports GDS,IOMMU State: Disabled
 GPU index 6 NVIDIA A800-SXM4-80GB bar:1 bar size (MiB):131072 supports GDS,IOMMU State: Disabled
 GPU index 7 NVIDIA A800-SXM4-80GB bar:1 bar size (MiB):131072 supports GDS,IOMMU State: Disabled
 ==============
 PLATFORM INFO:
 ==============
 IOMMU: disabled
 Platform verification succeeded

由于没有额外支持 GDS 的存储系统,仅 NVMe 设备处于支持 GDS 的状态。

4. 测试 GDS

4.1 创建一个 100G 的文件

1
time dd if=/dev/zero of=/data/test/dd.txt bs=40M count=2500

4.2 不同传输模型下的测试

/usr/local/cuda-12.2/gds/tools/gdsio 提供了 8 个不同的测试模式,分别是:

  • 0 - Storage->GPU (GDS)

GPU Direct Storage (GDS): 数据直接从存储传输到 GPU,绕过 CPU。这种模式减少了延迟并增加了吞吐量,特别适合需要 GPU 高速访问数据的场景。

1
2
3
/usr/local/cuda-12.2/gds/tools/gdsio -f /data/test/dd.txt -d 0 -w 4 -s 10G -i 1M -I 0 -x 0

IoType: READ XferType: GPUD Threads: 4 DataSetSize: 10203136/10240000(KiB) IOSize: 1024(KiB) Throughput: 4.443489 GiB/sec,Avg_Latency: 878.805571 usecs ops: 9964 total_time 2.189826 secs
  • 1 - Storage->CPU

存储到 CPU 的传统传输: 数据首先从存储传输到 CPU。这是传统的处理方式,CPU 接收并处理数据,然后再传递给其他组件,比如 GPU。

1
2
3
/usr/local/cuda-12.2/gds/tools/gdsio -f /data/test/dd.txt -d 0 -w 4 -s 10G -i 1M -I 0 -x 1

IoType: READ XferType: CPUONLY Threads: 4 DataSetSize: 10240000/10240000(KiB) IOSize: 1024(KiB) Throughput: 4.414133 GiB/sec,Avg_Latency: 868.366600 usecs ops: 10000 total_time 2.212354 secs
  • 2 - Storage->CPU->GPU

存储到 CPU 再到 GPU: 数据先从存储传输到 CPU,经过处理后再传输到 GPU。这是更常见的流程,适用于需要 CPU 进行数据预处理的场景。

1
2
3
/usr/local/cuda-12.2/gds/tools/gdsio -f /data/test/dd.txt -d 0 -w 4 -s 10G -i 1M -I 0 -x 2

IoType: READ XferType: CPU_GPU Threads: 4 DataSetSize: 10142720/10240000(KiB) IOSize: 1024(KiB) Throughput: 4.312804 GiB/sec,Avg_Latency: 905.410136 usecs ops: 9905 total_time 2.242822 secs
  • 3 - Storage->CPU->GPU_ASYNC

存储到 CPU 再到 GPU 的异步传输: 数据先从存储传输到 CPU,然后异步传输到 GPU。这种模式允许 CPU 在等待数据传输完成的同时执行其他任务,提高了效率。

1
2
3
/usr/local/cuda-12.2/gds/tools/gdsio -f /data/test/dd.txt -d 0 -w 4 -s 10G -i 1M -I 0 -x 3

IoType: READ XferType: CPU_ASYNC_GPU Threads: 4 DataSetSize: 10167296/10240000(KiB) IOSize: 1024(KiB) Throughput: 3.318594 GiB/sec,Avg_Latency: 1176.616969 usecs ops: 9929 total_time 2.921806 secs
  • 4 - Storage->PAGE_CACHE->CPU->GPU

存储->页缓存->CPU->GPU: 数据首先进入操作系统的页缓存,然后传输到 CPU,最后传输到 GPU。页缓存可以加快对常用数据的访问速度,但会增加一步缓存操作。

1
2
3
/usr/local/cuda-12.2/gds/tools/gdsio -f /data/test/dd.txt -d 0 -w 4 -s 10G -i 1M -I 0 -x 4

IoType: READ XferType: CPU_CACHED_GPU Threads: 4 DataSetSize: 10011648/10240000(KiB) IOSize: 1024(KiB) Throughput: 1.770729 GiB/sec,Avg_Latency: 2206.536591 usecs ops: 9777 total_time 5.392046 secs
  • 5 - Storage->GPU_ASYNC

存储到 GPU 的异步传输: 数据直接从存储异步传输到 GPU,允许其他操作在传输过程中继续执行,减少等待时间,提高整体处理效率。

1
2
3
/usr/local/cuda-12.2/gds/tools/gdsio -f /data/test/dd.txt -d 0 -w 4 -s 10G -i 1M -I 0 -x 5

IoType: READ XferType: ASYNC Threads: 4 DataSetSize: 10160128/10240000(KiB) IOSize: 1024(KiB) Throughput: 3.053654 GiB/sec,Avg_Latency: 1272.345376 usecs ops: 9922 total_time 3.173068 secs
  • 6 - Storage->GPU_BATCH

存储到 GPU 的批处理传输: 数据从存储传输到 GPU,但采用批处理的方式进行。适用于需要一次性处理大量数据的情况。

1
2
3
/usr/local/cuda-12.2/gds/tools/gdsio -f /data/test/dd.txt -d 0 -w 4 -s 10G -i 1M -I 0 -x 6

IoType: READ XferType: GPU_BATCH Threads: 1 IoDepth: 4 DataSetSize: 10240000/10240000(KiB) IOSize: 1024(KiB) Throughput: 4.422783 GiB/sec,Avg_Latency: 873.240876 usecs ops: 10001 total_time 2.208027 secs
  • 7 - Storage->GPU_BATCH_STREAM

存储到 GPU 的流式批处理传输: 这是一种批处理和流式处理结合的模式,数据从存储传输到 GPU 时,采用流式处理进行批处理,进一步优化了处理速度和资源利用率。

1
2
3
/usr/local/cuda-12.2/gds/tools/gdsio -f /data/test/dd.txt -d 0 -w 4 -s 10G -i 1M -I 0 -x 7

IoType: READ XferType: GPU_BATCH_STREAM Threads: 1 IoDepth: 4 DataSetSize: 10240000/10240000(KiB) IOSize: 1024(KiB) Throughput: 2.437489 GiB/sec,Avg_Latency: 1600.979502 usecs ops: 10001 total_time 4.006429 secs

4.3 不同模式下的测试结果

模式速度 (GiB/sec)
0 - Storage->GPU (GDS)4.443489 GiB/sec
1 - Storage->CPU4.414133 GiB/sec
2 - Storage->CPU->GPU4.312804 GiB/sec
3 - Storage->CPU->GPU_ASYNC3.318594 GiB/sec
4 - Storage->PAGE_CACHE->CPU->GPU1.770729 GiB/sec
5 - Storage->GPU_ASYNC3.053654 GiB/sec
6 - Storage->GPU_BATCH4.422783 GiB/sec
7 - Storage->GPU_BATCH_STREAM2.437489 GiB/sec
  • Storage->GPU (GDS)\Storage->GPU_BATCH: 速度最高,因为数据直接从存储传输到 GPU,绕过了 CPU
  • Storage->CPU->GPU_ASYNC 和 Storage->GPU_ASYNC: 异步模式下的速度稍低一些,因为异步传输增加了管理开销
  • Storage->PAGE_CACHE->CPU->GPU: 数速度最低,因为数据经过了页缓存,增加了额外的步骤

4.3 验证 GDS 模式下对 CPU 的低使用率

主要对比模式 0 和 2

  • 0 - Storage->GPU (GDS)
1
2
3
/usr/local/cuda-12.2/gds/tools/gdsio -f /data/test/dd.txt -d 0 -w 40 -s 100G -i 1M -I 0 -x 0

IoType: READ XferType: GPUD Threads: 40 DataSetSize: 101975040/102400000(KiB) IOSize: 1024(KiB) Throughput: 6.653494 GiB/sec,Avg_Latency: 5870.442542 usecs ops: 99585 total_time 14.616528 secs
1
2
PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
43261 root      20   0   41.9g 753364 700692 D  18.8   0.1   0:04.69 gdsio
  • 2 - Storage->CPU->GPU
1
2
3
/usr/local/cuda-12.2/gds/tools/gdsio -f /data/test/dd.txt -d 0 -w 40 -s 100G -i 1M -I 0 -x 2

IoType: READ XferType: CPU_GPU Threads: 40 DataSetSize: 101849088/102400000(KiB) IOSize: 1024(KiB) Throughput: 6.649129 GiB/sec,Avg_Latency: 5874.226678 usecs ops: 99462 total_time 14.608058 secs
1
2
PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
47977 root      20   0   36.0g 153276 138644 S  63.7   0.0   0:03.27 gdsio

可以看到在 GDS 模式下,CPU 使用率只有经过 CPU 传输的 30%。

5. 参考


微信公众号
作者
微信公众号