NCCL 带宽测试使用方法

本文档说明如何使用 NVIDIA nccl-tests 在单机 8 张 V100 GPU 上测试 NCCL AllReduce 和 AllGather 通信带宽。该测试适合用于检查 GPU 互联、NCCL 安装、CUDA 环境和分布式训练通信性能上限。

1. 工具来源

nccl-tests 是 NVIDIA 官方提供的 NCCL collective 通信性能与正确性测试工具。

官方 Git 仓库:

text 复制代码
https://github.com/NVIDIA/nccl-tests.git

当前 workspace 中已有一份源码:

bash 复制代码
/root/workspace/nccl-tests

当前本地仓库的远程地址为:

bash 复制代码
origin  https://github.com/NVIDIA/nccl-tests.git

2. 当前目录结构

进入项目目录:

bash 复制代码
cd /root/workspace/nccl-tests

当前目录中已经存在编译好的二进制:

bash 复制代码
build/all_reduce_perf
build/all_gather_perf

对应源码文件为:

bash 复制代码
src/all_reduce.cu
src/all_gather.cu

如果 build/all_reduce_perfbuild/all_gather_perf 存在,可以直接运行测试;如果不存在,按下文重新编译。

3. 环境要求

运行和编译 nccl-tests 通常需要:

  • NVIDIA GPU 和可用的 NVIDIA Driver
  • CUDA Toolkit,包括 nvcc
  • NCCL runtime 和 NCCL header
  • make
  • C/C++ 编译器,例如 gcc/g++

测试前建议确认系统能看到 8 张 V100:

bash 复制代码
nvidia-smi

确认 CUDA 编译器可用:

bash 复制代码
which nvcc
nvcc --version

确认 NCCL 库可被动态链接器找到:

bash 复制代码
ldconfig -p | grep nccl

如果 ldconfig 查不到 NCCL,但你明确知道 NCCL 安装路径,也可以通过 NCCL_HOMELD_LIBRARY_PATH 显式指定。

4. 获取源码

如果需要重新获取源码,可以执行:

bash 复制代码
cd /root/workspace
git clone https://github.com/NVIDIA/nccl-tests.git
cd nccl-tests

如果当前目录已经存在,不需要重复 clone。

5. 编译方法

5.1 默认编译

如果 CUDA 和 NCCL 都安装在默认路径,直接执行:

bash 复制代码
cd /root/workspace/nccl-tests
make

编译完成后会生成:

bash 复制代码
build/all_reduce_perf
build/all_gather_perf
build/reduce_scatter_perf
build/alltoall_perf
...

5.2 指定 CUDA 和 NCCL 路径

如果 CUDA 或 NCCL 不在默认路径,需要显式指定:

bash 复制代码
make CUDA_HOME=/path/to/cuda NCCL_HOME=/path/to/nccl

例如:

bash 复制代码
make CUDA_HOME=/usr/local/cuda NCCL_HOME=/usr/local/nccl

如果运行时报找不到动态库,需要设置:

bash 复制代码
export LD_LIBRARY_PATH=/path/to/cuda/lib64:/path/to/nccl/lib:$LD_LIBRARY_PATH

5.3 针对 V100 减少编译架构

V100 的 CUDA compute capability 是 sm_70。如果只在 V100 上使用,可以通过 NVCC_GENCODE 减少编译目标,缩短编译时间:

bash 复制代码
make NVCC_GENCODE="-gencode=arch=compute_70,code=sm_70"

如果还需要保留 PTX fallback,可以使用:

bash 复制代码
make NVCC_GENCODE="-gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_70,code=compute_70"

5.4 清理并重新编译

bash 复制代码
make clean
make

6. 单机八卡测试命令

以下命令使用单进程管理 8 张 GPU,即 -g 8。这适合单机八卡 V100 测试。

6.1 AllReduce 快速测试

bash 复制代码
cd /root/workspace/nccl-tests

CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
./build/all_reduce_perf -b 8 -e 1G -f 2 -g 8 -w 20 -n 100

6.2 AllGather 快速测试

bash 复制代码
cd /root/workspace/nccl-tests

CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
./build/all_gather_perf -b 8 -e 512M -f 2 -g 8 -w 20 -n 100

AllGather 的接收 buffer 会随 world size 放大,显存压力比 AllReduce 更高。因此 AllGather 示例默认最大消息大小使用 512M。如果显存不足,可以降低到 256M128M

7. 推荐的正式测试命令

建议正式测试时关闭 correctness check,并保存日志。

7.1 AllReduce

bash 复制代码
cd /root/workspace/nccl-tests
mkdir -p logs

CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
./build/all_reduce_perf -b 8 -e 1G -f 2 -g 8 -w 20 -n 100 -c 0 \
2>&1 | tee logs/v100_8gpu_all_reduce.log

7.2 AllGather

bash 复制代码
cd /root/workspace/nccl-tests
mkdir -p logs

CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
./build/all_gather_perf -b 8 -e 512M -f 2 -g 8 -w 20 -n 100 -c 0 \
2>&1 | tee logs/v100_8gpu_all_gather.log

8. 常用参数说明

-g 8:每个进程使用 8 张 GPU。单机八卡测试通常使用该参数。

