解决 NCCL 多节点通信问题:从 nranks 1 到 busbw 116 MB/s
背景
最近,我尝试在两台服务器(193.0.0.101
和 193.0.0.100
)上运行 NCCL 测试程序 all_reduce_perf
,以验证 GPU 间的通信性能。测试环境为:
- 服务器:
zzp-Z790-D-AX
(RTX 4090, CUDA 11.8, 驱动 12020)和zzp-System-Product-Name
(RTX 4060 Ti, CUDA 11.8, 驱动 12080)。 - 网络:千兆以太网(
enp4s0
和eno1
)。 - 目标:实现多节点通信(
nranks 2
)并获得合理带宽(busbw
)。
然而,初始测试遇到了一系列问题,包括编译失败、跨节点通信失败和带宽极低(busbw 0
)。本文记录了问题排查和解决过程,希望对遇到类似问题的开发者有所帮助。
问题描述
- NCCL 安装目录未明确:
LD_LIBRARY_PATH
未包含 NCCL 库路径,导致测试程序可能无法加载库。
- 跨节点通信失败:
- 测试输出显示
nranks 1
和busbw 0
,表明 NCCL 仅在一个节点上运行。
- 测试输出显示
- 编译错误:
- 重新编译
nccl-tests
时,报错:fatal error: mpi.h: 没有那个文件或目录
。
- 重新编译
- MPI 网络配置错误:
- 使用
--mca btl_tcp_if_include enp4s0,eno1
导致 MPI 通信失败。
- 使用
- 低带宽问题:
- 即使通信成功,
busbw
仅为 0.0018385 GB/s,远低于千兆以太网预期(~0.1 GB/s)。
- 即使通信成功,
- 错误接口选择:
- NCCL 日志显示使用了无线接口(如
wlp0s20f3:192.168.112.19
),导致性能低下。
- NCCL 日志显示使用了无线接口(如
排查与解决步骤
1. 确认 NCCL 安装目录
- 问题:
LD_LIBRARY_PATH
未包含 NCCL 库路径。 - 解决:
- 使用
find /usr -name "libnccl*"
找到 NCCL 库:/usr/lib/x86_64-linux-gnu
。 - 更新环境变量:
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu/openmpi/lib:/usr/local/cuda/lib64
- 验证库链接:
ldd /home/zzp/Documents/code/nccl-tests/build/all_reduce_perf | grep libnccl # 输出:libnccl.so.2 => /usr/lib/x86_64-linux-gnu/libnccl.so.2
- 使用
2. 修复编译错误
- 问题:缺少 MPI 开发库,导致
mpi.h
未找到。 - 解决:
- 安装 OpenMPI 开发库:
sudo apt-get install libopenmpi-dev openmpi-bin
- 找到
mpi.h
:/usr/lib/x86_64-linux-gnu/openmpi/include
。 - 重新编译
nccl-tests
:cd /home/zzp/Documents/code/nccl-tests make clean make MPI=1 CUDA_HOME=/usr/local/cuda NCCL_HOME=/usr/lib/x86_64-linux-gnu MPI_HOME=/usr/lib/x86_64-linux-gnu/openmpi
- 验证编译:
ls ./build/all_reduce_perf ldd ./build/all_reduce_perf | grep -E "libnccl|libmpi"
- 安装 OpenMPI 开发库:
3. 修复 MPI 网络配置
- 问题:
--mca btl_tcp_if_include enp4s0,eno1
无效,hostfile
格式错误。 - 解决:
- 创建正确的
hostfile
:echo "193.0.0.101 slots=1" > hosts.txt echo "193.0.0.100 slots=1" >> hosts.txt
- 测试命令(初始):
mpirun -np 2 --hostfile hosts.txt \-x NCCL_DEBUG=TRACE \-x NCCL_IB_DISABLE=1 \-x NCCL_SOCKET_IFNAME= \-x TORCH_NCCL_BLOCKING_WAIT=1 \-x LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu/openmpi/lib:/usr/local/cuda/lib64 \/home/zzp/Documents/code/nccl-tests/build/all_reduce_perf -b 8 -e 8M -f 2 > nccl_trace.log 2>&1
- 验证 MPI 通信:
#include <mpi.h> #include <stdio.h> int main(int argc, char** argv) {MPI_Init(&argc, &argv);int rank, size;MPI_Comm_rank(MPI_COMM_WORLD, &rank);MPI_Comm_size(MPI_COMM_WORLD, &size);printf("Rank %d of %d on host %s\n", rank, size, getenv("HOSTNAME"));MPI_Finalize();return 0; }
mpicc -o mpi_test mpi_test.c scp mpi_test 193.0.0.100:/home/zzp/mpi_test mpirun -np 2 --hostfile hosts.txt /home/zzp/mpi_test
- 创建正确的
4. 解决低带宽问题
- 问题:NCCL 使用了无线接口(
wlp0s20f3:192.168.112.19
),导致busbw 0.0018385 GB/s
。 - 解决:
- 强制 NCCL 使用有线接口:
mpirun -np 2 --hostfile hosts.txt \-x NCCL_DEBUG=TRACE \-x NCCL_IB_DISABLE=1 \-x NCCL_SOCKET_IFNAME=enp4s0,eno1 \-x TORCH_NCCL_BLOCKING_WAIT=1 \-x LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu/openmpi/lib:/usr/local/cuda/lib64 \/home/zzp/Documents/code/nccl-tests/build/all_reduce_perf -b 1M -e 128M -f 2 > nccl_trace.log 2>&1
- 调整测试数据量(
-b 1M -e 128M
),带宽提升到 0.116373 GB/s(~116 MB/s)。 - 日志确认使用正确接口:
NET/Socket : Using [0]enp4s0:193.0.0.101<0> NET/Socket : Using [0]eno1:193.0.0.100<0>
- 强制 NCCL 使用有线接口:
最终结果
- 跨节点通信:
nranks 2
,两节点(193.0.0.101
和193.0.0.100
)成功通信。 - 带宽:
busbw 0.116373 GB/s
(~116 MB/s),符合千兆以太网预期。 - 接口:使用有线接口
enp4s0
和eno1
,避免了无线接口干扰。 - 日志:
nccl_trace.log
确认通信路径正确,无错误。