NCCL 通信与调试
代码仓库
https://github.com/NVIDIA/nccl-tests
代码编译
编译 nccl-tests
(MPI 版本): ”
编译支持 MPI 的 nccl-tests
是整合 nvcc
, mpicc
和 NCCL 库的关键步骤
-
初始编译命令 (基于 README):
cd /path/to/your/nccl-tests # 进入源码目录 make clean make MPI=1 CUDA_HOME=... NCCL_HOME=... MPI_HOME=/path/to/shared/mpi
-
问题遭遇 #1:
fatal error: mpi.h: No such file or directory
- 原因: 编译器 (
nvcc
或其调用的g++
) 找不到mpi.h
。虽然MPI_HOME
设置了,但 Makefile 可能没有正确地将-I$(MPI_HOME)/include
添加到编译.cu
文件的NVCCFLAGS
中。 - 尝试的解决方案 (可能无效): 在
make
命令后添加CFLAGS="-I/path/to/mpi/include" LDFLAGS="-L/path/to/mpi/lib"
。但这可能因为 Makefile 内部变量优先级而失效。 - 最终解决方案: 直接修改
src/Makefile
。找到编译.cu
文件的规则(通常包含$(NVCC) ... -c $< -o $@
),在$(NVCUFLAGS)
或编译命令中显式添加 MPI 头文件路径:# 修改 src/Makefile 中编译 .cu 的行 $(NVCC) -o $@ $(NVCUFLAGS) -I/path/to/shared/mpi/include -c $<
- 修改后,返回上层目录,重新执行
make clean
和步骤 1 中的make
命令。
- 原因: 编译器 (
-
(可能遇到的) 问题 #2: 链接时报
Unknown option '-pthread'
或-Wl,-rpath
- 原因: 如果 Makefile 内部(或你错误地)将
mpicc --showme:link
的原始输出(包含-pthread
或-Wl,...
)直接传递给了nvcc
。 - 解决方案:
- 检查 Makefile: 确保 Makefile 没有直接使用
$(shell mpicc --showme:link)
。它应该只使用MPI_HOME
来推断-L
和-l
参数,或者你之前在LDFLAGS
中只提供了-L
路径。 - 手动指定链接参数 (如果必须): 如果 Makefile 没有正确处理 MPI 链接,你需要:
- 运行
mpicc --showme:link
。 - 提取必要的
-L/path/to/mpi/lib
和-lmpi
(及其他libmpi*
依赖库)。 - 提取必要的链接器选项,如
-rpath
,--enable-new-dtags
。 - 在
make
命令中通过LDFLAGS="..."
将-L
和-l
参数传递进去。 - 编辑
src/Makefile
,找到最终链接生成可执行文件 (%_perf
) 的nvcc
命令那一行。 - 使用
-Xlinker
将提取的链接器选项(如-rpath
, 路径,--enable-new-dtags
)逐个添加到该行的$(NVLDFLAGS)
之后。例如:# 修改 src/Makefile 中链接可执行文件的行 $(NVCC) -o $@ $(NVCUFLAGS) $^ ${NVLDFLAGS} -Xlinker -rpath -Xlinker /path/to/shared/mpi/lib -Xlinker --enable-new-dtags
- 运行
- 检查 Makefile: 确保 Makefile 没有直接使用
- 原因: 如果 Makefile 内部(或你错误地)将
经过这些调整,MPI 版本的 nccl-tests
应该能成功编译出来。
运行双节点测试
-
设置无密码 SSH: 确保 Node A 和 Node B 之间可以互相进行无密码 SSH 登录 (使用
ssh-keygen
和ssh-copy-id
)。这是mpirun
远程启动进程的前提。
具体的命令为:ssh-keygen -t rsa生成密钥,ssh-copy-id root@ip地址 拷贝到另外一个服务器节点,使用ssh root@172.21.33.14 date测试是否成功免密登录。输出日期则成功设置免密。 -
最终的
mpirun
命令:# 确保环境已激活 source /path/to/your/setup_env.sh # 执行 mpirun (替换 IP/主机名和路径) mpirun -np 2 \--prefix /path/to/shared/mpi \-host nodeA_ip,nodeB_ip \-bind-to none \-x PATH \-x LD_LIBRARY_PATH \-x NCCL_DEBUG=INFO \-x LD_PRELOAD="" \/path/to/your/nccl-tests/build/all_reduce_perf -b 8 -e 1G -f 2 -g 1 -a 1
-np 2
: 启动 2 个进程,是我们要测试的场景。--prefix ...
: 帮助mpirun
在远程节点找到orted
。-host ...
: 指定两个目标节点。-bind-to none
: 避免不必要的 CPU 绑定。-x PATH -x LD_LIBRARY_PATH
: 极其重要! 尝试将包含本地 CUDA/NCCL/MPI 路径的环境变量传播到远程进程。验证传播是否成功是调试的关键(可以通过在程序早期打印环境变量来检查)。-x NCCL_DEBUG=INFO
: 启用 NCCL 详细日志,用于分析通信细节。-x LD_PRELOAD=""
: 极其重要! 覆盖/etc/ld.so.preload
,禁用干扰库。/path/to/.../all_reduce_perf
: 指向编译好的 MPI 版本测试程序。-b 8 -e 1G -f 2
: 设置测试消息大小范围 (8B to 1GB, factor 2)。-g 1
: 核心设置! 每个 MPI 进程只使用 1 个 GPU,强制 NCCL 通过网络进行通信,从而测试节点间带宽。-a 1
: 报告平均性能。
结果解读
成功运行后,输出包含丰富的信息:
-
环境与设备确认 (开头注释与日志):
- 验证 Rank 数量 (2)、节点数量 (2)、每个进程的 GPU 数量 (1) 是否正确。
- 确认进程是否运行在预期的不同节点上,并使用了正确的 GPU 设备 (NVIDIA A30)。
- 确认 CUDA 和 NCCL 版本是否一致且正确 (12.4 和 2.26.2)。
-
NCCL 初始化日志 (
NCCL INFO
):- 网络选择: 关键看
Using network ...
行。我们的结果显示Using network IB
,证明 NCCL 成功选择了 InfiniBand。如果显示Using network Socket
,则表示回退到了以太网 TCP。 - IB 细节:
NET/IB : Using [0]mlx5_0:1/IB ...
显示了使用的具体 IB 设备和端口。 - 初始化成功: 两个 Rank 都应输出
ncclCommInitRank ... Init COMPLETE
。 - 拓扑信息:
nRanks 2 nNodes 2
确认了跨节点。MNNVL 0
暗示未使用多节点 NVLink (通常需要特定硬件)。intraNodeP2pSupport 0
确认了节点内无 P2P。
- 网络选择: 关键看
-
NCCL 运行时日志 (
NCCL INFO
):Channel ... via NET/IB/1
: 再次确认数据传输路径是 InfiniBand。Connected all rings, use ring PXN 0 GDR 0
:ring
: 使用了 Ring AllReduce 算法。PXN 0
: 通信主要走网络(而非节点内 P2P/NVLink)。GDR 0
: GPUDirect RDMA 未启用。 这意味着数据路径可能是GPU -> CPU(Pinned) -> NIC -> Network -> NIC -> CPU(Pinned) -> GPU
,而非最高效的GPU -> NIC -> Network -> NIC -> GPU
。这是未来可能的优化点,但需要检查硬件/驱动/系统配置。
-
性能表格分析:
#wrong
列: 必须为 0,确保结果正确性。- 核心指标
busbw (GB/s)
: 关注大消息(如 128MB - 1GB)下的饱和带宽。 - 结果解读: 我们的测试中,峰值
busbw
稳定在 11 GB/s 左右。 - 性能评估:
- 单位换算: 100 Gbps (EDR InfiniBand 理论线速率) ≈ 12.5 GB/s (理论数据吞吐量)。
- 比较: 实测 11 GB/s 非常接近 EDR IB 的理论可用吞吐量,表明 InfiniBand 网络工作正常且性能良好。远超普通千兆以太网 (~0.12 GB/s)。
- 与预期偏差: 如果你的 IB 卡是更高速率的(如 HDR 200Gbps ≈ 25 GB/s),那么 11 GB/s 就偏低,可能原因包括交换机瓶颈、配置问题、或者未启用 GDR 的影响。
好的,我们来逐一解答你的疑问,并理清 InfiniBand、PCIe、TCP/IP 在节点间通信中的角色和速率问题。
什么是 EDR InfiniBand?
- InfiniBand (IB): 是一种高性能、低延迟的计算机网络通信标准,主要用于高性能计算 (HPC)、数据中心和存储网络。它与我们常用的以太网 (Ethernet) 是不同的技术体系。
- 速率等级: InfiniBand 有不同的速率等级,通过缩写词表示:
- SDR (Single Data Rate): 理论带宽 10 Gbps
- DDR (Double Data Rate): 理论带宽 20 Gbps
- QDR (Quad Data Rate): 理论带宽 40 Gbps
- FDR (Fourteen Data Rate): 理论带宽 56 Gbps
- EDR (Enhanced Data Rate): 理论带宽 100 Gbps
- HDR (High Data Rate): 理论带宽 200 Gbps
- NDR (Next Data Rate): 理论带宽 400 Gbps
- XDR (Extreme Data Rate): 理论带宽 800 Gbps (及更高)