-b 8:最小消息大小,从 8 bytes 开始。

-e 1G:最大消息大小,到 1 GB 结束。

-f 2:消息大小按 2 倍递增,例如 8B、16B、32B,直到最大消息大小。

-w 20:warmup 轮数,不计入最终性能统计。

-n 100:正式计时迭代轮数。迭代越多,结果越稳定,运行时间也越长。

-c 0:关闭结果正确性检查。性能测试推荐关闭,以减少额外开销。

-d float:指定数据类型。默认通常为 float

-z 1:使用 blocking collective。默认通常为非 blocking 模式。一般性能测试保持默认即可。

9. 输出结果说明

输出表格中重点关注以下列:

time:单次 collective 操作的平均耗时。

algbw:algorithm bandwidth,按用户可见的数据量计算出的算法带宽。

busbw:bus bandwidth,按 collective 在底层互联上产生的通信量折算出的总线带宽。

比较 GPU 互联能力时,通常优先看大消息大小下的 busbw,例如 128M256M512M1G 对应的行。

典型输出格式如下:

text 复制代码
size         count       type   redop   root   time   algbw   busbw
...

如果要比较多次测试结果,应固定以下条件:

  • GPU 编号,即 CUDA_VISIBLE_DEVICES
  • 消息大小范围,即 -b-e-f
  • warmup 和 iteration 数量,即 -w-n
  • 机器负载,避免同时运行其他 GPU 或网络密集任务
  • NCCL、CUDA、Driver 版本

10. 常见测试场景

10.1 短测试,确认程序可运行

bash 复制代码
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
./build/all_reduce_perf -b 8M -e 128M -f 2 -g 8 -w 5 -n 20

10.2 只测试固定消息大小

例如只测试 256 MB AllReduce:

bash 复制代码
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
./build/all_reduce_perf -b 256M -e 256M -g 8 -w 20 -n 100 -c 0

例如只测试 256 MB AllGather:

bash 复制代码
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \
./build/all_gather_perf -b 256M -e 256M -g 8 -w 20 -n 100 -c 0

10.3 只测试部分 GPU

例如只测试前 4 张 GPU:

bash 复制代码
CUDA_VISIBLE_DEVICES=0,1,2,3 \
./build/all_reduce_perf -b 8 -e 1G -f 2 -g 4 -w 20 -n 100 -c 0

注意:CUDA_VISIBLE_DEVICES 中的 GPU 数量应与 -g 参数一致。

11. 多进程或多机测试说明

本文档主要针对单机八卡测试,使用 -g 8 即可。

如果需要多进程或多机测试,需要使用 MPI,并在编译时启用 MPI:

bash 复制代码
make MPI=1 MPI_HOME=/path/to/mpi CUDA_HOME=/path/to/cuda NCCL_HOME=/path/to/nccl

多机运行示例:

bash 复制代码
mpirun -np 16 -N 8 ./build/all_reduce_perf -b 8 -e 1G -f 2 -g 1

这里 -np 16 表示总进程数为 16,-N 8 表示每个节点 8 个进程,-g 1 表示每个进程使用 1 张 GPU。

12. 常见问题

12.1 找不到 CUDA 动态库

现象通常类似:

text 复制代码
error while loading shared libraries: libcudart.so: cannot open shared object file

处理方式:

bash 复制代码
export CUDA_HOME=/usr/local/cuda
export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH

12.2 找不到 NCCL 动态库

现象通常类似:

text 复制代码
error while loading shared libraries: libnccl.so: cannot open shared object file

处理方式:

bash 复制代码
export NCCL_HOME=/path/to/nccl
export LD_LIBRARY_PATH=$NCCL_HOME/lib:$LD_LIBRARY_PATH

12.3 AllGather 显存不足

AllGather 的输出 buffer 大小约为输入数据乘以 GPU 数量。八卡测试时显存压力明显高于 AllReduce。

如果出现 OOM,可以降低最大消息大小:

bash 复制代码
./build/all_gather_perf -b 8 -e 256M -f 2 -g 8 -w 20 -n 100 -c 0

12.4 -g 与可见 GPU 数量不一致

如果设置:

bash 复制代码
CUDA_VISIBLE_DEVICES=0,1,2,3

则应使用:

bash 复制代码
-g 4

不要在只暴露 4 张 GPU 时使用 -g 8

13. 建议记录的信息

为了便于复现实验结果,建议每次测试保存以下信息:

  • GPU 型号和数量,例如 8 x V100
  • nvidia-smi 输出中的 Driver 和 CUDA 版本
  • NCCL 版本
  • 测试命令完整参数
  • CUDA_VISIBLE_DEVICES 设置
  • all_reduce_perfall_gather_perf 的完整输出日志
  • 是否有其他任务同时占用 GPU

可使用以下命令保存基本环境信息:

bash 复制代码
mkdir -p logs
nvidia-smi > logs/v100_8gpu_env_nvidia_smi.txt

如需记录 NCCL 运行细节,可以临时打开 NCCL 日志:

bash 复制代码
export NCCL_DEBUG=INFO

正式性能测试时,如果不需要调试,建议关闭详细日志,避免干扰输出阅读。