Post

GPUDirect Storage(GDS)安装与使用

GPUDirect Storage(GDS)安装与使用

1 GDS 宿主机安装

1.1 环境要求

需要支持 GDS 的 NVIDIA GPU 和文件系统,具体可查阅官方文档。

1.2 安装GDS

(不确定此处步骤是否有些可省略,仅供参考)

  • 挂载iso

官网查找对应版本iso,上传至服务器root目录并挂载。

1
2
3
4
5
6
7
8
9
10
11
# 查看nvidia驱动版本
nvidia-smi

# 查看ubunt版本
lsb_release -a

# 挂载iso
sudo -i
mkdir -p /mnt/ofed
mount -o loop /root/MLNX_OFED_LINUX-5.8-7.0.6.1-ubuntu22.04-x86_64.iso /mnt/ofed
cd /mnt/ofed
  • 补齐编译依赖:
1
2
apt update
apt install -y linux-headers-$(uname -r) build-essential dkms lsb-release python3
  • 重装OFED驱动:(比较慢,大概10min)
1
2
3
4
5
./mlnxofedinstall --with-nvmf --with-nfsrdma --enable-gds --add-kernel-support --without-ucx-cuda

# 更新名称
update-initramfs -u -k `uname -r`
reboot
  • 查看cuda版本
1
2
3
4
5
6
7
8
9
10
11
nvcc --version

# 如果不对,配置环境变量
vim /etc/bash.bashrc
export PATH=/usr/local/cuda-12.8/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-12.8/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
source /etc/bash.bashrc

# 再次查看
echo $PATH
echo $LD_LIBRARY_PATH
  • 解压+编译+加载ko文件:
1
2
3
4
5
6
7
8
cd /root
tar -zxvf gds-nvidia-fs-2.17.4.tar.gz
cd gds-nvidia-fs-2.17.4/
make
insmod nvidia-fs.ko

# 查看是否加载成功
lsmod | grep nvidia_fs
  • 其他
1
2
3
4
5
6
7
8
9
10
11
12
13
# 分别开启nfs和rdma两协议:
modprobe nfs
modprobe rpcrdma

# 电源设置,要求active
systemctl status nvidia-persistenced

# 规则设置
cp /lib/udev/rules.d/40-vm-hotadd.rules /etc/udev/rules.d 
sed -i '/SUBSYSTEM=="memory", ACTION=="add"/d' /etc/udev/rules.d/40-vm-hotadd.rules

# 守护进程:
nvidia-smi -pm 1

1.3 检查GDS

安装完成后,验证GDS是否安装成功:

1
/usr/local/cuda-<x>.<y>/gds/tools/gdscheck.py -p

示例输出:

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
75
76
77
78
79
80
xjhui@gpu-2:/usr/local/cuda-12.8/gds/tools$  ./gdscheck -p
warn: error opening log file: Permission denied, logging will be disabled
 GDS release version: 1.13.0.11
 nvidia_fs version:  2.17 libcufile version: 2.12
 Platform: x86_64
 ============
 ENVIRONMENT:
 ============
 =====================
 DRIVER CONFIGURATION:
 =====================
 NVMe P2PDMA        : Unsupported
 NVMe               : Supported
 NVMeOF             : Unsupported
 SCSI               : Unsupported
 ScaleFlux CSD      : Unsupported
 NVMesh             : Unsupported
 DDN EXAScaler      : Unsupported
 IBM Spectrum Scale : Unsupported
 NFS                : Supported
 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_pci_p2pdma : false
 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 : 1024
 properties.max_device_cache_size_kb : 131072
 properties.max_device_pinned_mem_size_kb : 18014398509481980
 properties.posix_pool_slab_size_kb : 4 1024 16384 
 properties.posix_pool_slab_count : 128 64 64 
 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
 fs.gpfs.gds_async_support: true
 profile.nvtx : false
 profile.cufile_stats : 0
 miscellaneous.api_check_aggressive : false
 execution.max_io_threads : 0
 execution.max_io_queue_depth : 128
 execution.parallel_io : false
 execution.min_io_threshold_size_kb : 1024
 execution.max_request_parallelism : 0
 properties.force_odirect_mode : false
 properties.prefer_iouring : false
 =========
 GPU INFO:
 =========
 GPU index 0 NVIDIA H100 80GB HBM3 bar:1 bar size (MiB):131072 supports GDS, IOMMU State: Disabled
 GPU index 1 NVIDIA H100 80GB HBM3 bar:1 bar size (MiB):131072 supports GDS, IOMMU State: Disabled
 GPU index 2 NVIDIA H100 80GB HBM3 bar:1 bar size (MiB):131072 supports GDS, IOMMU State: Disabled
 GPU index 3 NVIDIA H100 80GB HBM3 bar:1 bar size (MiB):131072 supports GDS, IOMMU State: Disabled
 GPU index 4 NVIDIA H100 80GB HBM3 bar:1 bar size (MiB):131072 supports GDS, IOMMU State: Disabled
 GPU index 5 NVIDIA H100 80GB HBM3 bar:1 bar size (MiB):131072 supports GDS, IOMMU State: Disabled
 GPU index 6 NVIDIA H100 80GB HBM3 bar:1 bar size (MiB):131072 supports GDS, IOMMU State: Disabled
 GPU index 7 NVIDIA H100 80GB HBM3 bar:1 bar size (MiB):131072 supports GDS, IOMMU State: Disabled
 ==============
 PLATFORM INFO:
 ==============
 IOMMU: disabled
 Nvidia Driver Info Status: Supported(Nvidia Open Driver Installed)
 Cuda Driver Version Installed:  12080
 Platform: R8868 G13, Arch: x86_64(Linux 5.15.0-105-generic)
 Platform verification succeeded

