当nccl无法覆盖全部节点或跨网络边界时出现延迟升高、连接失败等问题,需引入tcp作为补充传输通道,具体包括确认nccl与tcp共存支持条件、修改nccl环境变量启用tcp回退机制、手动注入tcp通信插件、pytorch端适配及验证混合通信链路连通性。

如果您在配置Relax集群的分布式训练通信时,发现NCCL无法覆盖全部节点或跨网络边界时出现延迟升高、连接失败等问题,则可能是由于纯NCCL通信路径受限于InfiniBand拓扑或驱动兼容性,需引入TCP作为补充传输通道。以下是实现NCCL与TCP混合通信的具体配置步骤:
一、确认NCCL与TCP共存支持条件
NCCL 2.10及以上版本原生支持混合后端(如NCCL+TCP),但需确保各节点CUDA、NCCL、OpenMPI及内核参数协同满足多路径通信要求。关键在于禁用NCCL对非IB设备的自动屏蔽,并显式声明TCP插件加载路径。
1、执行 nvidia-smi -L 验证GPU设备可见性。
2、运行 nccl-tests/build/all_reduce_perf -b 8 -e 128M -f 2 测试纯NCCL通路是否正常。
3、检查 /usr/lib/x86_64-linux-gnu/libnccl.so 版本是否 ≥ 2.10,使用 strings /usr/lib/x86_64-linux-gnu/libnccl.so | grep "NCCL version" 提取版本号。
二、修改NCCL环境变量启用TCP回退机制
通过设置NCCL环境变量强制NCCL在检测到RDMA不可用时自动启用TCP传输层,无需替换底层通信库,适用于异构网络中部分节点无IB网卡的场景。
1、在启动训练脚本前导出以下变量:export NCCL_IB_DISABLE=1。
2、设置 export NCCL_SOCKET_IFNAME=eth0 指定TCP绑定网卡(根据实际接口名调整)。
3、启用混合探测模式:export NCCL_ALGO=Ring,Tree 并附加 export NCCL_PROTO=LL,LL128,Simple 以兼容TCP吞吐特性。
三、手动注入TCP通信插件至NCCL运行时链
当默认NCCL未内置TCP插件或需定制序列化行为时,可编译并加载独立TCP插件模块,使NCCL在初始化阶段动态注册TCP传输实例,实现与GPU间数据搬运解耦。
1、从NCCL源码树中提取 src/transport/tcp 目录,执行 make CUDA_HOME=/usr/local/cuda 编译生成 libnccl_tcp.so。
2、将编译产物复制至各节点统一路径,例如 /opt/nccl-plugins/libnccl_tcp.so。
3、设置 export NCCL_PLUGIN_PATH=/opt/nccl-plugins 并确保该路径下仅存在 libnccl_tcp.so 单一插件文件。
四、PyTorch端适配:绕过默认init_process_group限制
PyTorch默认init_process_group仅接受单一backend(如'nccl'),需通过自定义ProcessGroupTCP扩展类接管通信调度逻辑,在rank 0协调NCCL组与TCP组双初始化,并按tensor shape分流通信请求。
1、在训练主进程导入自定义模块:from relax_nccl_tcp import init_hybrid_group。
2、调用 dist.init_process_group(backend='none') 跳过原生初始化。
3、执行 init_hybrid_group(world_size, rank, nccl_ranks=[0,1,2], tcp_ranks=[3,4]) 显式划分设备角色。
五、验证混合通信链路连通性
使用轻量级ping-pong测试验证NCCL与TCP通道是否均能独立完成点对点同步,避免因某类通道静默失败导致训练hang死。
1、在NCCL节点间运行 python -m torch.distributed.run --nproc_per_node=2 --nnodes=3 --node_rank=0 --master_addr=192.168.1.10 --master_port=29500 test_nccl_ping.py。
2、在TCP节点间启动 python test_tcp_ping.py --peer_ip 192.168.1.11 --port 8888 进行裸socket往返时延采样。
3、观察日志中是否同时出现 "NCCL SEND completed in 0.87ms" 与 "TCP SEND completed in 1.23ms" 字样。











