11 KiB
多机多卡 NCCL 测试概念说明
本文先讲概念,不涉及脚本改造。目标是理解两台 8 卡 H100 服务器做多机多卡通信测试时,应该从哪些层次逐步验证,以及每一层到底在证明什么。
当前示例机器:
| 别名 | 主机名 | 内网 IP | GPU |
|---|---|---|---|
| nccl-gpu-1 | aikubeworker0012 | 172.72.8.12 | 8 x H100 |
| nccl-gpu-2 | aikubeworker0016 | 172.72.8.16 | 8 x H100 |
两台机器合起来就是 16 张 GPU。多机 NCCL 测试的核心问题是:这 16 张 GPU 是否能通过正确的 GPU、NVLink、PCIe、IB/RDMA 网络路径,高效且正确地完成集体通信。
1. 总体思路
多机多卡通信测试是一个自底向上的过程。越底层越接近硬件和链路,越上层越接近真实训练业务。
flowchart TD
L0["0. 物理与基础连通<br/>电源 / GPU / 网卡 / 线缆 / 交换机 / SSH"] --> L1["1. 系统识别层<br/>nvidia-smi / lspci / ibstat / ibdev2netdev"]
L1 --> L2["2. 单机 GPU 健康层<br/>温度 / 功耗 / ECC / PCIe / Throttling / NVLink Topo"]
L2 --> L3["3. 单机 GPU 性能层<br/>HBM 带宽 / H2D-D2H / FP32-TF32-FP16-BF16-FP8 算力"]
L3 --> L4["4. 单机多卡通信层<br/>单节点 8 卡 NCCL over NVLink/NVSwitch"]
L4 --> L5["5. 跨机网络与 RDMA 层<br/>IP 连通 / IB Active / RDMA 带宽 / RDMA 延迟"]
L5 --> L6["6. 跨机 NCCL 层<br/>两机 16 卡 AllReduce / AllGather / ReduceScatter / Broadcast / AllToAll"]
L6 --> L7["7. 训练负载层<br/>torchrun / Megatron / DeepSpeed / 业务训练压测"]
最重要的原则:
上层失败,不一定是上层问题。
比如两机 all_reduce_perf 失败,原因可能在 NCCL,也可能在 SSH、MPI、IB、GID、网卡选择、驱动版本、CUDA 版本、NCCL 版本或 GPU Direct RDMA。
所以排查顺序应该是:
基础连通 -> 单机健康 -> 单机性能 -> 单机 NCCL -> 跨机 RDMA -> 跨机 NCCL -> 训练业务
2. 两机 16 卡通信路径
单机内部主要走 NVLink/NVSwitch;跨机器时,数据必须经过 GPU、PCIe/NVLink、网卡、交换机和对端网卡。
flowchart LR
subgraph A["aikubeworker0012 / 172.72.8.12"]
A0["GPU0"] --- ASW["NVSwitch / NVLink"]
A1["GPU1"] --- ASW
A2["..."] --- ASW
A7["GPU7"] --- ASW
ASW --> ANIC["IB/RDMA NIC(s)"]
end
subgraph NET["InfiniBand / RoCE Fabric"]
SW["IB Switch"]
end
subgraph B["aikubeworker0016 / 172.72.8.16"]
BNIC["IB/RDMA NIC(s)"] --> BSW["NVSwitch / NVLink"]
B0["GPU0"] --- BSW
B1["GPU1"] --- BSW
B2["..."] --- BSW
B7["GPU7"] --- BSW
end
ANIC <--> SW
SW <--> BNIC
这里有两个不同的通信域:
| 通信域 | 典型路径 | 主要测试 |
|---|---|---|
| 单机内 8 卡 | GPU -> NVLink/NVSwitch -> GPU | 单机 NCCL、NVLink topo、D2D |
| 跨机器 16 卡 | GPU -> NIC -> IB/RDMA 网络 -> NIC -> GPU | RDMA、跨机 NCCL |
这两个域的性能阈值不能混用。单机 NVSwitch 很快,跨机 RDMA 一般慢一些,跨机 NCCL 的瓶颈通常在 IB/RDMA 网络。
3. 每一层要测什么
3.1 基础连通层
这一层只证明机器能访问、身份和地址正确。
要确认:
| 检查项 | 目的 |
|---|---|
| SSH 互通 | MPI/NCCL 多机启动依赖远端拉起进程 |
| hostname 正确 | 避免登录错机器 |
| IP 正确 | 确认使用的是训练网络或 IB/RDMA 对应网络 |
| 时间同步 | 长时间训练日志和超时排查更可靠 |
这一层不证明 GPU 或 RDMA 性能,只证明“机器能互相找到”。
3.2 系统识别层
这一层证明系统能看见 GPU 和网卡。
常见信息:
| 工具 | 看什么 |
|---|---|
nvidia-smi |
GPU 数量、型号、驱动、CUDA、温度、功耗 |
nvidia-smi topo -m |
GPU、NIC、CPU NUMA、NVLink/NVSwitch 拓扑 |
ibstat |
IB 设备、端口状态、链路速率 |
ibdev2netdev |
mlx5 设备和网络接口的映射 |
/sys/class/infiniband |
端口状态、link layer、rate、GID |
这一层很关键,因为 NCCL 经常因为选错网卡而跑到 TCP 或错误的接口上。
3.3 单机 GPU 健康层
这一层证明每台机器自己是健康的。
flowchart LR
H["单机健康检查"] --> T["温度"]
H --> P["功耗"]
H --> E["ECC 错误"]
H --> PCIE["PCIe Gen/Width"]
H --> C["SM/Mem Clock"]
H --> TH["Throttling"]
H --> PM["Persistence Mode"]
如果某张卡温度过高、ECC double-bit、PCIe 降级或 throttling,后面的 NCCL 测试即使能跑,结果也不可信。
3.4 单机 GPU 性能层
这一层证明每台机器的 GPU 本身性能正常。
| 测试 | 证明什么 |
|---|---|
| HBM/D2D 带宽 | GPU 显存和设备间拷贝能力 |
| H2D/D2H 带宽 | CPU/Host 到 GPU 的 PCIe 路径 |
| FP32/TF32 | 基础矩阵计算能力 |
| FP16/BF16/FP8 | 训练常用 Tensor Core 能力 |
这一步是单机验收。它不能证明两台机器之间通信正常,但可以排除“某台机器本身 GPU 算力或带宽异常”。
3.5 单机多卡 NCCL 层
这一层验证单台机器 8 卡之间的集体通信。
flowchart TD
S["单机 8 卡 NCCL"] --> AR["AllReduce"]
S --> AG["AllGather"]
S --> RS["ReduceScatter"]
S --> BC["Broadcast"]
S --> AT["AllToAll"]
单机 NCCL 主要看 NVLink/NVSwitch 通信路径是否正常。常见指标:
| 指标 | 含义 |
|---|---|
algbw |
算法视角的有效带宽 |
busbw |
总线视角的带宽,更适合比较通信链路利用率 |
#wrong |
结果错误数量,必须是 0 |
单机测试通过后,只能说明单台服务器内部 8 卡通信正常。
3.6 跨机 RDMA 层
这一层验证两台机器之间的网络和 RDMA 能力,不涉及 NCCL。
sequenceDiagram
participant N1 as aikubeworker0012
participant FAB as IB/RDMA Fabric
participant N2 as aikubeworker0016
N1->>N2: ping / ssh
N1->>FAB: ib_write_bw client
FAB->>N2: ib_write_bw server
N1->>FAB: ib_read_bw client
FAB->>N2: ib_read_bw server
N1->>N2: ib_write_lat / ib_read_lat
这一层要回答:
| 问题 | 说明 |
|---|---|
| IB 端口是否 Active | 没 Active 就不用跑 NCCL |
| RDMA 带宽是否达标 | 证明网络数据面能跑起来 |
| RDMA 延迟是否正常 | 高延迟会影响小消息和训练同步 |
| 是否是 InfiniBand/RoCE | 两者环境变量和排障点不同 |
如果 RDMA 层失败,跨机 NCCL 大概率也会失败或退化到 TCP。
3.7 跨机 NCCL 层
这一层才是真正的多机多卡 NCCL 测试。
两台 8 卡机器通常是:
2 nodes x 8 GPUs = 16 ranks
每个 rank 绑定 1 张 GPU
概念上是:
flowchart LR
subgraph N1["Node 1: 172.72.8.12"]
R0["rank 0 / GPU0"]
R1["rank 1 / GPU1"]
R2["..."]
R7["rank 7 / GPU7"]
end
subgraph N2["Node 2: 172.72.8.16"]
R8["rank 8 / GPU0"]
R9["rank 9 / GPU1"]
R10["..."]
R15["rank 15 / GPU7"]
end
R0 <--> R8
R1 <--> R9
R7 <--> R15
N1 <--> N2
典型测试项:
| NCCL 测试 | 训练里对应什么 |
|---|---|
| AllReduce | 数据并行梯度同步 |
| ReduceScatter | ZeRO/FSDP 梯度切分 |
| AllGather | ZeRO/FSDP 参数聚合 |
| Broadcast | 参数广播、初始化 |
| AllToAll | MoE、专家并行、部分并行策略 |
| SendRecv | 点对点通信、pipeline parallel |
跨机 NCCL 要看:
| 指标 | 判定 |
|---|---|
| 是否成功启动 16 rank | MPI/SSH/路径/环境是否正常 |
#wrong == 0 |
正确性必须过 |
busbw |
跨节点通信链路利用率 |
| 是否走 IB/RDMA | 需要从 NCCL_DEBUG=INFO 确认 |
| 是否退化 TCP | 如果退化,性能会明显偏低 |
4. NCCL 为什么要分单机和跨机
单机 8 卡通信和跨机 16 卡通信的瓶颈不同。
flowchart TD
A["NCCL 性能结果"] --> B{"测试范围"}
B --> C["单机 8 卡"]
B --> D["跨机 16 卡"]
C --> C1["主要瓶颈:NVLink / NVSwitch"]
C --> C2["阈值可参考 GPU NVLink 能力"]
D --> D1["主要瓶颈:IB/RDMA 网络"]
D --> D2["阈值应参考网卡数量、速率、拓扑和 rail 数"]
所以不能用单机 NVLink 的阈值直接判断跨机 NCCL。跨机要根据真实网络能力设阈值,例如:
| 网络配置 | 理论上限理解 |
|---|---|
| 单张 400G 网卡 | 约 50 GB/s 单向原始带宽 |
| 8 张 400G 网卡 | 约 400 GB/s 原始聚合带宽 |
| 实测 NCCL busbw | 会受拓扑、GDR、rail、NUMA、交换机、NCCL 算法影响 |
实际验收时,应该先知道每台机器有几张 IB/RDMA 网卡、每张速率多少、GPU 到 NIC 的拓扑关系,再定跨机 NCCL 阈值。
5. 常见失败位置
flowchart TD
F["跨机 NCCL 失败"] --> A["启动失败"]
F --> B["能启动但很慢"]
F --> C["运行中 timeout"]
F --> D["结果 #wrong 非 0"]
A --> A1["SSH 不通"]
A --> A2["远端路径不存在"]
A --> A3["MPI 环境不一致"]
A --> A4["root 运行未允许"]
B --> B1["NCCL_SOCKET_IFNAME 选错"]
B --> B2["没走 IB/RDMA,退化 TCP"]
B --> B3["NCCL_IB_HCA 没选对"]
B --> B4["GPU Direct RDMA 没生效"]
C --> C1["IB 端口不稳定"]
C --> C2["交换机/PFC/ECN 问题"]
C --> C3["NCCL timeout 配置"]
C --> C4["驱动/CUDA/NCCL 版本不兼容"]
D --> D1["通信正确性失败"]
D --> D2["必须 FAIL,不能只看带宽"]
6. 推荐验收顺序
下面是面向两台 8 卡机器的推荐顺序:
flowchart TD
A["Step 1: 两台机器基础信息"] --> B["Step 2: 两台机器单机 GPU 健康"]
B --> C["Step 3: 两台机器单机 benchmark"]
C --> D["Step 4: 两台机器分别跑单机 8 卡 NCCL"]
D --> E["Step 5: 两台机器互测 RDMA bandwidth/latency"]
E --> F["Step 6: 两机 16 卡 NCCL correctness"]
F --> G["Step 7: 两机 16 卡 NCCL performance"]
G --> H["Step 8: 两机训练 demo 或业务压测"]
每一步的意义:
| 步骤 | 目的 |
|---|---|
| Step 1 | 确认没有登录错机器,基础网络和环境存在 |
| Step 2 | 排除 GPU 健康问题 |
| Step 3 | 排除 GPU 单卡/单机性能问题 |
| Step 4 | 排除单机 NVLink/NVSwitch/NCCL 问题 |
| Step 5 | 排除跨机 RDMA 问题 |
| Step 6 | 先证明 NCCL 正确性 |
| Step 7 | 再证明 NCCL 性能 |
| Step 8 | 最后用真实训练形态验证稳定性 |
7. 对当前脚本的映射
当前脚本已有模块和上面层次的关系:
| 当前模块 | 覆盖层次 | 备注 |
|---|---|---|
gpu_info |
系统识别层 | 单机 |
health |
单机 GPU 健康层 | 单机 |
benchmark |
单机 GPU 性能层 | 单机 |
nccl |
单机多卡通信层 | 当前主要是单机 |
rdma |
RDMA 检查 | 当前偏本机检查,不是两机互测 |
stress |
稳定性 | 单机 |
training |
训练负载层 | 当前偏单机 |
建议新增 multi_node_nccl |
跨机 NCCL 层 | 专门处理 hostfile、mpirun、多节点环境、结果解析 |
如果未来要扩展脚本,比较自然的方向是新增一个多机模块,而不是把所有逻辑塞进现有 nccl 模块。
8. 最小概念模型
记住这句话即可:
单机 NCCL 验证 GPU 之间的 NVLink/NVSwitch。
跨机 RDMA 验证机器之间的网络。
跨机 NCCL 验证 NCCL 是否能把 GPU 和网络组合起来,为真实训练提供高效通信。
因此,多机多卡测试不是一个命令,而是一条验证链路。