RoCE 网络实战:从 NCCL 调优到 RDMA 硬件计数器排障

适用场景:GPU 训练集群、RoCEv2 组网、NCCL AllReduce 跑不满、交换机侧 PFC/ECN 联调

排障链路:NCCL 参数 → 网卡 hw_counters → ib_write_bw 打流 → 华三交换机 QoS

核心认知:RoCE 问题从来不是单一层面能定位的,主机侧打标不对、交换机 PFC 不开、GID index 选错,任何一个都能让带宽腰斩


一、背景:为什么 RoCE 排障最容易被低估

AI 集群交付里,最容易被误判成"NCCL 不行"或"网卡坏了"的,其实是 RoCE 链路没调对。表现通常是:

  • 训练启动卡在 bootstrap,或 AllReduce 带宽只有理论值 30%~50%
  • ib_write_bw 单向通、反向不通
  • GPU 利用率周期性掉,伴随网卡 np_cnp_sent 疯涨
  • 交换机端口 PFC 帧暴增,但服务器侧看起来一切正常

RoCEv2 跑在 UDP/IP 上,依赖无损网络 + 正确打标 + GID 选对三者同时成立。任何一层错位,现象都长一个样------慢。


二、主机侧:NCCL 参数怎么配

下面是一版在 Mellanox/NVIDIA 网卡 + RoCEv2 环境下跑通过的启动脚本框架。注意:HCA 名、GID index、网卡名必须按你机器现场核对,不能直接抄。

bash 复制代码
# 走 RDMA,不要禁掉
export NCCL_IB_DISABLE=0

# GPUDirect RDMA 距离门限(2=跨 PCIe switch 可用,具体按拓扑测)
export NCCL_NET_GDR_LEVEL=2

# RoCEv2 走 GID index 3(常见,但必须用 show_gids 确认)
export NCCL_IB_GID_INDEX=3

# Traffic Class:NCCL_IB_TC 不是裸 DSCP 值,
#它是把 DSCP 放高 6 位、ECN 放低 2 位打包出来的 traffic_class 字节
export NCCL_IB_TC=106

# 建连阶段走 TCP bootstrap 的网卡
export NCCL_SOCKET_IFNAME=bond0,bond1,eth0

#明确绑定用哪些 HCA,避免 NCCL 选到管理网网卡
export NCCL_IB_HCA=mlx5_bond_1,mlx5_bond_2,mlx5_bond_3,mlx5_bond_4

#超时与重试(大集群、长链路建议调大)
export NCCL_IB_TIMEOUT=22
export NCCL_TIMEOUT=180

自适应脚本思路(生产推荐)

别写死 HCA 列表。训练脚本里先探测:

bash 复制代码
for hca in mlx5_bond_1 mlx5_bond_2 mlx5_bond_3 mlx5_bond_4; do
  if [ -d "/sys/class/infiniband/$hca" ]; then
    HCA_LIST="HCA_LIST,hca"
  fi
done
export NCCL_IB_HCA=${HCA_LIST#,}

再判断是否存在 /sys/class/infiniband/mlx5_bond_4 或 /sys/class/net/bond0,区分"特殊节点"和"标准 worker",给不同的 HCA 顺序。

GID index 必须现场查

看每个 GID 槽位对应什么类型

bash 复制代码
for f in /sys/class/infiniband/mlx5_0/ports/1/gids/*; do
  idx=${f##*/}
  echo "idx=$idx  gid=$(cat $f)  type=$(cat /sys/class/infiniband/mlx5_0/ports/1/gid_attrs/types/$idx 2>/dev/null)"
done

挑 type 是 RoCE v2 且 GID 末尾是你网卡 IPv4 地址 的那一行,把 idx 填到 NCCL_IB_GID_INDEX。别默认就是 3,不同驱动/固件/网卡半卡可能不一样。


三、RDMA 硬件计数器:RoCE 排障的硬功夫

NCCL 报错是结果,网卡计数器才是原因。路径在:

bash 复制代码
/sys/class/infiniband/mlx5_XX(填实际的)/ports/1/hw_counters/(这里下下面列表里的计数器的名字)

重点盯这几个

计数器 含义 异常说明
out_of_sequence 报文乱序到达 LAG 哈希不均、多路径、自适应路由没开导致乱序
local_ack_timeout_err 本端 ACK 超时 对端没回、链路丢包、buffer 被打满
np_cnp_sent 本端发了拥塞通知包 非零正常,说明 DCQCN 在干活;持续暴涨=真拥塞
rp_cnp_handled 本端收到并处理了 CNP 说明对端在通知你降速,DCQCN 闭环正常
rnr_nak_retry_err 接收端没准备好被重试 对端 CQ/QP 资源不够,或接收端 CPU 没跟上
np_ecn_marked_roce_packets 本端发出的 RoCE 包被打 ECN 交换机在标记拥塞,非零正常,但斜率太陡要查阈值
packet_seq_err 序列号错误 疑似丢包或重传异常

