363 lines
11 KiB
Markdown
363 lines
11 KiB
Markdown
# 多机多卡 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. 总体思路
|
||
|
||
多机多卡通信测试是一个自底向上的过程。越底层越接近硬件和链路,越上层越接近真实训练业务。
|
||
|
||
```mermaid
|
||
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。
|
||
|
||
所以排查顺序应该是:
|
||
|
||
```text
|
||
基础连通 -> 单机健康 -> 单机性能 -> 单机 NCCL -> 跨机 RDMA -> 跨机 NCCL -> 训练业务
|
||
```
|
||
|
||
## 2. 两机 16 卡通信路径
|
||
|
||
单机内部主要走 NVLink/NVSwitch;跨机器时,数据必须经过 GPU、PCIe/NVLink、网卡、交换机和对端网卡。
|
||
|
||
```mermaid
|
||
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 健康层
|
||
|
||
这一层证明每台机器自己是健康的。
|
||
|
||
```mermaid
|
||
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 卡之间的集体通信。
|
||
|
||
```mermaid
|
||
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。
|
||
|
||
```mermaid
|
||
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 卡机器通常是:
|
||
|
||
```text
|
||
2 nodes x 8 GPUs = 16 ranks
|
||
每个 rank 绑定 1 张 GPU
|
||
```
|
||
|
||
概念上是:
|
||
|
||
```mermaid
|
||
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 卡通信的瓶颈不同。
|
||
|
||
```mermaid
|
||
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. 常见失败位置
|
||
|
||
```mermaid
|
||
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 卡机器的推荐顺序:
|
||
|
||
```mermaid
|
||
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. 最小概念模型
|
||
|
||
记住这句话即可:
|
||
|
||
```text
|
||
单机 NCCL 验证 GPU 之间的 NVLink/NVSwitch。
|
||
跨机 RDMA 验证机器之间的网络。
|
||
跨机 NCCL 验证 NCCL 是否能把 GPU 和网络组合起来,为真实训练提供高效通信。
|
||
```
|
||
|
||
因此,多机多卡测试不是一个命令,而是一条验证链路。
|
||
|