test_gpu_scripts/docs/multinode_nccl_concepts.md

363 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 多机多卡 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 和网络组合起来,为真实训练提供高效通信。
```
因此,多机多卡测试不是一个命令,而是一条验证链路。