排障套路

测前清基线(记录当前值)

bash 复制代码
for c in out_of_sequence local_ack_timeout_err np_cnp_sent rp_cnp_handled np_ecn_marked_roce_packets rnr_nak_retry_err; do
  echo "c = (cat /sys/class/infiniband/mlx5_0/ports/1/hw_counters/$c)"
done

跑一轮 AllReduce 或 ib_write_bw

再读一次,看 delta

判断逻辑:

  • out_of_sequence 涨得快 → bond 哈希策略不对(没开 layer3+4),或需要开自适应路由
  • np_cnp_sent 和 rp_cnp_handled 都很高 → 网络在拥塞,去查交换机 ECN 阈值是不是太激进了
  • local_ack_timeout_err 涨 → 对端可能 PFC 被暂停太久,或光模块/线缆有问题
  • rnr_nak_retry_err 涨 → 接收端 buffer 小,调大 NCCL_BUFFSIZE 或接收端队列深度

四、ib_write_bw 打流:先证明物理链路是好的

NCCL 跑不满,先别怪 NCCL。用 perftest 里的 ib_write_bw 单独压网卡。

服务端(接收端)

bash 复制代码
ib_write_bw -d mlx5_0 -x 3 -F -R -T 136 --port 11001 -s 65536 --report_gbits -q 200 --run_infinitely

客户端(发送端)

bash 复制代码
ib_write_bw -d mlx5_0 -x 3 -F -R -T 136 --port 11001 -s 65536 --report_gbits -q 200 <服务端IP>

参数速查

参数 作用
-d mlx5_0 指定 RDMA 设备
-x 3 GID index,RoCE 必须指定,值来自 show_gids
-F 忽略 CPU 频率告警
-R 用 rdma_cm 建连
-T 136 ToS 字节(对应 DSCP 打标)
--tclass=236 等价写法,打 Traffic Class
-s 65536 单消息 64 KB,压带宽常用
-q 200 QP 数量,单 QP 打不满 200G/400G 网卡
--report_gbits 以 Gbit/s 输出
-D 10 跑 10 秒
--run_infinitely 常驻,配合监控脚本读计数器

验收基线(经验值)

  • 200G 网卡:单端口应跑到 180+ Gbps
  • 400G 网卡:单端口应跑到 370+ Gbps
  • 单向通、反向报 Failed status 4 → 八成是对端 PCIe/NIC 拓扑或 GID 不对,不是交换机问题。

⚠️ 打流时一定双向都测 。A→B 通 B→A 不通,优先查 B 这块网卡的 ibstat 状态、NUMA 亲和、PCIe 带宽。


五、bond 与网卡侧基础调优

5.1 bond 配置(RoCE 推荐 mode=4 + layer3+4)

bash 复制代码
BONDING_OPTS="miimon=100 mode=4 xmit_hash_policy=layer3+4"

为什么必须 layer3+4:RDMA 点对点通信时 IP 和 MAC 不变,只用 L2/L3 哈希,所有流会砸到同一条成员口上。源端口有随机性,layer3+4 才能把多 QP 流量摊开。

5.2 RX ring 调整

当前值小于预设再调,别无脑调。

bash 复制代码
RX_MAX=4096
for DEVICE in ens4f0 ens4f1 ens5f0 ens5f1 ens7f0 ens7f1; do
  cur=(ethtool -g DEVICE | awk '/RX:/&&2!="RX:"{print 2; exit}')
  if [ "{cur:-0}" -lt "RX_MAX" ]; then
    ethtool -G DEVICE rx RX_MAX
  fi
done

5.3 MTU 统一

RoCE 链路 MTU 必须端到端一致(网卡、ToR、Spine 全统一),否则分片开销直接吃掉带宽:

bash 复制代码
ip link set bond0 mtu 1500      # 保守值
或 jumbo:ip link set bond0 mtu 9216  (整链都得改)

5.4 路由与抓包辅助

添加静态路由到训练网

bash 复制代码
route add -net 10.223.128.0/20 gw 10.223.159.254 dev bond1

抓 ARP / RoCE 报文

bash 复制代码
tcpdump -i ens5f0 -w 2.pcap -c 100 arp
tcpdump -i bond0 -nn udp port 4791 -c 100

