# 多机多卡 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. 物理与基础连通
电源 / GPU / 网卡 / 线缆 / 交换机 / SSH"] --> L1["1. 系统识别层
nvidia-smi / lspci / ibstat / ibdev2netdev"] L1 --> L2["2. 单机 GPU 健康层
温度 / 功耗 / ECC / PCIe / Throttling / NVLink Topo"] L2 --> L3["3. 单机 GPU 性能层
HBM 带宽 / H2D-D2H / FP32-TF32-FP16-BF16-FP8 算力"] L3 --> L4["4. 单机多卡通信层
单节点 8 卡 NCCL over NVLink/NVSwitch"] L4 --> L5["5. 跨机网络与 RDMA 层
IP 连通 / IB Active / RDMA 带宽 / RDMA 延迟"] L5 --> L6["6. 跨机 NCCL 层
两机 16 卡 AllReduce / AllGather / ReduceScatter / Broadcast / AllToAll"] L6 --> L7["7. 训练负载层
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 和网络组合起来,为真实训练提供高效通信。 ``` 因此,多机多卡测试不是一个命令,而是一条验证链路。