有 Supported 则说明 GDS 配置成功,且有支持的文件系统。注意 IOMMU 需要是 disabled。如果发现gds目录下没有tools文件夹那说明toolkit安装有缺失:apt install --reinstall gds-tools-12-8 重装即可。IOMMU如果不是disabled,需要禁用。同时要求nvidia-fs版本符合要求。

后续正确添加挂载点即可:

1
2
3
4
# 挂载文件
mount -t nfs -o vers=3,nolock,proto=rdma,nconnect=8,port=20049 10.10.10.119:/test0908 /mnt/gds_rdma
# 查看挂载是否成功 rdma/nvme/nfs...
mount | grep rdma

2 GDS容器配置

起容器脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
docker run \
    --gpus all \
    --privileged \
    --ipc=host \
    --network=host \
    --cap-add SYS_ADMIN \
    --device /dev/infiniband \	# 需要挂载的 RDMA 字符设备
    --device /dev/nvidia-fs* \	# 用户端所有nvidia-fs
    -v /opt/gds/lib:/usr/local/gds/lib:ro \
    -v /sys/class/infiniband:/sys/class/infiniband:ro \	# sysfs 要挂载的 infiniband 路径
    -v /var/lib/nfsd-ro:/host/nfsd:ro \
    -v /home:/home \
		-v /usr/lib/x86_64-linux-gnu \	# GDS相关so包
    -w /workspace \
    --entrypoint="/bin/bash" \
    --name $2 \
    -itd $1

说明:gdscheck 还要读 /proc/fs/nfsd/exports 确认 NFS 服务器正在运行;容器默认没有这个挂载点,把接口只读挂进去。但是-v /proc/fs/nfsd:/proc/fs/nfsd:ro 大概率会报错,因为Docker 禁止把 /proc 子目录再挂载到容器里(proc-safety 检查),让容器只读宿主机的 /proc/fs/nfsd,用 bind mount + 只读 并且不挂在 /proc 下:

1
2
3
4
5
6
# 在宿主机先创建一个普通目录做跳板:
mkdir -p /var/lib/nfsd-ro
mount --bind /proc/fs/nfsd /var/lib/nfsd-ro

# 启动容器时挂这个跳板目录,目标路径不要放在 /proc:(即添加这行指令)
-v /var/lib/nfsd-ro:/host/nfsd:ro

通过脚本启动自己的gds容器,并配置剩余内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 启动容器
sh start_gds_container.sh 镜像ID test-gds

# 把tools拷进容器
docker cp /usr/local/cuda-12.8/gds/tools test-gds:/usr/local/cuda-12.8/gds/

# 加可执行权限
docker exec fenghao-gds chmod +x /usr/local/cuda-12.8/gds/tools/*

# 配置环境变量
vim /etc/bash.bashrc
export PATH=/usr/local/cuda-12.8/bin${PATH:+:${PATH}} 
export LD_LIBRARY_PATH=/usr/local/cuda-12.8/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
source /etc/bash.bashrc

# 检查环境变量:
echo $PATH
echo $LD_LIBRARY_PATH

检查GDS:

1
2
3
4
5
# 检查GDS
/usr/local/cuda-<x>.<y>/gds/tools/gdscheck.py -p

# 检查挂载点
cat /proc/mounts | grep rdma

注意一定要在宿主机先挂好,如果宿主机挂载点有变化记得docker restart

3 GDSIO测试

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

传输模式传输类型 (XferType)含义
0GPUD数据直接从存储传输到 GPU,绕过 CPU
1CPUONLY数据从存储传输到 CPU
2CPU_GPU数据先从存储传输到 CPU,经过处理后再传输到 GPU
3CPU_ASYNC_GPU数据先从存储传输到 CPU,然后异步传输到 GPU
4CPU_CACHED_GPU存储->页缓存->CPU->GPU
5ASYNC数据直接从存储异步传输到 GPU
6GPU_BATCH存储到 GPU 的批处理传输
7GPU_BATCH_STREAM存储到 GPU 的流式批处理传输

测试命令如下:

1
2
/usr/local/cuda-12.8/gds/tools/gdsio -f /data/test/dd.txt -d 0 -w 4 -s 10G -i 1M -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 

参数含义为:-d 设备号,-w 线程数,-s 文件大小,-i 单次I/O大小,-x 传输模式

4 如何验证真正使用了GDS?

4.1 用 gdscheck 证明挂载点/路径是 GDS-capable

1
2
3
4
5
# 查系统上哪些 FS 支持 GDS:
sudo /usr/local/cuda-*/gds/tools/gdscheck -p

# 检查实际的 gds_path
sudo /usr/local/cuda-*/gds/tools/gdscheck -p <YOUR_GDS_PATH>

4.2 看libcufile 日志,确认没有 fallback

因为 libcufile 可能内部 fallback,常用做法是设置 cuFile 日志环境变量:设置 compat_modefalse,跑完后看到明确的 “using nvidia-fs / gds path / GDS enabled” 且没有 “fallback to POSIX” 之类的字样:强证据。如果日志里出现 “POSIX fallback”:那就证明数据面不是纯 GDS。

参考资料

This post is licensed under CC BY 4.0 by the author.