百度百舸万卡集群的训练稳定性系统设计和实践
点击蓝字,关注我们
01
1.1 标早期的小模型时代:手动运维的黄金年代
1.2 大模型风暴:从量变到质变的冲击
02
任务无效训练时间 = 故障中断次数 × 任务故障恢复时长 + 任务常态写 Ckpt 总时长
提高基础设施的交付质量。 提高任务故障容错的召回率、准确率和时效性。 优化 checkpoint 机制,减少保存时间和恢复时的重算时间。
03
交付前,百度百舸会对机器进行 200 多项指标检测,然后进行 48 小时烤机,以及 NCCL-Test 的机内、机间的大环、同号卡通信性能基准测试,端到端的大模型训练、推理性能基准测试。 交付后,需要能够实时的感知节点故障及定期巡检,并具备分级处理的自愈能力,例如 Error 级别的故障实现自动排水、重启,Fault 级别故障实现自动换机。
04
任务层面稳定性最核心的就是做好容错,能够让业务在无论遇到何种故障时都能快速恢复。
那么,首要的工作就是我们能够准确的识别出异常,然后对故障进行诊断定位,最后能够自动化的从异常中恢复。
因此,任务容错需要能够从端侧(即每个训练 worker)探测到进程与环境的各类异常,同时有个中心服务(Master)从任务全局的视角去诊断、定位异常,最终做出相应的决策来使任务能够快速从异常中恢复。
显式的故障通常比较容易召回,我们将实践积累的各种进程异常状态及各类报错pattern形成专家知识库,再结合硬件感知服务(HAS Agent)的硬件全链路 10 秒级监控能力,可以实现显式故障的召回率达到 95%+。 隐式的异常则往往很难轻易的识别,例如训练进程 hang、慢节点就是典型的隐式故障,需要丰富的经验积累才能准确的识别出异常。
4.1 训练hang 的自动感知
训练任务发⽣ hang 之后,绝⼤多数情况都会以 timeout 的⽅式报错并退出进程,最常⻅的就是在通信过程中如果发⽣ hang,NCCL 的 watchdog 会中断通信,并有报如下 timeout 报错,然后再由 pytorch 的 torchrun 进程感知并中断训练过程。
[E ProcessGroupNCCL.cpp:828] [Rank 1] Watchdog caught collective operation timeout: WorkNCCL(SeqNum=15173, OpType=ALLREDUCE, Timeout(ms)=1800000) ran for 1802710 milliseconds before timing out.[E ProcessGroupNCCL.cpp:828] [Rank 0] Watchdog caught collective operation timeout: WorkNCCL(SeqNum=15173, OpType=ALLREDUCE, Timeout(ms)=1800000) ran for 1802713 milliseconds before timing out.
训练进程 hang 的最直观表现是什么? 人工判断一个任务是否 hang 了,最直接的方式就是看是否所有 worker 的任务日志一段时间内都不输出日志了,所以 hang 自动感知的第一种方法就是采集所有 worker 的日志,并判断所有 worker 日志中最后一行日志是否为 x 分钟前的(x 小于 Pytorch 的通信超时时间,例如 8 分钟),如果是则基本可以判定为 hang。 任务 hang 时进程有什么样的表现? 任务 hang 时,可能进程的调用栈都不在发生变化,进程的调用栈可以通过 py-spy/pystack 等工具进行探测,所以我们可以用此类工具对所有训练任务进行一个定时采样,当采集 n 个样本所有进程栈都没有变化时,可以判定一次 hang,这种方式通常可以将 hang 感知缩小至 3~5 分钟。 任务 hang 时监控指标有哪些变化? 训练进程中的 CUDA 算子计算、集合通信操作通常都是在毫秒,甚至微秒、纳秒内完成的,当任务在正常迭代过程中发生了 hang,我们常遇到的情况是所有 rank 的 RDMA 流量会降到 0,而 GPU 的利用率为 100%、SM 利用率则在很低的水位。如果持续几分钟都是这种状态时,意味着训练进程已经计算完成,在等着集合通信完成,这种情况下基本可以判定为 hang。 是否能在通信库中更快的感知通信 hang? 通常单次集合通信操作都是在 ms 级的,如果一次操作在 30 秒钟都没有完成,那就可以判定为通信 hang 死了。百度自研的 BCCL 集合通信库层可以对每一次集合通信操作都进行打点,来实现通信 hang 感知。
百度集合通信库 BCCL是百度智能云推出的一款面向大模型训练场景优化的集合通信库。 BCCL 基于开源的 NCCL 进行了功能扩展和能力增强,针对大模型训练场景在可观测性、故障诊断、稳定性等方面进行优化,进一步提升集合通信库的可运维能力。相比 NCCL,BCCL 的关键特性如下: * 可观测性:新增集合通信带宽实时统计能力; * 故障诊断:新增集合通信 hang 时的故障诊断能力; * 稳定性:增强网络稳定性和故障容错能力; * 性能优化:提升大模型训练主流 GPU 芯片的集合通信性能。
4.2 训练 hang 的自动诊断
有了以上感知手段,我们需要进一步的诊断、定位,来确定是否真的发生了 hang,以及 hang 的具体位置。具体的来讲,master 收集到各类 agent 的数据后,会做一些综合分析:
是否真的发生了 hang?
感知阶段各种探针只能探测到 hang 的一种特征,并没有办法 100% 的确定是否真的 hang 住了,事实上不侵入用户进程是很难做到 100% 确定 hang 的。因此,为了提高 hang 的判定准确率,我们需要将各种特种综合起来判断,探针上报到 master 后,由一个 hang 诊断模块,按照一个时间窗口(例如 5 分钟),进行综合判断。如果在时间窗口内日志、监控、进程调用栈、通信库中有 2 条以上都处于不处于活跃状态时,我们判断任务真正发生了 hang。
hang 的具体发生的位置?
确定任务 hang 了之后,我们需要找到 hang 所在的节点来对它进行隔离。因此诊断模块需要在探针上报的数据中进一步找寻特征,来确定 hang 发生的位置:
BCCL Tracehang 诊断:在感知阶段,BCCL 可以在通信库层面对所有 rank 的通信进行打点。如果有节点一直未完成通信则是发生了 hang。但是此节点可能并非真正发生 hang 的源头,有可能是在等待其他节点完成通信。诊断模块可以根据 BCCL 打印的通信组信息,进行交叉判断,如果某个节点在多个通信组中都未完成通信,那这个节点就是 hang 的源头。
RDMA/GPU 指标诊断:上文中我们提到,通信阶段发生 hang 之后,所有 rank 的 RDMA 流量都会降到 0,而同时绝大部分 rank 的 GPU 利用率持续为 100%,只有某一两个 rank 的 GPU 利用率为 0,那这个 rank 很有可能是 hang 的源头。
进程调用栈诊断:进程调用栈也可以作为一个 hang 源头诊断的重要参考。当发生 hang 之后,绝大部分的 rank 都要么处于 barrier 等待状态,要么处于通信等待阶段。只有个别的 rank 卡在其他函数上,那么通过对比分析,可以将调用栈与其他 rank 不同的节点初步判定为 hang 的源头。
综合诊断:上面 3 种特征为我们提供了 hang 的诊断依据,将 3 者关联起来分析后,我们基本上可以比较准确的确定一个具体的 hang 的源头,再结合硬件故障感知的相关信息可以进一步明确根因。
4.3 基于 eBPF 的隐式故障感知与诊断
在复杂的大规模分布式训练场景中,传统用户态监控往往难以捕获系统内核层面的异常事件。
百度百舸基于 eBPF(Extended Berkeley Packet Filter)技术的隐式故障感知体系,能够在不侵入用户代码的前提下,对训练进程的系统调用、网络通信、CPU 调度等内核态行为以及训练框架关键函数运行时间建立立体观测能力。
eBPF 探针部署原理通过在内核关键路径注入轻量级探针,实现低开销的系统级行为捕获。针对训练场景特点,主要聚焦 4 类事件跟踪:
训练关键函数跟踪:微秒级跟踪训练过程中,前向计算、反向计算、集合通信操作等关键函数执行耗时,记录函数间调用关系。
进程调度阻塞跟踪:挂钩 sched_switch 事件,检测进程在 TASK_UNINTERRUPTIBLE 状态持续时间,当单次持续超过阈值(如 5 秒)时捕获调用栈。
CUDA 运行时 API 监控:通过 uprobe 在 libcuda.so 等关键库注入探针,记录 CUDA API 调用耗时分布。
RDMA Verbs 级通信监控:在 ibv_post_send/ibv_poll_cq 等核心通信接口设置观测点,统计通信时延分布。
结合上面 4 类事件,完成以下 2 类数据分析:
单体异常探测基线与实时数据对比。
群体一致性检测。采用卡间对比算法,当某一 rank 的以下指标偏离集群中位数超过阈值时判定异常,包括系统调用频率、进程就绪队列等待时长、NVLink/RDMA 带宽利用率等。
基于以上所述方法,百度百舸针对以下 2 类典型的隐式故障进行诊断:
训练 hang 根因定位。通过关联 eBPF 捕获的多维度数据进行如下操作:
当检测到某 rank 的 GPU Kernel 执行出现分钟级空跑(SM 利用率 > 70% 但无有效计算输出)。
同时伴随该节点 RDMA QP 状态停滞(ibv_poll_cq 无新完成事件)。
内核调度器显示进程处于 D 状态超过阈值。
性能抖动溯源。基于 eBPF 火焰图、时序图等进行分析:
抓取发生性能下降时段的 CPU on-cpu/off-cpu 堆栈。
对比正常时段数据,识别出异常的锁竞争(futex 调用占比上升)。
结合 NUMA 内存访问统计,定位跨 NUMA 内存访问导致的 TLB 颠簸问题。
05
故障恢复的时效性也是容错能力的一个重要指标,反映的是任务从故障发生到再次重新进入训练迭代的时间,恢复效率越高则算力浪费越少。影响到任务恢复效率有 2 个重要因素,一是任务平均中断时间,二是训练重算时间。
5.1 多级重启策略减少故障中断时间
任务发生异常后,上文中我们提到需要经过故障自动感知、诊断和自愈等 3 个环节,那么减少中断时间的核心思想,就是尽可能的缩短这 3 个环节的时间,通过多维度的感知、诊断手段可以将故障发现、定位的时效性降低至分钟级甚至秒级。自愈则需要能够根据不同的诊断结果进行分级恢复和故障屏蔽的能力:
单点显式故障:重调度异常节点(replace),对节点进行集群级别屏蔽。 单点隐式故障:重调度异常节点,对节点进行任务级别屏蔽。 非单点故障:原地重启尝试恢复(restart),无法恢复时重新调度所有节点(resubmit)。
通过多级重启策略,尽可能避免单点故障引发全部节点的重新调度。在万卡级别的训练场景中,百度百舸将大部分训练异常场景恢复时间从过去的 30min 缩短至现在的 30s 内,成功率到 95%+。
5.2 触发式 checkpoint 减少训练重算时间
除了上述的多级任务重启策略外,另一个提高任务故障恢复效率的重要手段就是减少训练重算时间。在探讨具体技术方案之前,我们先来看看目前主流的 checkpoint 保存策略。
传统的 checkpoint 保存通常采用固定间隔策略,比如每隔 N 个 step 或每隔 T 小时保存一次,这种方式实现简单但缺乏灵活性,可能会产生大量冗余存储,同时在故障发生时可能会损失较多训练进度。
而触发式 checkpoint 则是一种更智能的方案,它根据特定条件或异常事件(如故障、显存不足、显式指令等)动态触发模型状态保存。其核心目标是通过灵活的控制保存时机,减少不必要的存储开销和训练中断时间,从而降低因频繁或冗余保存导致的重算时间浪费。
随着大模型训练规模的扩大,还有一种更激进的「零重复 checkpoint」技术,即在每个训练 step 都保存一次 checkpoint。这种方案的优势在于可以将重算时间降到最低,确保故障发生时能够从最近的 step 恢复,几乎不会损失训练进度。但其显著的缺点是存储开销巨大,即使采用增量式存储,仍然需要相当大的存储空间和 I/O 带宽。此外,频繁的 checkpoint 操作也可能影响训练性能。
相比之下,触发式 checkpoint 走的是一条平衡之路。我们来看下它实现的几个核心要点:
集成容错:训练进程集成容错的故障感知与定位机制,在进程退出前自动触发保存。这种主动感知机制能够在故障发生的第一时间保存训练状态,最大限度减少进度损失。
高速转储:异步 checkpoint 保存机制会将 checkpoint 暂存到共享内存中,再由外部程序转储至磁盘。当某个节点异常时,容错组件会拉起新节点,并在新节点训练进程启动前,利用 RDMA 技术实现 checkpoint 快速从故障节点转储至新节点,这大大减少了从远程存储拉取 checkpoint 的时间。
冗余备份:触发式 checkpoint 也并非完美无缺,例如在节点发生内核 crash 等严重故障时,可能无法触发自动保存。因此,需要通过定期的冗余备份机制进行兜底,确保 checkpoint 不会完全丢失。
实践表明,当触发式 checkpoint 与异步、增量式的 checkpoint 机制结合使用时,可以在保证数据安全性的同时,显著提高 checkpoint 保存效率,减少训练重算时间。
相比零重复 checkpoint 的重型方案,触发式 checkpoint 提供了一个更实用的折中方案,在合理的存储开销下实现较好的容错效果。当然,具体选择哪种方案,还需要根据实际的训练规模、硬件条件和可用资源来权衡。
随着分布式训练规模的持续增长,相信未来会出现更多创新的 checkpoint 方案,比如基于预测的主动保存策略、多级存储架构的智能调度等,这些都将为提高大规模训练的可靠性提供新的可能。
06
AI 训练的稳定性管理已经演变为智能时代的精密工程。从最初靠人工重启解决问题的摸索阶段,到如今能自动感知异常、快速恢复的智能系统,每一次进步都映照着算力规模的跨越式发展。
让人不禁思考,在未来十万卡集群的算力洪流中,或许会出现更精妙的动态平衡方案:既能像鹰隼般敏锐捕捉故障征兆,又能如雁群迁移般智能调度资源,在秒级恢复与 PB 级存储成本之间找到新的平衡支点。
目前百度百舸支持厂内千卡和万卡集群有效训练时长已经可达 99.5%,为客户大模型的预训练保驾护航,比如国内第一个数学大模型——九章算术,国内第一个类 Sora 大模型 —— Vidu 等。
END
推荐阅读