L3.4 万卡集群弹性容错
三维坐标
layer: L3(训练)|level: Senior/Architect|pillar: 训推框架万卡集群训练的核心矛盾不是「算得快不快」,而是**「在硬件持续 抖动下能不能活到收敛」。当 GPU 数量从千卡跨到万卡,单卡平均无故障时间(MTBF)被乘上一万倍稀释——一次训练里几乎必然**会有卡掉、网断、ECC 翻位。本文先下沉到 NCCL / 昇腾 HCCL 集合通信底层,看清 All-Reduce 的物理耗时从何而来,再上浮到 弹性训练(elastic training) 的故障剔除—热备拉起—无重启热恢复全链路。
学习目标
- 前置知识:读过 L3.1 3D 并行(知道 TP/PP/DP 怎么切,world size 为何对并行策略敏感)、L3.2 ZeRO 显存优化(知道优化器状态/梯度如何分片)、L3.3 框架实践(跑过
torchrun起多进程任务);并了解 L1.3 AI 存储架构里的 checkpoint 落盘路径(GDS / 本地 NVMe + 远端对象存储分层)。无需 NCCL 源码经验。 - 学完产出:① 能写出 Ring All-Reduce 的耗时公式
T_ring ≈ 2·(N-1)/N·S/BW,并解释(N-1)/N因子为何让带宽量与卡数几乎无关;② 能区分 Ring / Tree / Double Binary Tree 三种 All-Reduce 在「带宽 vs. 延迟」上的取舍,说清NCCL_ALGO改了为什么大小消息表现相反;③ 能画出「故障检测 → 秒级剔除 → 热备拉起 / 缩容 → 重组 → 无重启续训」的容错状态机,并指出 NCCL 通信组「半死不活」这个最致命的坑;④ 能算清「真死 vs. 慢」误判、「热备 vs. 缩容」成本、「checkpoint 频率最优解」三笔账,理解为什么 TP 维度几乎不能缩容;⑤ 亲手用torchrun跑通弹性训练,kill掉一个 worker 后观测到 rendezvous 重组 + 从 checkpoint 续 训。 - 阅读姿势:盯住一条主线——「万卡训练的胜负手不是峰值算力,而是『在硬件持续抖动下能不能活到收敛』」。从集合通信底层(故障最终都暴露在 All-Reduce 这一环)一路上浮到弹性恢复全链路,每个机制都在回答同一个问题:单卡可靠、万卡必坏,如何让一次故障的代价从「小时级全量重启」压到「秒级无重启热恢复」。
背景与现状
万卡集群弹性容错(Large-Cluster Elastic Fault Tolerance) 解决的是一个朴素却致命的工程现实:单卡可靠,万卡不可靠。假设单张 GPU 的日故障率是 0.1%,那么一个 1 万卡集群在一天内至少坏一张卡的概率高达 99.99%——这意味着没有容错能力的训练任务,跑不过一个晚上就会因为单点故障而全军覆没。
故障来源是物理性的、不可消除的:
- 硬件层:HBM 的 ECC(纠错码) 不可纠错错误、SM 计算单元降频、NVLink 链路降速。
- 网络层:RDMA/RoCE 的网络丢包、光模块(optical module)抖动、交换机端口 flap。
- 系统层:进程 OOM、节点宕机、NCCL 通信在环死锁(hang)——这是最隐蔽的一类,所有 rank 卡在同一个 All-Reduce 上,GPU 利用率 100% 却没有任何进展。
业界的演进可以概括为三个阶段:
- 静态训练时代(2020 前):world size 固定,任意一卡挂掉 → 整个 job 失败 → 从上一个 checkpoint 全量重启。万卡场景下,一次重启的代价可能是数小时算力。
- 弹性训练登场(2019–2021):PyTorch 于 2019 年推出 TorchElastic(2021 年随 PyTorch 1.9 并入主干成为
torchrun),引入 c10d rendezvous(集合点) 机制,允许 world size 动态伸缩,单点故障后仅重组幸存 worker 而非全量重启。 - 无重启热恢复(2023 至今):Meta、字节、阿里等团队推动热备卡(hot spare)动态拉起与进程级热恢复,目标是把单次故障的恢复代价从「小时级」压到「秒级 / 分钟级」,让万卡 MFU(Model FLOPs Utilization)不被容错开销吃掉。
业界信号:Meta 在 OPT-175B 训练日志中坦承,2 个月里经历了 100+ 次硬件故障与手动重启;Llama 3 的 405B 训练在 16K H100 集群上平均每 3 小时一次中断。这说明:在万卡尺度,容错不是「锦上添花」,而是「能不能训出来」的胜负手。
原理与架构
要理解弹性容错,必须先理解**「故障发生在哪里」——而 90% 的训练故障,最终都暴露在集合通信(collective communication)** 这一环。
2.1 通信库底层:NCCL 与昇腾 HCCL
NCCL(NVIDIA Collective Communications Library) 是 NVIDIA GPU 之间集合通信的事实标准;华为昇腾的对应物是 HCCL(Huawei Collective Communication Library)。两者的源码组织高度相似:都把 All-Reduce / All-Gather / Reduce-Scatter / Broadcast 等原语,映射到底层物理拓扑(NVLink / PCIe / RDMA 网卡)上的一系列点对点(P2P)传输。
以最核心的 All-Reduce(梯度同步)为例,NCCL 会根据节点规模与拓扑,在三种算法间自动选择:
| 算法 | 拓扑结构 | 适用规模 | 通信轮数 |
|---|---|---|---|
| Ring All-Reduce | 环形 | 中等规模、带宽敏感 | 2(N-1) 步 |
| Tree All-Reduce | 二叉树 | 大规模、延迟敏感 | 2·log(N) 步 |
| Double Binary Tree | 双二叉树 | 超大规模(NCCL 默认) | ~2·log(N),且带宽利用率接近 Ring |
Ring All-Reduce 的物理耗时公式是理解一切通信优化的基石。设 N 为参与卡数、S 为待规约数据量(字节)、BW 为单链路带宽(字节/秒),则一次 Ring All-Reduce 的理论传输耗时约为:
T_ring ≈ 2 · (N-1)/N · S / BW
关键洞察藏在 (N-1)/N 这个因子里:当 N → ∞,该因子 → 1,意味着 Ring All-Reduce 的通信量与卡数 N 几乎无关,只取决于数据量 S 与带宽 BW——这正是 Ring 算法在大规模下「带宽最优」的数学根源。但它的步数 2(N-1) 随 N 线性增长,因此万卡尺度下延迟(latency)会被放大,NCCL 才转而用 Double Binary Tree 把步数压到 log(N) 级别。
源码必读路径:NCCL 的算法选择逻辑在 src/transport/ 与 src/graph/(拓扑探测)、src/collectives/(原语实现);HCCL 的对应实现在 CANN 的 hccl/ 目录,其 AllReduceOperator 与 NCCL 的 ncclAllReduce 一一对应。理解这一层,你才能解释「为什么改了 NCCL_ALGO=Tree 后小消息变快、大消息变慢」。
2.2 长周期训练容错:故障剔除—热备拉起—无重启热恢复
弹性训练的核心抽象是 rendezvous(集合点):所有 worker 在启动时向一个中心化的 KV 存储(c10d store,底层常用 etcd / TCPStore) 注册,达成对「当前 world size 与各自 rank」的共识。当某个 worker 故障,rendezvous 会触发重组(re-rendezvous),幸存 worker 重新分配 rank 并从 checkpoint 续训。
整个容错闭环可以建模成一个