基本简介
NVIDIA NCCL Tests是NVIDIA维护的NCCL通信测试工具集,用于检验NCCL操作的性能和正确性。
要理解NCCL Tests,需要先理解NCCL本身。NCCL是一个专注于GPU间通信的库,提供拓扑感知的集合通信和点对点通信原语,官方文档列出的集合通信包括AllReduce、Broadcast、Reduce、AllGather、ReduceScatter、AlltoAll、Gather和Scatter。NCCL支持单机多GPU和跨节点通信,底层可能使用PCIe、NVLink、InfiniBand Verbs或IP sockets等互联方式。
在大模型训练、分布式推理和HPC负载中,NCCL经常承担梯度同步、参数聚合、激活或专家数据交换等通信路径。应用层看到的表现通常只是”训练变慢””启动卡住””某个节点掉队”或”偶发NCCL错误”,但根因可能涉及GPU拓扑、网卡选择、IB/RoCE链路、容器权限、CUDA/NCCL版本、进程与GPU的绑定关系、集合通信算法选择乃至硬件健康状态等多个层面。NCCL Tests的价值就在于剥离真实业务逻辑,只保留可重复的NCCL通信操作,让运维和研发能够获得独立于框架的通信性能与正确性证据。
NVIDIA NCCL Tests的官方仓库地址:https://github.com/NVIDIA/nccl-tests
解决的问题
NCCL Tests主要解决以下问题:
| 问题 | 说明 |
|---|---|
| 建立通信基线 | 使用统一参数扫描消息大小,得到不同节点、不同GPU数量、不同通信操作下的time、algbw和busbw基线。 |
验证NCCL正确性 | 默认执行结果校验,输出#wrong,可以发现通信结果与期望值不一致的问题。 |
| 排查通信性能退化 | 通过单机、跨机、指定算法、指定网卡、禁用某类传输等方式做对照实验,缩小问题范围。 |
| 验证集群上线质量 | 在新节点、扩容节点、驱动升级、NCCL升级、交换机变更后快速确认通信路径是否符合预期。 |
| 提供框架无关证据 | 不依赖PyTorch、TensorFlow或业务代码,方便把问题定位在通信栈、系统配置或上层框架之间。 |
显著优点
| 优点 | 说明 |
|---|---|
| 官方实现 | 由NVIDIA维护,测试调用真实NCCL API,结果更接近NCCL通信栈本身的行为。 |
| 操作覆盖广 | 当前本地源码生成all_reduce_perf、all_gather_perf、broadcast_perf、reduce_scatter_perf、reduce_perf、alltoall_perf、alltoallv_perf、scatter_perf、gather_perf、sendrecv_perf和hypercube_perf。 |
| 同时看性能和正确性 | 同一轮测试既输出通信耗时与带宽,也可以执行数据校验,避免只看性能而忽略错误结果。 |
| 单机和多机一致 | 单机通过-g指定每线程GPU数,多机通过MPI管理进程数;总rank数为MPI进程数、线程数和每线程GPU数的乘积。 |
| 指标可解释 | 输出algbw和busbw,其中busbw用于把集合通信结果映射为更接近硬件瓶颈链路的带宽指标。 |
| 适合自动化 | 支持固定消息范围、循环运行、JSON输出、每迭代统计、超时、最小带宽阈值和分组并行测试。 |
工作原理
NCCL Tests不是一个后台监控组件,也不是硬件诊断工具。其工作方式是启动一组rank,为每个rank绑定一个CUDA设备,初始化NCCL communicator,在不同消息大小上执行指定通信操作,并用CUDA event和同步逻辑计算耗时。启用数据校验时,它还会准备确定性输入和期望输出,再比较实际通信结果。
rank模型
NCCL Tests可以在多个MPI进程、多个线程和每线程多个GPU上运行。README明确说明,进程数由MPI管理,不作为测试二进制的命令行参数传入。总rank数计算如下:
total_ranks = number_of_processes * number_of_threads * number_of_GPUs_per_thread
常见推荐用法是多节点运行时采用“每个MPI进程绑定一个GPU”,也就是mpirun -np TOTAL_GPUS ... -g 1。这种方式更接近PyTorch DDP、Megatron-LM等训练框架的常见部署模型,也更容易处理CPU/GPU/NUMA/NIC亲和性。
测试二进制
当前本地源码的src/Makefile中,BIN_FILES_LIST定义了以下测试二进制:
| 二进制 | 测试操作 | 常见用途 |
|---|---|---|
all_reduce_perf | AllReduce | 梯度同步、训练扩展性基线,最常用。 |
all_gather_perf | AllGather | 参数、序列、张量并行中的全量聚合路径。 |
reduce_scatter_perf | ReduceScatter | ZeRO、张量并行、分片梯度同步路径。 |
broadcast_perf | Broadcast | 参数广播、初始化同步。 |
reduce_perf | Reduce | 多rank到根rank聚合。 |
alltoall_perf | AlltoAll | 专家并行、MoE、重分布通信。 |
alltoallv_perf | AlltoAllv | 不均衡all-to-all通信,适合模拟不规则专家路由。 |
scatter_perf | Scatter | 根rank向其他rank分发不同片段。 |
gather_perf | Gather | 多rank向根rank汇聚不同片段。 |
sendrecv_perf | SendRecv | 邻居交换、点对点链路排查。 |
hypercube_perf | Hypercube | 使用send/recv构造的超立方交换模式。 |
输出指标
默认输出会分别展示out-of-place和in-place两组结果。需要注意的是,部分测试如alltoall、alltoallv和sendrecv在源码中对in-place结果不报告正确性错误,输出会显示N/A,这不是没有执行测试,而是该路径没有按相同方式报告#wrong。
| 指标 | 单位 | 含义 |
|---|---|---|
size | B | 本行测试的消息大小,小消息主要看延迟,大消息主要看带宽。 |
count | 元素数 | 按数据类型换算后的元素数量,需要结合type共同决定真实字节数。 |
type | 字符串 | float、half、bfloat16等数据类型,支持范围取决于编译和运行时NCCL/CUDA版本。 |
redop | 字符串 | sum、prod、max、min、avg、mulsum等规约操作,只对规约类通信有实际意义。 |
root | rank | 根rank,对broadcast、reduce、gather、scatter等操作有意义。 |
time | us | 平均每次操作耗时,默认来自CUDA event计时,使用-C 1时改为CPU时间。 |
algbw | GB/s | 算法带宽,常见公式为数据规模除以耗时,适合估算同类操作耗时。 |
busbw | GB/s | 链路等效带宽,经集合通信模式修正后更贴近硬件瓶颈链路的实际利用率,适合与NVLink、PCIe或网络瓶颈能力对比。 |
#wrong | 个数 | 正确性校验发现的错误元素数,非0表示通信结果不符合期望。 |
NCCL Tests的性能文档强调,小消息的time主要反映固定开销或延迟;大消息的耗时则更接近”固定开销 + 数据规模 / 带宽”的模型,因此大消息更适合评估带宽。algbw是按操作数据规模和耗时计算的算法带宽,而busbw会根据集合通信模式乘以修正系数,使结果更贴近硬件通信瓶颈。
常见操作的busbw修正系数如下:
| 操作 | busbw修正方式 |
|---|---|
AllReduce | algbw * 2 * (n - 1) / n |
ReduceScatter | algbw * (n - 1) / n |
AllGather | algbw * (n - 1) / n |
AlltoAll | algbw * (n - 1) / n |
Broadcast | algbw |
Reduce | algbw |
其中n是参与本次NCCL communicator的rank数量。对AllReduce而言,busbw通常比algbw高,因为每个元素需要规约并分发,通信量修正系数是2 * (n - 1) / n。对Broadcast和Reduce而言,根rank通常是瓶颈,因此busbw等于algbw。
能够检测的常见问题
严格来说,NCCL Tests直接检测的是“通信操作是否成功、结果是否正确、耗时和带宽是否符合基线”。它不会像DCGM Diagnostics那样直接读取硬件健康字段,也不会自动告诉你根因是交换机、网卡、PCIe、驱动还是容器权限。但它非常适合作为通信栈的主动探针,通过可重复的对照测试把问题范围缩小。
问题概览
| 问题类型 | 典型表现 | NCCL Tests检测方式 | 后续定位手段 |
|---|---|---|---|
| 数据正确性问题 | #wrong非0,尾部Out of bounds values为FAILED。 | 默认-c 1生成期望结果并比较实际结果。 | 查看NCCL日志、驱动日志、XID、硬件健康状态。 |
| 通信性能退化 | busbw明显低于历史基线或同型号节点。 | 固定参数重复扫描消息大小,或用NCCL_TESTS_MIN_BW设置自动失败阈值。 | 检查NVLink/PCIe/IB/RoCE、亲和性、NCCL_ALGO、NCCL_PROTO。 |
| 多节点网络问题 | 单机正常,多机慢、报错或卡住。 | 对比单机-g 8与多机mpirun -np ... -g 1结果。 | 用NCCL_DEBUG=INFO、NCCL_DEBUG_SUBSYS=NET、ibstat、ib_write_bw等排查。 |
| 拓扑或链路异常 | 某些节点busbw明显偏低,跨GPU组差异大。 | 使用NCCL_TESTS_SPLIT拆分组,分别测节点内和节点间通信。 | 查看nvidia-smi topo -m、NCCL_TOPO_DUMP_FILE、DCGM拓扑检查。 |
| 初始化或异步错误 | ncclCommInitRank失败,首个集合通信失败,运行中异步错误。 | 源码中封装NCCLCHECK,运行期间查询ncclCommGetAsyncError,必要时ncclCommAbort。 | 开启NCCL_DEBUG=WARN/INFO,检查MPI启动和网络可达性。 |
| 超时或挂起 | 测试长时间无输出。 | 使用-T SECONDS为测试同步阶段设置超时,超时后中止通信器。 | 结合NCCL RAS、NCCL_DEBUG_FILE和节点日志分析。 |
| 迭代抖动和掉队 | 平均带宽尚可,但训练不稳定或尾延迟高。 | 使用-I 1输出i_min、i_max、i_p99和i_cv%,再用tools/analyze_perf_json.py分析。 | 检查进程绑核、NUMA、网卡亲和性、后台任务和功耗限制。 |
GPU数量或绑定错误 | 请求GPU数量超过实际设备,或rank落到错误设备。 | 启动时打印每个rank的主机名、PID、CUDA设备号和PCI BDF。 | 修正mpirun、调度器、CUDA_VISIBLE_DEVICES、NCCL_TESTS_DEVICE。 |
| 显存不足 | 大消息测试失败或被自动降低maxBytes。 | 源码会根据可用显存保留空间,并在必要时降低maxBytes;-M 1可输出显存使用。 | 降低-e、关闭校验-c 0、排空业务进程。 |
| 不规则通信失衡 | MoE类负载中某些rank通信量过大。 | alltoallv_perf支持距离加权模式和矩阵文件模式。 | 使用-a 3看最慢rank时间,开启NCCL_TESTS_ALLTOALLV_PRINT_SUMMARY。 |
正确性校验
默认参数-c 1会进行一次正确性校验。源码中BenchTime方法先执行性能测试,再按datacheck参数指定的次数循环执行数据初始化、单次通信和结果比较。输入数据和期望结果由verifiable目录中的校验逻辑生成,结果比较会统计错误元素数。
校验相关输出包括:
| 输出 | 含义 |
|---|---|
#wrong | 当前消息大小、当前操作的错误元素数。 |
Out of bounds values : 0 OK | 汇总校验没有发现错误。 |
Out of bounds values : 非0 FAILED | 至少有校验失败。 |
进程退出码非0 | 源码在错误数非0或最小带宽阈值失败时返回非成功状态。 |
正确性校验很有价值,但要注意两个限制。第一,它会额外分配expected缓冲区,显存压力比纯性能测试更大。第二,大规模、多GPU、多数据类型全量扫描时会明显变慢。做性能压测可以临时使用-c 0关闭校验,但上线验收或疑似数据错误时不建议关闭。
性能退化和基线失败
性能退化通常不是看单次绝对值,而是看同一批硬件、同一软件版本、同一参数下的相对变化。建议基线至少固定以下维度:
| 维度 | 建议固定内容 |
|---|---|
| 硬件 | GPU型号、GPU数量、NVLink/PCIe拓扑、NIC型号、交换机和链路速率。 |
| 软件 | 驱动版本、CUDA版本、NCCL头文件和运行库版本、MPI版本。 |
| 启动方式 | 每节点进程数、每进程GPU数、进程绑核、CUDA_VISIBLE_DEVICES。 |
| 测试参数 | 二进制、-b、-e、-f或-i、-n、-w、-c、-a。 |
| 环境变量 | 所有显式设置的NCCL_*和NCCL_TESTS_*变量。 |
源码支持NCCL_TESTS_MIN_BW作为最小平均busbw阈值。尾部输出Avg bus bandwidth时,如果平均busbw低于该阈值的90%,会在输出中标记FAILED并以非零退出码退出。这个设计适合自动化巡检,但阈值必须来自同环境历史基线,不能直接照搬其他集群的数值。
网络、拓扑和亲和性问题
NCCL Tests本身不会直接输出“错误网卡”或“拓扑错误”,但它能让这些问题以性能或失败形态暴露出来。常见方法是构造对照组:
| 对照方式 | 目标 |
|---|---|
单节点-g 8对比多节点mpirun -np ... -g 1 | 区分节点内和节点间问题。 |
设置NCCL_TESTS_SPLIT="MOD 8" | 在每节点8 GPU场景下拆成8组,每组跨节点通信,突出节点间网络瓶颈。 |
设置NCCL_TESTS_SPLIT="DIV 8" | 每节点形成一组,主要观察节点内通信。 |
指定NCCL_SOCKET_IFNAME | 验证NCCL是否选择了预期IP网卡。 |
设置NCCL_IB_DISABLE=1 | 临时禁用IB/RoCE,迫使回退IP sockets,用于判断IB/RoCE路径是否异常。 |
设置NCCL_TOPO_DUMP_FILE | 保存NCCL检测到的拓扑XML,用于与硬件拓扑做比对。 |
NCCL官方文档提醒,环境变量分为系统配置和调试类参数。调试类参数不应长期保留在生产脚本中,因为它们可能导致性能次优、崩溃或挂起。因此,诸如NCCL_IB_DISABLE、NCCL_ALGO、NCCL_PROTO这类变量更适合用于短期对照实验,定位完成后应恢复默认或只保留确有依据的系统配置。
抖动和尾延迟
平均带宽无法解释所有训练问题。某些场景中,平均busbw接近基线,但训练仍然周期性变慢,常见原因是某些进程、节点或链路出现尾延迟。当前源码支持-I 1收集每迭代CUDA event计时,输出i_min、i_max、i_p99和i_cv%;配合-J result.json还会写入原始迭代数据。仓库中的tools/analyze_perf_json.py可以读取这些数据,输出尖峰、掉队进程和节点聚合分析。
-I 1和-G的CUDA Graph模式不兼容,源码会自动禁用每迭代计时。-K COUNT可以在汇总统计时跳过前几个迭代,适合剔除刚启动时的预热波动;但原始JSON数据仍然完整保留。
AlltoAllv不均衡通信
alltoallv_perf用于不规则all-to-all模式,适合模拟MoE专家路由、动态负载分发等场景。当前源码支持两种模式:
| 模式 | 配置 | 说明 |
|---|---|---|
| 距离加权生成模式 | 默认模式,NCCL_TESTS_ALLTOALLV_SPREAD控制不均衡程度。 | 0.0表示均匀分布,1.0表示完全距离加权。 |
| 矩阵文件模式 | 设置NCCL_TESTS_ALLTOALLV_MATRIX_FILE。 | 文件为方阵,单元格表示从源rank到目标rank的字节数。 |
矩阵文件模式有两个重要约束。第一,-b和-e必须相等,因为消息大小来自矩阵而不是扫描参数。第二,-e至少要覆盖所有rank中最大的发送或接收总字节数,否则测试缓冲区不足。对于不均衡负载,源码注释建议使用-a 3报告跨rank最大耗时,避免默认平均值被空闲或轻载rank稀释。
安装和构建
前置依赖
| 依赖 | 是否必需 | 说明 |
|---|---|---|
CUDA Toolkit | 必需 | 需要nvcc、CUDA头文件和运行库。默认路径为/usr/local/cuda。 |
NCCL | 必需 | 需要NCCL头文件和库。默认从系统路径查找,也可设置NCCL_HOME。 |
C++编译器 | 必需 | 当前common.mk中,CUDA 13及以上默认使用C++17,较低版本默认使用C++14。 |
MPI | 多机必需 | 多进程、多节点测试需要编译时设置MPI=1和MPI_HOME。 |
Linux工具链 | 常见必需 | make、gcc/g++、ldconfig等基础工具。 |
如果只测试单进程单节点,可以不启用MPI。如果需要多节点或每GPU一个MPI进程,应编译MPI版本。
基础构建
cd /Users/john/Workspace/github/NVIDIA/nccl-tests
make -j CUDA_HOME=/usr/local/cuda NCCL_HOME=/usr
如果CUDA或NCCL安装在非默认路径,需要显式指定:
make -j CUDA_HOME=/path/to/cuda NCCL_HOME=/path/to/nccl
构建完成后,二进制默认位于build/目录,例如:
ls build/*_perf
编译MPI版本
cd /Users/john/Workspace/github/NVIDIA/nccl-tests
make -j MPI=1 MPI_HOME=/path/to/mpi CUDA_HOME=/path/to/cuda NCCL_HOME=/path/to/nccl
为了同时保留非MPI和MPI版本,可以使用NAME_SUFFIX:
make -j MPI=1 NAME_SUFFIX=_mpi MPI_HOME=/path/to/mpi CUDA_HOME=/path/to/cuda NCCL_HOME=/path/to/nccl
这样会生成类似build/all_reduce_perf_mpi的二进制。
减少编译目标架构
当前源码会根据CUDA版本设置一组默认NVCC_GENCODE。如果只面向固定型号GPU,可以显式设置NVCC_GENCODE减少编译时间和二进制体积。例如只为Ampere的sm_80构建:
make -j \
CUDA_HOME=/usr/local/cuda \
NCCL_HOME=/usr \
NVCC_GENCODE="-gencode=arch=compute_80,code=sm_80"
运行前检查
建议在运行前确认以下信息:
nvidia-smi
nvcc --version
ldconfig -p | grep nccl
mpirun --version
多节点运行还需要确认:
| 检查项 | 目的 |
|---|---|
SSH或调度器启动方式 | 确认MPI可以在所有节点拉起进程。 |
NCCL库路径 | 确保所有节点加载同一版本libnccl.so。 |
CUDA_VISIBLE_DEVICES | 确认进程看到的GPU序号符合预期。 |
| 网卡和防火墙 | 确认节点间IP/IB/RoCE可达。 |
| 容器权限 | 确认容器具备访问GPU、共享内存和网络设备的权限。 |
使用和配置
常用参数
| 参数 | 默认值 | 说明 |
|---|---|---|
-t,--nthreads | 1 | 每进程线程数。 |
-g,--ngpus | 1 | 每线程使用的GPU数。 |
-b,--minbytes | 32M | 起始消息大小。K/M/G按二进制单位解析(即1K = 1024,1M = 1048576)。 |
-e,--maxbytes | 32M | 最大消息大小。 |
-i,--stepbytes | 1M | 固定步长。 |
-f,--stepfactor | 禁用 | 倍增步长,例如-f 2。 |
-n,--iters | 20 | 每个消息大小的计时迭代次数。 |
-w,--warmup_iters | 1 | 不计时预热迭代次数。 |
-m,--agg_iters | 1 | 每次外层迭代中聚合执行的操作次数。 |
-N,--run_cycles | 1 | 完整扫描循环次数,0表示无限循环。 |
操作参数
| 参数 | 默认值 | 说明 |
|---|---|---|
-o,--op | sum | 规约操作,支持范围随NCCL版本变化,常见值为sum/prod/min/max/avg/mulsum/all。 |
-d,--datatype | float | 数据类型,常见值包括int8、uint8、int32、uint32、int64、uint64、half、float、double、bfloat16和fp8类型。 |
-r,--root | 0 | 根rank,对broadcast、reduce、gather和scatter有意义。 |
-c,--check | 1 | 正确性校验次数,0表示关闭校验。 |
-p,--parallel_init | 0 | 是否由多线程并发初始化NCCL communicator。 |
-z,--blocking | 0 | 集合通信阻塞模式,支持0/1/2/3。 |
-u,--unalign | 0 | 让发送和接收缓冲区按元素偏移,用于测试非对齐场景。 |
输出和诊断参数
| 参数 | 默认值 | 说明 |
|---|---|---|
-J,--output_file | 空 | 写入JSON文件,当前源码按后缀识别,仅支持json。 |
-I,--per_iter_timing | 0 | 输出每迭代统计列。 |
-K,--per_iter_skip | 0 | 汇总每迭代统计时跳过前若干迭代。 |
-S,--report_timestamps | 0 | 在性能行追加时间戳。 |
-T,--timeout | 禁用 | 为测试同步阶段设置超时时间。 |
-M,--memory | 0 | 输出初始化、用户缓冲区和集合通信的显存使用。 |
-C,--report_cputime | 0 | 使用CPU时间而不是CUDA event时间。 |
-a,--average | 1 | MPI场景下汇总耗时,0为Rank0,1为平均,2为最小,3为最大。 |
高级参数
| 参数 | 条件 | 说明 |
|---|---|---|
-G,--cudagraph | 需要支持的CUDA/NCCL版本 | 捕获迭代为CUDA Graph并重复回放。与-I 1不兼容。 |
-R,--local_register | NCCL >= 2.19相关功能 | 对发送和接收缓冲区启用本地或对称注册,2表示对称注册。 |
-D,--device_implementation | 需要NCCL >= 2.28,且要求-R 2 | 使用设备侧实现。当前源码说明并非所有集合通信都支持,主要是all_reduce和alltoall。 |
-V,--device_cta_count | 配合-D使用 | 设置设备侧实现的CTA数量,源码要求大于0且小于128。 |
-x,--cta_policy | 需要支持的NCCL版本 | 设置NCCL communicator的CTA policy。 |
NCCL Tests环境变量
| 环境变量 | 作用 |
|---|---|
NCCL_TESTS_DEVICE | 指定起始CUDA设备号。未设置时,源码根据本地rank自动分配连续设备。 |
NCCL_TESTS_MIN_BW | 设置平均busbw基线阈值。低于阈值90%时标记失败。 |
NCCL_TESTS_SPLIT | 按AND/OR/MOD/DIV或`&/ |
NCCL_TESTS_SPLIT_MASK | 等价于NCCL_TESTS_SPLIT="&VALUE"。 |
NCCL_TESTS_ALLTOALLV_SPREAD | 控制alltoallv默认生成模式的不均衡程度,范围为0.0到1.0。 |
NCCL_TESTS_ALLTOALLV_MATRIX_FILE | 指定alltoallv矩阵文件,进入显式流量矩阵模式。 |
NCCL_TESTS_ALLTOALLV_MATRIX_SCALE | 对矩阵文件中的流量值做倍率缩放。 |
NCCL_TESTS_ALLTOALLV_PRINT_SUMMARY | 输出alltoallv每rank发送、接收和带宽摘要。 |
常用NCCL环境变量
这些变量属于NCCL库本身,不是NCCL Tests独有。建议只在排查或有明确系统配置依据时设置。
| 环境变量 | 作用 | 使用建议 |
|---|---|---|
NCCL_DEBUG | 控制日志级别,常见值为VERSION、WARN、INFO、TRACE。 | 日常排查使用WARN或INFO,TRACE日志量很大。 |
NCCL_DEBUG_SUBSYS | 过滤INFO日志子系统。 | 网络问题常用NET,拓扑问题常用INIT,GRAPH。 |
NCCL_DEBUG_FILE | 将NCCL日志写入文件。 | 多进程建议包含%h和%p,避免日志互相覆盖。 |
NCCL_SOCKET_IFNAME | 指定NCCL使用的IP网卡前缀或精确名称。 | 多网卡环境建议显式验证。 |
NCCL_IB_DISABLE | 禁用IB/RoCE传输,回退到IP sockets。 | 只适合短期对照实验。 |
NCCL_IB_HCA | 筛选IB/RoCE设备。 | 用于验证特定HCA或排除异常网卡。 |
NCCL_TOPO_DUMP_FILE | 将NCCL检测到的拓扑输出为XML。 | 用于比对GPU/NIC/NVLink/PCIe拓扑。 |
NCCL_ALGO | 限制或排除通信算法。 | 用于算法对照,不建议长期硬编码。 |
NCCL_PROTO | 限制或排除通信协议。 | 用于协议对照,不建议长期硬编码。 |
使用示例
单节点8 GPU测试AllReduce
cd /Users/john/Workspace/github/NVIDIA/nccl-tests
./build/all_reduce_perf -b 8 -e 128M -f 2 -g 8
这个命令在单进程中使用8个GPU,从8B扫到128MiB,每次消息大小乘以2。它适合快速观察单机NVLink或PCIe通信基线。
多节点每GPU一个MPI进程
mpirun -np 64 -N 8 \
./build/all_reduce_perf_mpi -b 8 -e 8G -f 2 -g 1
这个命令适用于8个节点、每节点8 GPU、总共64 GPU的场景。-N 8是mpirun的每节点进程数参数,测试二进制自身仍然使用-g 1,表示每个进程只管理一个GPU。
关闭校验做纯性能扫描
./build/all_reduce_perf -b 1M -e 16G -f 2 -g 8 -n 100 -w 10 -c 0
-c 0会关闭正确性校验,减少expected缓冲区和校验开销。这个模式适合大消息纯性能压测,但不能证明通信结果正确。
输出每迭代统计和JSON
./build/all_reduce_perf \
-b 8M -e 1G -f 2 -g 8 \
-n 200 -w 20 \
-I 1 -K 10 \
-J allreduce_iter.json
python3 tools/analyze_perf_json.py allreduce_iter.json --all
-I 1会输出尾延迟和抖动统计;-K 10表示汇总时跳过前10个迭代;-J保留原始结构化结果,便于后续自动分析。
节点内与节点间拆分对照
在每节点8 GPU、每GPU一个MPI进程的场景下,测试跨节点网络路径:
NCCL_TESTS_SPLIT="MOD 8" \
mpirun -np 64 -N 8 ./build/all_reduce_perf_mpi -b 8M -e 1G -f 2 -g 1
测试节点内通信路径:
NCCL_TESTS_SPLIT="DIV 8" \
mpirun -np 64 -N 8 ./build/all_reduce_perf_mpi -b 8M -e 1G -f 2 -g 1
这种拆分方式很适合判断问题主要发生在节点内NVLink/PCIe,还是节点间IB/RoCE/IP网络。
带日志的网络排查
NCCL_DEBUG=INFO \
NCCL_DEBUG_SUBSYS=INIT,NET,GRAPH \
NCCL_DEBUG_FILE=/tmp/nccl.%h.%p.log \
NCCL_SOCKET_IFNAME='=ib0' \
mpirun -np 16 -N 8 ./build/all_reduce_perf_mpi -b 8M -e 1G -f 2 -g 1 -T 120
这个示例将NCCL日志写到每个主机和进程独立的文件中,并显式指定IP网卡。NCCL_SOCKET_IFNAME的值前面带一个等号时表示精确匹配接口名;如果只想匹配前缀,可以写成NCCL_SOCKET_IFNAME=ib。
AlltoAllv矩阵模式
准备流量矩阵:
0 1048576 2097152 3145728
1048576 0 1048576 2097152
2097152 1048576 0 1048576
3145728 2097152 1048576 0
运行测试:
NCCL_TESTS_ALLTOALLV_MATRIX_FILE=traffic.txt \
NCCL_TESTS_ALLTOALLV_PRINT_SUMMARY=1 \
mpirun -np 4 ./build/alltoallv_perf_mpi -b 8M -e 8M -g 1 -a 3
这里-b和-e保持一致,-a 3使用跨rank最大耗时,更适合观察不均衡通信中的慢rank。
结果解读建议
不同消息大小看不同指标
| 消息范围 | 重点指标 | 常见解释 |
|---|---|---|
B到KB级 | time、i_p99、i_cv% | 更容易受启动开销、调度、CPU亲和性和协议选择影响。 |
MB级 | algbw、busbw、曲线斜率 | 观察链路利用率是否爬升到稳定区间。 |
GB级 | busbw、稳定性、显存压力 | 适合压测带宽上限和显存分配边界。 |
不要孤立看busbw
busbw的价值是跨不同rank数量和集合通信操作更容易比较硬件瓶颈,但它仍然依赖测试参数和通信模式。至少要同时保留:
NCCL Tests命令行参数。NCCL、CUDA、驱动和MPI版本。- 输出开头的
rank、主机名、GPU设备号和PCI BDF。 - 所有
NCCL_*和NCCL_TESTS_*环境变量。 - 同环境历史基线和同型号健康节点结果。
常见判断路径
| 现象 | 更可能的方向 |
|---|---|
| 单机慢,多机也慢 | 节点内NVLink/PCIe、GPU功耗/温度、驱动或NCCL版本。 |
| 单机正常,多机慢 | 网络接口选择、IB/RoCE、交换机、路由、GDR路径。 |
平均正常,i_max很高 | 进程或节点掉队、后台任务、亲和性、链路拥塞。 |
| 只有某些消息大小慢 | NCCL算法或协议阈值、NCCL_ALGO、NCCL_PROTO、分片策略。 |
#wrong非0 | 通信正确性或硬件稳定性问题,应优先停止性能结论。 |
| 初始化失败 | NCCL版本、网络可达性、MPI启动、容器权限、共享内存。 |
与类似工具对比
| 工具 | 定位与优势 | 适用场景与边界 |
|---|---|---|
NCCL Tests | 测试NCCL操作性能和正确性,直接调用NCCL API,覆盖训练常用集合通信并输出busbw。 | 适合GPU训练通信基线、NCCL升级验证和跨节点通信排查;不直接做硬件健康诊断,根因需要结合其他工具。 |
NVIDIA HPC Benchmarks中的nccl_tests.sh | 在HPC基准套件中包装运行NCCL Tests,提供多节点、多GPU运行脚本和亲和性参数。 | 适合集群验收和标准化HPC基准作业;本质仍是调用NCCL Tests,灵活性取决于包装脚本。 |
DCGM Diagnostics | 检查部署、软件、硬件、PCIe/NVLink、显存、压力和集成问题,支持JSON输出,也包含nccl_tests插件。 | 适合节点健康检查、故障后诊断和调度系统集成;通信微基准测试灵活性不如直接运行NCCL Tests。 |
NVBandwidth | 测量NVIDIA GPU上的各种memcpy链路带宽,更贴近原始GPU内存、NVLink和PCIe拷贝能力。 | 适合判断底层链路带宽是否健康;不测试NCCL集合通信语义和规约正确性。 |
OSU Micro-Benchmarks | 覆盖MPI、OpenSHMEM、UPC、UPC++和NCCL等微基准,便于比较不同通信栈。 | 适合网络、MPI和多通信模型横向评估;busbw解释和训练实践贴合度不如NCCL Tests直接。 |
Intel MPI Benchmarks | 测试符合MPI-1/2/3标准的基础通信操作,并包含GPU相关扩展。 | 适合MPI作业性能和CPU/GPU MPI通信验证;不是NCCL专项工具,不能替代NCCL通信基线。 |
RCCL Tests | AMD ROCm/RCCL生态中的类似测试,面向RCCL,用法与NCCL Tests相近。 | 适合AMD GPU集群中的RCCL通信验证;原独立ROCm/rccl-tests仓库已标注迁移或弃用,需以当前ROCm仓库为准。 |
选型上,可以按以下原则组合使用:
- 先用
DCGM Diagnostics确认节点基础健康,包括驱动、CUDA/NVML访问、PCIe/NVLink、显存和压力测试。 - 再用
NVBandwidth确认底层GPU链路和拷贝能力是否接近预期。 - 然后用
NCCL Tests确认真实NCCL集合通信性能和正确性。 - 如果问题跨越
MPI启动、CPU网络或非NCCL通信栈,再补充OSU Micro-Benchmarks或Intel MPI Benchmarks。