- 高性能计算
- 通信
- 深度学习
- 分布式训练
【免费下载链接】nccl
Optimized primitives for collective multi-GPU communication
本篇技术指南围绕 NCCL 跨节点通信的网络故障排查展开,覆盖三大主题:如何正确指定 NCCL 使用的 IP 网络接口与 TCP 端口范围、如何用 perftest/RDMA 工具集对 NIC 进行带宽与延迟基线诊断、以及 InfiniBand 与 RoCE 两类组网下各自的专项检查方法(Subnet Manager、端口错误计数、连通性测试与 GPUDirect RDMA 相关问题)。读完本文,读者可以掌握一套可复制的跨节点通信排障流程,并能结合当前仓库源码理解 NCCL 报错(如ibv_reg_mr failed、ibv_modify_qp failed)背后的实现机制。以下内容基于 网络故障排查文档 整理,并结合仓库源码做了实现层面的印证与扩充。
一、IP 网络接口:NCCL 的自动检测与手动指定
NCCL 会自动检测用于跨节点通信的网络接口。风险在于:某些接口处于 UP 状态但节点之间实际无法通信,NCCL 仍可能尝试使用它们,结果就是在ncclCommInitRank等初始化函数中直接报错,甚至挂死(hang)。因此排障的第一步就是确认接口选择是否符合预期。
用 NCCL_SOCKET_IFNAME 显式指定接口
解决方案是设置NCCL_SOCKET_IFNAME环境变量。该变量接受接口前缀列表,语法要点(详见 环境变量手册):
- 多个前缀用逗号分隔,如
eth会匹配eth0、eth1等所有以eth开头的接口; - 用
=前缀做精确匹配:=eth0只使用eth0,=eth0,eth1只使用这两个接口; - 用
^前缀做排除:^docker表示不使用任何以docker开头的接口,^=docker0表示只排除docker0。
自动选择算法的行为值得注意:默认情况下,回环接口lo与 docker 接口docker*只有在没有其他可用接口时才会被选中;默认算法会优先选择以ib开头的接口;而一旦显式设置了NCCL_SOCKET_IFNAME,就会绕过自动选择算法,直接使用所有匹配手动选择的接口。
源码印证:接口发现逻辑
从源码结构看,这一逻辑位于 src/misc/socket.cc 的ncclFindInterfaces函数中:
- 优先读取
NCCL_SOCKET_IFNAME,若设置了则直接交给ncclOsFindInterfaces按用户规则过滤; - 未设置时先尝试匹配
ib前缀的接口(与文档描述的"优先 ib 接口"一致); - 都不行时依次回退到
^docker,lo,virbr(排除 docker、lo、virbr 后取其余接口)、docker、lo、virbr。
这段回退链正好解释了文档所说的故障场景:当节点上存在 UP 但不可达的接口时,自动算法可能选中它们,最终导致初始化失败或挂起。排障时应先用ip link之类的命令确认接口真实可用,再用NCCL_SOCKET_IFNAME锁定正确的接口。
二、TCP 端口范围管理
NCCL 会打开 TCP 端口用于进程互联和交换连接信息(bootstrap 阶段)。如果环境有端口限制(防火墙、安全组等),可以通过 Linux 内核的net.ipv4.ip_local_port_range属性把 NCCL 使用的端口收敛到一个可管理的范围。
把 NCCL 端口限制在50000-51000:
echo 50000 51000 > /proc/sys/net/ipv4/ip_local_port_range如需持久化,写入/etc/sysctl.conf:
echo "net.ipv4.ip_local_port_range = 50000 51000" >> /etc/sysctl.conf收敛端口范围的实际价值在于可以按范围开放防火墙规则。例如在 Google Cloud 上为打了ncclnet标签的机器开放 NCCL 端口、SSH 以及 gVNIC 的 1024-1039 端口:
gcloud compute --project=myproject firewall-rules create ncclnet-ingress \ --direction=INGRESS --priority=1 --network=ncclnet --action=ALLOW \ --rules=tcp:50000-51000,22,1024-1039 --destination-ranges=0.0.0.0/0 --target-tags=ncclnet适用前提:该示例针对 Google Cloud 的防火墙规则语法;其他云平台或自管防火墙需要用各自的方式放行相同端口范围。核心原则不变——先收敛端口范围,再按范围开墙。
三、NIC 级诊断:在跑 NCCL 之前先测链路
在 InfiniBand(或 RoCE)上运行 NCCL 之前,先做底层网络测试确认端口是 UP 的、且工作在预期配置(link layer、link rate、active 状态)下,可以省掉大量"NCCL 挂了但其实是网络问题"的误判。
3.1 端口健康快速检查:ibstatus 与 ibstat
# 按端口汇总视图 ibstatus # 按 HCA 和端口详细视图 ibstat健康端口的特征:
- 端口状态为
Active(而不是Down、Init或Armed); - 物理状态显示链路已 up(通常是
LinkUp); - link layer 符合预期(例如 RoCE 环境应为
Ethernet,纯 IB 环境为InfiniBand),且所有参与传输的 NIC 之间保持一致; - 报告的
Rate与预期组网速率一致,没有意外的降速(downshift)。
3.2 带宽测试:ib_write_bw
端口状态正常后,选两台计算节点分别作为 server 和 client 测试点对点带宽:
# server 节点 ib_write_bw -d <device> -a # client 节点 ib_write_bw -d <device> <server_hostname_or_ip> -a其中<device>替换为ibstat中显示的 HCA 设备名(例如mlx5_0),-a表示遍历所有消息大小。
GPUDirect RDMA 专项对比:排查 GPUDirect RDMA 时,建议把 host 内存结果与 GPU 内存结果做对比,以定位问题出在 PCIe/驱动路径还是纯 NIC 路径。依赖perftest的构建方式,GPU 内存选项可能包括:
# GPU 内存路径 ib_write_bw -d mlx5_0 --use_cuda=<gpu_id> <server_hostname_or_ip> -a # DMA-BUF 路径(需要内核、驱动和 perftest 构建均支持) ib_write_bw -d mlx5_0 --use_cuda=<gpu_id> --use_cuda_dmabuf <server_hostname_or_ip> -aGB300 之类的平台上,某些perftest构建还暴露额外的数据直通模式。对比结果前,先用ib_write_bw --help确认当前构建实际支持的 GPU 内存选项。
从源码结构看,NCCL 的 IB 传输同时探测这两种 GPUDirect 路径:src/transport/net_ib/gdr.cc 中的ncclIbDmaBufSupport通过一次性探测确认内核 DMA-BUF 是否可用(dmaBufSupported == 1表示可用),并与ncclIbGdrSupport()(传统 nvidia-peermem 路径)一起在 src/transport/net_ib/connect.cc 决定 flush 等优化是否启用。所以--use_cuda与--use_cuda_dmabuf的对比结果,直接对应 NCCL 运行时可能走的两条 DMA 路径。
3.3 延迟测试:ib_write_lat
带宽健康不代表尾延迟健康。如果问题表现为卡顿、长尾或间歇性变慢,还要测点对点延迟:
# server 节点 ib_write_lat -d <device> # client 节点 ib_write_lat -d <device> <server_hostname_or_ip>延迟偏高或不稳定,尤其伴随带宽波动时,通常指向拥塞、重传或链路退化。
3.4 RDMA 协议层统计:rdma statistic
rdma statistic可以在 RDMA 层识别重传或类似丢包的症状:
rdma statistic重点观察测试运行期间这些计数器是否增长:
rnr_nak_retry_err(接收未就绪引发的重传错误)packet_seq_err(报文序号错误)implied_nak_seq_err(隐含 NAK 序号错误)local_ack_timeout_err(本地 ACK 超时)
非零或持续增长的值通常意味着丢包、重试或其他传输层问题。
3.5 链路健康:mlxlink
如果问题看起来像 PCIe、C2C 或物理端口健康度退化,直接用mlxlink查链路:
mlxlink -d <mst_device>用它确认预期的链路宽度(width)、链路速率、错误状态和端口整体健康度。当带宽或延迟退化而软件配置看不出问题时,这一工具特别有用。
四、InfiniBand 网络专项排查
4.1 Subnet Manager 状态检查
InfiniBand 组网必须有 Subnet Manager(SM)在运行。用如下命令检查:
sudo sminfo如果sminfo失败或显示没有 SM,确保至少在某个节点上运行了 SM(例如opensm服务)。没有 SM 的 IB 网络无法路由,这是"整网不通"类故障的第一检查项。
4.2 端口错误计数器:perfquery
用perfquery检查链路错误、符号错误或丢包,这类计数通常指向线缆或交换机问题:
sudo perfquery -x <lid>关注错误计数器,尤其是SymbolErrorCounter、LinkErrorRecoveryCounter、LinkDownedCounter的非零值——它们可能指示硬件或布线问题。
4.3 连通性测试:ibping
ibstat/ibstatus看不出问题但仍怀疑连通性时,用ibping测试节点间连通性。ibping需要先在对端节点启动 server:
# 在远端节点启动 ibping server sudo ibping -S # 在本节点用 LID ping 该 server(LID 见 ibstat 输出) sudo ibping <lid from ibstat>4.4 全Fabric 综合诊断:ibdiagnet
更彻底的 Fabric 级诊断(通常需要 SM 访问权限):
sudo ibdiagnet它检查拓扑、路由,并报告整个 Fabric 中的错误。一个典型的排障场景:NCCL 在大部分 rail 上正常,但反复在某一条 rail 上失败或变慢——先跑ibdiagnet,检查报告里连接该 rail 的交换机端口是否存在缺链、坏端口或路由不一致,处理后再重试 NCCL 任务。
4.5 NCCL 报错:ibv_create_qp / ibv_reg_mr 失败与 memlock 限制
InfiniBand 上一个常见问题是库无法注册足够的 pinned memory,典型报错为:
NCCL WARN Call to ibv_create_qp failed或:
NCCL WARN Call to ibv_reg_mr failed解决方案是去掉用户注册 pinned memory 的限额。在/etc/security/limits.conf(或发行版等价配置)中加入:
* soft memlock unlimited * hard memlock unlimited注意:修改limits.conf通常要求用户重新登录、重启,或者在 Slurm 集群上确保作业以新限制启动。用ulimit -l验证新的限制值是否生效。
这些报错并非凭空而来:在 src/misc/ibvwrap.cc 中,NCCL 对所有 verbs 调用做了统一封装——wrap_ibv_reg_mr(第 193 行)、wrap_ibv_create_qp(第 253 行)等函数通过IBV_PTR_CHECK_ERRNO宏检查返回值,失败时打印带函数名的 WARN 并向上返回ncclSystemError。也就是说,你在日志里看到的每一条Call to ibv_xxx failed都来自这一层包装,对应的失败点可以在 src/transport/net_ib/connect.cc 的连接建立路径(如wrap_ibv_create_qp调用点、QP 状态迁移调用点)中定位。
五、RoCE(RDMA over Converged Ethernet)网络专项排查
RoCE 组网与 InfiniBand 的诊断工具链不同,需要针对以太网信道做检查。
5.1 端口计数器:ethtool
ethtool -S <nic_name>检查错误、丢包、pause 帧、PFC 相关计数器。这些计数器的非零值可能指示硬件问题、布线问题或无损网络(lossless fabric)配置不当。
5.2 拥塞指标
RoCE 性能问题通常与拥塞控制或无损组网配置相关,而不是链路直接故障。除ethtool外,还应检查环境中交换机和 NIC 暴露的 PFC、ECN、CNP、队列丢包计数器。如果这些计数器在延迟长尾变长或吞吐不稳定期间持续增长,应先排查拥塞控制与无损组网配置,再考虑调整 NCCL 侧的参数。
5.3 连通性测试:rping
端口级检查无异常但仍怀疑连通性问题时,用rping测试。同样需要先在对端节点启动 server:
# 在远端节点启动 rping server rping -s -a <ip_address_of_the_server_nic> -V -C 10 # 在本节点用 IP ping 该 server rping -c -a <ip_address_of_the_server_nic> -S <ip_address_of_the_client_nic> -V -C 10参数含义:-s/-c分别为 server/client 模式,-a指定本地地址,-S指定对端地址,-V开启详细输出,-C 10表示执行 10 个连接循环。
5.4 NCCL 报错:ibv_modify_qp EINVAL 与 GID index
RoCE 上一个常见问题是 RoCE v2 NIC 选错了 GID index,典型报错:
NCCL WARN Call to ibv_modify_qp failed with error Invalid argument版本差异是排障关键:
- NCCL 2.21 及以后:GID index 由 NCCL 动态选择,用户不应再设置
NCCL_IB_GID_INDEX; - 更早版本:需要手动运行
show_gids查看 GID 表,然后把NCCL_IB_GID_INDEX设为 RoCE v2 GID 对应的索引。
此外,RoCE 组网可能还需要设置NCCL_IB_TC(InfiniBand 流量类字段),具体取值需参照网卡/交换机厂商文档。
源码印证:动态 GID 选择与报错提示机制
当前仓库中的实现与上述版本行为完全一致:
- 参数定义在 src/transport/net_ib/connect.cc:
NCCL_PARAM(IbGidIndex, "IB_GID_INDEX", -1),默认值-1即"交给 NCCL 动态选择"; - 动态选择逻辑在
ncclIbGetGidIndex(src/transport/net_ib/connect.cc#L298-L335):IB 链路层优先选取携带可路由 FLID 的 GID;RoCE 链路层下,若用户显式设置了NCCL_IB_GID_INDEX(≥0)则直接采用,否则按地址族(NCCL_IB_ADDR_FAMILY,默认AF_INET)、地址范围(NCCL_IB_ADDR_RANGE)和 RoCE 版本(NCCL_IB_ROCE_VERSION_NUM,默认 2)扫描 GID 表,通过/sys/class/infiniband/<dev>/ports/<port>/gid_attrs/types/<idx>读取每个 GID 的 RoCE 版本属性来挑选最匹配的条目。这些配套变量自 2.21 引入,可在 环境变量手册 中查看完整取值说明; - 报错提示在 src/misc/ibvwrap.cc:
wrap_ibv_modify_qp对ibv_modify_qp带重试(按NCCL_IB_MQP_RETRY_CNT次数递增睡眠重试),最终失败才打印Call to ibv_modify_qp failed with %d %s,并调用printIbModifyQpHint输出针对性提示——当 errno 为EINVAL时明确提示"很可能是NCCL_IB_GID_INDEX强制了错误的 GID index,可设置NCCL_IB_GID_INDEX=-1启用自动检测",errno 为ETIMEDOUT时则提示检查 NIC 是否跨 rail 连接(可用NCCL_CROSS_NIC=0验证)。
因此当你看到ibv_modify_qp failed with ... Invalid argument时,日志里通常会同时附带上述 HINT 行,直接按提示处理即可,不必再手动猜测。
六、结合 NCCL 日志验证排查结论
网络诊断工具给出的结论,最终要回到 NCCL 自身的日志中交叉验证。NCCL 提供分级日志(NCCL_DEBUG=VERSION/WARN/INFO/TRACE),可用NCCL_DEBUG_SUBSYS过滤子系统(网络相关日志属于NET/IB子系统)、NCCL_DEBUG_FILE按主机和 PID 分流落盘,详见 日志文档。排障时建议:
- 用
NCCL_DEBUG=INFO NCCL_DEBUG_SUBSYS=NET,ENV启动作业,确认 NCCL 实际选择了哪些网络接口和 IB HCA(对应前文NCCL_SOCKET_IFNAME、NCCL_IB_HCA的解析结果,接口选择日志即来自 src/misc/socket.cc 中的INFO(NCCL_ENV, ...)输出); - 与
ibstat/ethtool/rdma statistic的测量结果互相印证,区分"NCCL 配置问题"与"网络本身问题"。
小结
NCCL 网络排障可以归纳为一条从上层到下层、再到组网类型的检查链:
| 层次 | 关键手段 | 常见问题 |
|---|---|---|
| 接口选择 | NCCL_SOCKET_IFNAME显式指定 | 选中 UP 但不可达的接口导致 init 失败/挂起 |
| 端口管理 | ip_local_port_range+ 防火墙按范围放行 | bootstrap TCP 连接被防火墙拦截 |
| NIC 基线 | ibstatus/ibstat、ib_write_bw、ib_write_lat、rdma statistic、mlxlink | 降速、重传、尾延迟、PCIe/端口退化 |
| InfiniBand | sminfo、perfquery、ibping、ibdiagnet;memlock 限额 | 无 SM、符号错误、rail 级路由问题、ibv_reg_mr失败 |
| RoCE | ethtool -S、PFC/ECN/CNP 计数、rping;GID index 动态选择 | 拥塞/无损配置不当、ibv_modify_qpEINVAL |
核心原则:先用底层工具确认网络本身健康,再看 NCCL 报错与 HINT,最后才调整 NCCL 环境变量;对 NCCL 2.21 以后的版本,让 GID 选择交给自动检测(不要设置NCCL_IB_GID_INDEX),是 RoCE 排障的第一步。
- 高性能计算
- 通信
- 深度学习
- 分布式训练
【免费下载链接】nccl
Optimized primitives for collective multi-GPU communication
相关推荐
从零到一:Ubuntu 24.04上ROCm 6.5软件源配置的完整指南 🚀
从零到一:Ubuntu 24.04上ROCm 6.5软件源配置的完整指南 🚀 想要在Ubuntu 24.04上体验AMD ROCm 6.5的强大GPU计算能力
开发工具高性能计算文档ZooKeeper连接故障排查手记:从网络到配置的深度诊断
ZooKeeper连接故障排查手记:从网络到配置的深度诊断 副标题:7个典型场景+抓包分析 在分布式系统的世界里,ZooKeeper作为分布式协调服务的核心,其
后端前端可观测性消息队列TobudOS MicroPython 组件实战:ESP8266 从固件烧录、串口 REPL 到网络接入与故障排查
TobudOS MicroPython 组件实战:ESP8266 从固件烧录、串口 REPL 到网络接入与故障排查 本文围绕 MicroPython 官方 ES
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考