日期:2026-08-28
我们做领域大模型训练,单次跑几天是常态,几十张卡一起算。最怕半夜节点掉一个,整个任务从头来,几万块的算力直接打水漂。我们进场时,训练脚本没有任何容错,掉卡就是人工重启,重启还是从零,研究员看见报警就头疼。
更糟的是,训练数据 pipeline 也有状态。从头重启不只是丢模型进度,数据读取位置、随机打乱的 epoch 状态全没了,重跑一遍数据加载本身就耗不少时间。研究员说,最怕的不是报错,是报错后不知道从哪捡起来,只能含泪 rm 重来。
我们给训练加周期性快照,把模型权重、优化器状态、数据读取位置都存下来。节点故障自动检测,坏卡隔离,任务不中断。断点续训从最近快照拉起,丢失的只那几步。checkpoint 做一致性校验,防写坏。故障期间任务进排队,资源一恢复就续上。
除了续训,我们还做了多副本快照,存到不同存储,防止单点盘坏把唯一 checkpoint 也带走了。训练看板实时显示每张卡的健康度、当前 step、预计剩余时长,研究员一眼看清进度。故障告警直接推到值班群,附上最近快照时间和预计恢复 step。
快照频率是个跷跷板。我们最早五分钟存一次,训练吞吐掉了快一成,研究员嫌慢。改成一小时一次,结果一次掉卡丢了一小时进度,又肉疼。后来按步数动态调,前期稳就稀疏存,临近易错阶段加密,整体开销压到可接受。续训对齐也容易出事,优化器状态没存全,拉起来梯度乱跳,loss 飙了,我们后来把优化器 state 和随机数种子一起快照才稳。故障隔离不能只踢卡,得把依赖它的通信组也重排,否则剩的卡互相等。
快照写入本身也会拖训练。我们早期同步写盘,step 卡顿明显,后来改成异步写加带宽限流,训练几乎无感。一致性校验也不能省,有过一次快照写一半进程被杀,拉起来权重损坏,loss 直接 NaN,我们加了写后 crc 校验,坏快照自动弃用上一个。
案例片段(已脱敏): 训练快照与续训的核心配置:
yaml checkpoint: interval_steps: dynamic save: [weights, optimizer, dataloader_state, rng_seed] async_write: true consistency_check: crc32 fault: detect: heartbeat_5s isolate: true requeue: true resume: from_latest: true reinit_comm_group: true上线后续训恢复时长从平均四十分钟降到五分钟以内,无效重算率从约一成降到百分之一,训练中断次数基本归零,GPU 利用率回升约一成五。
续训恢复时长从平均四十分钟降到五分钟以内,掉卡不再意味着归零。无效重算率从约一成降到百分之一,算力不再白白烧。训练中断次数基本归零,研究员不用半夜爬起来重启。GPU 利用率因为少做无用快照、异步写盘,回升约一成五。多副本快照上线后,再没出现过唯一 checkpoint 损坏导致全废的情况。最实在的是,一次大训练原本可能重跑两三次,现在一次跑完,账单好看很多。
容错上线后,研究员的心态变了。以前大训练能不重启就不重启,不敢动任何参数,怕一停回到解放前。现在随便调,掉卡也无所谓,反而更愿意做实验,训练迭代快了。这比省下的算力更值钱。
我们还把快照接进了成本账单,每次续训省下的重算时长折算成钱,月底给老板看。一张大训练卡几天,少重跑一次就是几万,这数字比任何汇报都管用。平台组从此在预算会上有了底气,不用再为闲置卡挨批。
续训能力还顺手解决了一个老大难,长训练的版本管理。以前一次训练跑几天,中途想换个小参数得从头,大家宁可带着缺陷跑完,导致很多次训练结果其实不干净。现在随时能停能续,研究员反而更敢在中途做小实验,训练质量反而提高了。这种心理层面的解放,是算力账单之外更大的收益。
我们还把故障检测和续训做成了可观测的链路,每次掉卡自动记录是哪张卡、什么时间、丢了多少步,月底汇总成硬件健康报告。采购据此找供应商退换了一批不稳定卡,整体故障率又降一截。训练平台从救火队变成了能反向推动硬件质量的角色,这层价值老板当初没想到。
还有一点值得说,断点续训让新人上手训练不再心惊。以前怕一个误操作毁掉几天的进度,现在随时能停能续,新人敢练手,团队迭代速度反而更快。我们把续训操作写进标准流程,配了检查清单,连实习生都能安全跑长任务,这层人力成本的释放以前没算过账。
大模型训练容错,快照是底线,但频率不能拍脑袋,按步数动态调比固定间隔聪明,我们两头吃亏后才找到平衡点。续训最容易被忽略的是优化器状态和随机数种子,只存权重拉起来梯度会乱跳,这坑踩过一次就记住了。故障隔离要连通信组一起重排,否则剩的卡空等更浪费。快照异步写加 crc 校验,既保性能又防坏盘。讲句实话,训练平台的成熟度,不看它跑得多快,看它掉卡之后能不能让你继续睡安稳觉。