六、华三交换机侧:只给框架,不写死阈值

服务器打标再漂亮,交换机不配合一样白搭。华三 Comware 上的核心动作就三条:

6.1 信任模式要对

bash 复制代码
interface HundredGigE1/0/1
 qos trust dscp
 priority-flow-control enable

6.2 只在 RoCE 数据优先级开 no-drop

假设 RoCE 走 priority 3,就只开 3。

bash 复制代码
priority-flow-control no-drop dot1p 3

别把 0~7 全开。PFC 是"按优先级暂停整类流量",开多了容易 PFC 风暴、死锁,还会把管理/IRF/存储流量一起暂停。

6.3 ECN 阈值要现场调

思路:min-threshold 别太低,max-threshold 给足,probability 按机型文档来。

bash 复制代码
qos ecn profile roce-profile
 ecn mode wred
 ecn queue 3 min-threshold 200 max-threshold 800
 ecn queue 3 probability 100

经验起点(不是万能值):每端口 buffer 32 MB 时,ECN min 设 3~4 MB,max 设 12~16 MB,PFC 触发放 24 MB 以上,再拿真实训练流量微调。

6.4 端到端一致性检查清单

  • 服务器 DSCP 值 ↔ 交换机 dscp-to-8021p 映射 ↔ PFC 优先级 三处一致
  • CNP 所在优先级不能开 no-drop,否则 CNP 自己被暂停,DCQCN 闭环断掉
  • MTU、ToS、GID 类型(RoCEv2)全链路对齐

七、踩坑清单

现象 先查什么
NCCL 启动卡很久 NCCL_SOCKET_IFNAME 绑错网卡,bootstrap 走管理网
AllReduce 只有 30% 带宽 GID index 不对 / 没走 RoCEv2 / 没开 GDR
单向通反向不通 对端 GID、NUMA、PCIe 拓扑;ibstat 看 State 是否 Active
out_of_sequence 暴涨 bond 没开 layer3+4,或需要开自适应路由
np_cnp_sent 持续高 交换机 ECN 阈值太激进,DCQCN 一直在降速
交换机 PFC 帧暴增 RoCE 优先级没隔离,或 buffer 水线太低
local_ack_timeout_err 涨 对端被 PFC 暂停太久 / 光模块或线缆问题
改完重启失效 mlnx_qos / PFC / 路由没写持久化,进 systemd service 或 rc.local
多节点表现不一致 固件版本不一致,或网卡命名乱序导致 HCA 绑错

八、小结

RoCE 排障的四层闭环:

  1. NCCL 层 :HCA 绑对、NCCL_IB_GID_INDEX 用 show_gids 确认、NCCL_IB_TC 打标和交换机队列对齐
  2. 网卡计数器层 :out_of_sequence / np_cnp_sent / rp_cnp_handled / np_ecn_marked_roce_packets 看 delta,比看 NCCL 日志更早发现问题
  3. 打流层 :ib_write_bw -x 3 -q 200 双向都跑,先证明物理链路到线速
  4. 交换机层:只给 RoCE 优先级开 PFC no-drop,ECN 阈值现场调,端到端 DSCP 映射一致

一句话:RoCE 不是"配完就能跑",是"配完要能解释每一个计数器为什么这样跳"才算交差。

有问题的在评论区贴 ibstat + show_gids + hw_counters delta,我看到会回。

相关推荐
水饺编程1 小时前
第2章:Linux 基础,pwd 命令
linux·c语言·汇编
砚凝霜1 小时前
【软考信息安全】第二十一章 网络设备安全增强技术与漏洞防护
网络·安全·web安全
鱼很腾apoc1 小时前
【MySQL】 第1期 从核心概念到表约束全解析
linux·c语言·数据库·学习·mysql
程序员-Benothing1 小时前
Linux进程优先级与调度:nice、renice、CPU亲和性实战
linux·运维·服务器
程序员-Benothing1 小时前
Linux进程前后台管理:jobs、fg、bg、nohup、disown
linux·运维·服务器
JavaEdge.1 小时前
Docker Compose部署Dify
运维·docker·容器
Alinket2 小时前
毫米波雷达 vs 摄像头 vs 手环:养老跌倒监测三类方案怎么选
网络·数据库·健康医疗·信息与通信·iot
腾讯云大数据2 小时前
本体立骨架,语义供刻度——DataBuddy对企业AI语义架构的一次完整回答
大数据·人工智能·架构·云计算·腾讯云
企业解惑小助手2 小时前
大型企业终端如何统一管理排障实录:批量终端策略不生效问题排查
运维·服务器·网络·域智盾软件