预训练工程实战:Checkpoint、容错与训练稳定性
摘要: 预训练不是"把代码跑起来"——是在万卡集群上跑几个月不出事。Checkpoint 怎么写才能既保进度又不拖慢训练?节点挂了怎么最快恢复?Loss 曲线异常怎么排查?本文给出工程答案:Checkpoint 策略、容错流程、Loss 异常排查清单。
0. 实验目标
- 设计 Checkpoint 策略:周期、异步、分片三要素
- 掌握节点故障恢复流程:从发现到重启训练的可执行步骤
- 建立 Loss 异常排查清单:先查数据、再查代码、最后查集群
- 理解训练稳定性的工程护栏(watchdog、健康检查、日志审计)
1. Checkpoint 三要素:周期 / 异步 / 分片
python
# 训练框架里的 Checkpoint 配置(Megatron/DeepSpeed 等语义)
checkpoint = {
"interval": 500, # 每 500 步存一次
"async_save": True, # 异步保存:不阻塞训练
"shard": True, # 分片存储:每卡只存自己的分片
"keep_last": 3, # 保留最近 3 个(磁盘成本控制)
"save_optimizer": True, # 存优化器状态(否则恢复后动量丢失)
}逐段拆解:
- 周期(interval):步数间隔。太频繁拖慢训练(同步保存阻塞),太稀损失进度。经验值:500-2000 步,配合硬件故障概率权衡。
- 异步保存(async_save):保存到本地磁盘先落盘,再后台拷贝到共享存储——保存不阻塞训练步,是大规模训练标配。
- 分片(shard):每个 rank 只存自己的权重分片(Megatron 的
distributed_optimizer),避免"一个 checkpoint 文件几百 GB、集中写挂掉"。 - 保存优化器状态:只存权重 = 恢复后优化器动量清零,收敛曲线会倒退。训练中断恢复必须存 optimizer state。
2. 容错:节点挂了怎么办
bash
# 故障发现:训练进程 watchdog(挂掉即报警并拉日志)
# 常见信号:rank 心跳超时、NCCL 超时、OOM、节点无响应
# 恢复流程(可执行步骤):
# 1) 定位故障节点:scontrol show job + 集群监控(DCGM/IB 状态)
# 2) 隔离故障节点:slurm 置 DRAIN / K8s cordon,防止再次分配
# 3) 硬件处置:坏 GPU/网卡换件;IB 故障检查(本知识库 [IB 运维](/guide/03-network/ib-admin-guide) 篇)
# 4) 重启训练:从最近的 checkpoint 恢复
srun --nodes=N --ntasks-per-node=8 \
python train.py --resume-from /share/ckpt/latest/工程启示(容错要点):
- 检查点是恢复的唯一依赖:重启 = 从最近 checkpoint 恢复,所以"checkpoint 写坏了"比"节点挂了"严重得多——恢复后先校验 checkpoint 完整性(权重 hash)再继续。
- 故障分级处理:单节点故障(最常见)→ 重启恢复即可;大面积故障(网络分区)→ 先别急着恢复,排查根因,否则重启了还会再挂。
- 保存与恢复要可审计:每个 checkpoint 记录步数、loss、配置 hash;恢复日志里确认"从第 N 步恢复",防止静默恢复到旧版本。
3. Loss 异常排查清单(按顺序排查)
| 现象 | 第一嫌疑 | 排查动作 |
|---|---|---|
| Loss 突增/发散(NaN/Inf) | 数据问题 | 检查最近数据批次:重复、异常 token、清洗规则误杀 |
| Loss 缓慢不降 | 学习率/配比 | 检查 LR schedule、数据混合配比(数据管线 篇) |
| 重启后 Loss 反弹 | checkpoint 缺失 optimizer state | 确认恢复含优化器状态 |
| 多卡 Loss 不一致 | 通信/并行配置 | 检查 DDP/TP 配置、NCCL 拓扑 |
| 偶发 NaN | 数值稳定性 | AMP 检查、梯度裁剪、BF16 溢出 |
原理讲解:
- 排查顺序铁律:先数据、再代码、后集群。预训练数据是 TB 级,清洗规则一个 bug 可能污染整段训练(本知识库 数据管线 篇强调"loss 异常先查数据报告")。
- 重启后 Loss 反弹是最常见的"假异常":只存了权重没存 optimizer state,恢复后等于"换了个优化器起点"——查 checkpoint 是否含
optimizer。 - 偶发 NaN:大模型 BF16 训练中,梯度 underflow/overflow 是常态风险;
loss_scaler(AMP)与梯度裁剪(max_grad_norm)是两道防线。
4. 训练稳定性护栏(长期运行的关键)
python
# 1) Watchdog:训练进程健康探活 + 自动重启 + 日志留存
# 2) 指标审计:每 N 步记录 loss/吞吐/GPU 利用率到时序库
# 3) 配置版本化:训练脚本 hash 进日志,恢复时校验一致
# 4) 定时校验:每个 checkpoint 保存后做一次权重 hash + 可加载性测试
# 5) 熔断机制:连续 N 步 loss 异常 → 自动暂停 + 报警,避免"带病训练"跑几天工程启示:
- Checkpoint 三要素:周期 500-2000 步、异步保存、分片存储 + optimizer state。
- 故障恢复流程化:定位 → 隔离 → 处置 → 恢复,恢复后先校验 checkpoint。
- 排查顺序铁律:先数据、再代码、后集群。
- 重启反弹 ≠ 训练坏了:先查 checkpoint 是否含 optimizer state。
- 熔断机制:连续 loss 异常自动暂停,别让坏训练浪费算力。
- 配置版本化:恢复日志核对"从第几步、哪个配置恢复"。
- 健康检查进集群:watchdog + DCGM/IB 探活,故障自动 DRAIN。