动手:用 perftest 打通第一条 RDMA 链路
ib_send_bw 跑不出线速时,问题几乎总在 GID、设备名或 MTU 上。
学完这节你能做到
- 用 show_gids 选对 GID index 并解释为什么要选
- 跑 ib_send_bw / ib_write_lat 并判读结果是否合格
- 按结果区分是链路问题、配置问题还是拓扑问题
建议先学
跳过这几节会看不懂本节的部分推导
这一节的目标:拿到基线
原理讲完了,现在要回答一个很实际的问题:这条链路到底能跑多快?
perftest 是 RDMA 的标准测试套件。它的价值不在"跑个分",而在给出一个可对照的基线——
后面 NCCL 出问题时,能立刻判断是网络的问题还是上层的问题。
顺序永远是:先点对点,再集群。点对点不达标就没必要往上测。
环境检查(三条,缺一不可)
# ① 设备识别到了吗
ibv_devinfo | grep -E 'hca_id|state|phys_state|link_layer'
# ② 设备名与网卡名的对应关系
ibdev2netdev -v
# ③ 锁内存额度(RDMA 要注册并锁住内存)
ulimit -l # 期望 unlimited
hca_id: mlx5_0
state: PORT_ACTIVE (4)
phys_state: LINK_UP (5)
link_layer: Ethernet ← RoCE;显示 InfiniBand 则是 IB
link_layer 决定了后面要不要选 GID:
| link_layer | 场景 | 要不要 -x |
|---|---|---|
InfiniBand | 纯 IB | 通常不用 |
Ethernet | RoCE | 要,必须选对 RoCEv2 的 GID index |
ib_send_bw 会在初始化阶段报 Couldn't allocate MR 或 Failed to register memory region,
而机器上明明有几百 GB 空闲内存。原因是锁内存额度不够,不是内存不够。
# 临时
ulimit -l unlimited
# 持久化
cat >> /etc/security/limits.conf <<'EOF'
* soft memlock unlimited
* hard memlock unlimited
EOF容器里还要额外加 IPC_LOCK(为什么需要 RDMA 那节讲过)。
这个坑查一次记一辈子。
RoCE 场景:先选对 GID
一张网卡有多个 GID 条目,对应 RoCEv1/RoCEv2、IPv4/IPv6。选错会出现"连得上但性能不对" 或者直接连不上。
show_gids | grep v2
DEV PORT INDEX GID IPv4 VER DEV
mlx5_0 1 3 0000:0000:0000:0000:0000:ffff:0a68:1467 10.104.20.101 v2 ens1f0np0
mlx5_1 1 3 0000:0000:0000:0000:0000:ffff:0a68:1468 10.104.20.102 v2 ens1f1np0
记住 INDEX(这里是 3),后面所有命令的 -x 参数用它。
# 只看某个设备
show_gids mlx5_0 | grep v2
# 没有 show_gids 时的等价查法
ls /sys/class/infiniband/mlx5_0/ports/1/gids/
测试一:带宽 ib_send_bw
服务端(先起):
ib_send_bw -x 3 -d mlx5_0 -F --report_gbits
客户端:
ib_send_bw -x 3 -d mlx5_0 -F --report_gbits 10.104.20.101
---------------------------------------------------------------------------------------
#bytes #iterations BW peak[Gb/sec] BW average[Gb/sec] MsgRate[Mpps]
65536 1000 394.21 392.87 0.749412
---------------------------------------------------------------------------------------
常用参数:
| 参数 | 作用 |
|---|---|
-x <idx> | GID index(RoCE 必需) |
-d <dev> | 设备名,mlx5_0 这种 |
-F | 忽略 CPU 频率变化的警告 |
--report_gbits | 用 Gb/s 报告,方便和网卡标称值对比 |
-s <bytes> | 消息大小,默认 65536 |
-q <n> | QP 数量,多 QP 更容易打满 |
-D <sec> | 按时间跑而不是按次数 |
-a | 扫描所有消息大小(看曲线) |
合格线怎么定
理论线速 = 端口速率(如 400 Gbps)
合格线 = 理论线速 × 90% = 360 Gbps
上面那个结果 392.87 / 400 ≈ 98%,健康。
如果 ib_send_bw 稳定卡在某个奇怪的数值上不动,先算一下 PCIe 够不够:
| 网卡 | 需要 | Gen4 x16(31.5 GB/s)够吗 |
|---|---|---|
| 200 Gb | 25 GB/s | 刚好 |
| 400 Gb | 50 GB/s | 不够 |
lspci -vv -s <bdf> | grep -E 'LnkCap|LnkSta'400G 网卡插在 Gen4 x16 上,ib_send_bw 的上限就是约 250 Gb,
而 ibstat 照样显示 Rate: 400。详见
PCIe:机内的那张网。
测试二:延迟 ib_write_lat
带宽好看不代表延迟好。延迟是 RDMA 的核心卖点,必须单独测。
# 服务端
ib_write_lat -x 3 -d mlx5_0 -F
# 客户端
ib_write_lat -x 3 -d mlx5_0 -F 10.104.20.101
#bytes #iterations t_min[usec] t_avg[usec] t_max[usec] 99% percentile[usec]
2 1000 1.42 1.51 8.93 1.78
看 P99 而不是平均值。 判断口径:
| 场景 | t_avg | P99 |
|---|---|---|
| 同交换机(一跳) | 1–2 μs | 低于 3 μs |
| 跨 spine(三跳) | 2–4 μs | 低于 6 μs |
| 出现十几微秒的 max | 正常(偶发调度抖动) | 但 P99 若也这么高就要查 |
对照一下 L0:内核 TCP 同机房是 20–50 μs。 这一个数量级的差距就是 RDMA 存在的理由。
测试三:单边操作 ib_write_bw / ib_read_bw
ib_write_bw -x 3 -d mlx5_0 -F --report_gbits <server> # WRITE
ib_read_bw -x 3 -d mlx5_0 -F --report_gbits <server> # READ
三者的差异值得知道:
| 工具 | 操作 | 特点 |
|---|---|---|
ib_send_bw | SEND(双边) | 对端要挂 RECV,最接近通用场景 |
ib_write_bw | WRITE(单边) | 对端 CPU 不参与,通常带宽最高 |
ib_read_bw | READ(单边) | 要等对端返回数据,延迟敏感、带宽通常略低 |
结果不达标:按顺序排除
带宽偏低 / 延迟偏高
│
├─ 1. 端口速率对吗 ibstat | grep Rate
├─ 2. PCIe 够吗 lspci -vv | grep LnkSta
├─ 3. GID 选对了吗(RoCE) show_gids | grep v2
├─ 4. MTU 两端一致吗 ibstat | grep -i mtu
├─ 5. 无损配置生效了吗(RoCE) mlnx_qos -i <dev>;ethtool -S | grep pause
├─ 6. 跨 NUMA 了吗 nvidia-smi topo -m / lspci NUMA node
└─ 7. 试多 QP ib_send_bw -q 8
一张对照表:
| 现象 | 最可能的原因 |
|---|---|
| 稳定在理论值的 60% 左右 | PCIe 代际或 lane 数不够 |
| 稳定在 一半 | 端口协商降速(400 跑成 200) |
| 带宽正常但延迟高、抖动大 | 跨 NUMA,或路径上有拥塞 |
| 空载正常、加压就崩 | RoCE 无损配置没生效(PFC/ECN 映射) |
| 单 QP 低、多 QP 正常 | 正常现象,单 QP 打不满高速网卡 |
| 完全连不上 | GID 选错,或 MTU 不一致 |
点对点测试是无拥塞的两点通信,它验证的是"这条链路的物理与配置正确"。
它测不出来的问题:
- rail 布线接错(拓扑那节)
- 多对多同时通信时的拥塞与无损配置缺陷
- NCCL 参数配错(少用了几张卡)
所以顺序必须是:点对点达标 → 再测集群 busbw。 反过来(直接测 NCCL 发现慢)会让你在一堆可能性里乱猜。
把它变成例行检查
交付一批机器时,手工两两测不现实。写成脚本按 rail 遍历:
#!/bin/bash
# 对每张卡都和参考节点对打一次,输出不达标的
REF=10.104.20.101; MIN=360 # 400G 的 90%
for d in $(ibstat -l); do
bw=$(ib_send_bw -x 3 -d "$d" -F --report_gbits "$REF" 2>/dev/null \
| awk '/^ [0-9]/ {print $4}')
ok=$(awk -v b="${bw:-0}" -v m="$MIN" 'BEGIN{print (b>=m)?"OK":"FAIL"}')
printf '%-10s %8s Gb/s %s\n' "$d" "${bw:-n/a}" "$ok"
done
mlx5_0 392.87 Gb/s OK
mlx5_1 391.44 Gb/s OK
mlx5_4 248.10 Gb/s FAIL ← 这张卡要查(PCIe 或速率)
把它放进上机验收流程,比事后调 NCCL 参数有效得多。
检查点
RoCE 环境下 ib_send_bw 直接连不上或性能异常,最先该检查什么?
400G 网卡的 ib_send_bw 稳定在 240 Gb/s 左右,而 ibstat 显示 Rate: 400。最可能的原因?
点对点 ib_send_bw 已达线速 98%,为什么还必须再测集群 busbw?
这节课的落点
- 顺序永远是先点对点、再集群;点对点不达标就别往上测
- 三条环境检查:
ibv_devinfo(设备与 link_layer)、ibdev2netdev(名字对应)、ulimit -l ulimit -l不是 unlimited 会在初始化就报内存注册失败,容器里还要IPC_LOCK- RoCE 必须先
show_gids | grep v2拿 index,再用-x传进去 ib_send_bw --report_gbits测带宽,合格线是理论线速的 90%ib_write_lat测延迟,看 P99;同机房 RDMA 是个位数微秒,内核 TCP 是 20–50 μs- 不达标按七步排除;三个指纹:约 60% = PCIe 不够、一半 = 速率降级、 空载好加压崩 = 无损配置没生效
- 把逐卡带宽检查写成脚本放进上机验收,比事后调参有效
延伸资料
- k8s-in-action
network/network-operator/README.md