![[从零训练一个500B大语言模型] 19/25:训练突然停了,怎样接着跑?](/_next/image?url=%2Fblog%2Ftraining-500b-part-19-cover.webp&w=3840&q=75&dpl=dpl_HKDZtjNTn1U2zk8pGrYRnYGkyGR9)
[从零训练一个 500B大语言模型] 19/25:训练突然停了,怎样接着跑?
训练进行到第十天,上午10点40分,一台服务器掉线了。其他机器很快停在通信等待里,刚才还在推进的5,120张GPU,停住了。
我先翻保存记录。10点,那一份检查点已经完成。
这意味着最近40分钟需要重算,前九天的工作还有退路。接下来要做的很具体:确认这份存档能用,把故障机器换出去,再沿着原来的材料顺序继续。
第十三篇留出的存储容量,此刻成了训练能否接回来的关键。我沿着这次中断往回查,先看10点那份存档究竟保存了什么。
先把“训练进度”理解完整
权重文件能告诉我模型现在学到了什么。要继续训练,还需要知道它怎样走到这里、下一批准备读什么。
AdamW保存近期梯度的历史,学习率调度保存当前处在预热还是下降阶段;取样程序保存材料顺序与位置;随机状态影响某些训练操作。把这些信息放在一起,才能接着原来的训练路径继续。
保存点因此放在一次完整参数更新结束以后。这个时点,各个分片已经完成同一步,下一步的梯度尚未开始累积。恢复时从下一次完整更新开始,状态关系最清楚。
| 存档中的内容 | 恢复时用它回答什么 |
|---|---|
| 模型权重及高精度主权重 | 此刻各参数是什么值 |
| Adam的两组历史状态 | 下一次更新怎样延续此前方向与尺度 |
| 学习率调度状态 | 下一步应该用多大的步幅 |
| 已读样本、成功更新和跳过更新计数 | 材料账与参数更新账分别走到哪里 |
| 数据版本、取样位置与必要的随机状态 | 下一批应当读什么 |
| 模型、分词器、软件和并行配置 | 用什么环境重新解释这些文件 |
核对进度时,第十六篇分开的两本账派上了用场:读取进度与成功更新进度。某一步可能已经读完材料,却因异常数值跳过了参数更新,所以两种计数都要存。恢复程序按保存的状态接续,日志再明确哪些材料是故障后重新读取的。故障前未保留下来的计算与恢复后的重算都计入算力成本;正式10T进度从检查点继续累计,同一段回滚材料不在有效进度中重复计数。
再对照第十三篇的容量账,主要状态一项项找齐:500B参数的BF16权重约1TB,FP32主权重约2TB,Adam两组历史约4TB,合计约7TB。其他状态、索引和文件格式增加实际容量,由验收时的文件清单记录。
训练状态:继续执行训练所需的全部信息,包含模型、优化器、进度和随机状态等。
随机状态:随机数生成器当前的位置。保存它,有助于恢复后延续相同的随机操作序列。
7TB怎样从很多张卡变成一份存档?
文件分散在很多进程写出的目录里。每张GPU只持有自己负责的状态,保存时把分片写出去,同时记录它属于模型的哪一块。恢复就沿着这些记录,把状态送回对应位置。
80个数据并行副本里有重复的计算权重,存档却只需要一份完整逻辑模型。分布式保存实现可以让不同进程共同写文件,既利用多台机器的能力,也避免把80份重复权重全写一遍。我们核对的是逻辑张量是否覆盖完整、是否重复,以及恢复时能否找到对应位置。
Megatron提供分布式检查点接口。本计划固定Core 0.19.2的实现和检查点格式,验收时把一次真实保存产生的清单与预期模型状态逐项比较。
我又看了一眼保存的两个时间:GPU何时继续计算,后台何时把文件真正写完。它们可以不同。异步保存先形成一致的快照,再让后台继续写入,训练可以在满足实现条件后恢复计算。文件还没有写完时,这份新检查点仍然处于进行中。
这份还在后台写出的快照,也要占用CPU内存与存储资源。用于异步写出的快照要有地方放,后台写入还会与数据读取争用资源。我们先测真实状态快照和写入过程,再决定并发度,不让“后台保存”变成另一种持续拖慢训练的来源。
分片:把一个大对象分成多部分,分别由不同设备保存或处理。
一致快照:来自同一个逻辑时点、能够共同恢复的一组状态副本。
目录里有文件,怎样才能宣布保存成功?
目录里有好几TB文件,还不足以让我按下恢复。保存途中只要有一台机器退出,一部分分片就可能缺失;已经写完的那些文件,拼不回完整进度。
我沿着这次保存的独立编号核对。开始写入时标为进行中,只有全部必要分片写完、元数据与完整性检查通过,才把它加入“已完成”的列表。恢复入口只选择已完成的编号。
框架的完成回调与检查点元数据之外,还留着一份清单:更新时间、训练步数、文件数量与大小、分片覆盖、校验结果,以及复制到归档的状态。需要额外校验的文件,在存储预算内完成校验。目标是让完整性判断有记录可查。
系统原来指向9点的完整存档。10点的新存档全部准备好,再一次性把“最新完成”指向10点,这就是这里的原子更新。读取者要么看到9点,要么看到10点,不能看到一个完成了一半的10点。共享文件系统的重命名语义与对象存储的提交方式不同,集成时按实际后端实现并测试这一动作。
往前翻,最近三份完成存档仍按第十三篇的方案保留,第四份写入也有空间。新的一份通过以后,再按策略删除最旧的一份。删除任务与完成判断分开,避免保存失败时把已有退路一起清掉。
原子更新:对使用者呈现为一次完整变化的更新,中间状态不会作为完成结果被读取。
完整性校验:检查数据是否齐全、是否在传输或存储中发生变化的过程。
什么时候保存,才能少浪费时间?
这次找回了10点的进度,也让我重新看每小时保存一次的安排。存得更勤,丢掉的40分钟可以缩短;可保存本身也会占用训练时间。
我先把保存阻塞3分钟、平均每24小时遇到一次需回滚的中断放进表格。按每小时保存,平均回滚约半小时。定时保存损耗是3÷60,约5%;回滚损耗是0.5÷24,约2.08%。检测、重启与加载时间还得另加。
如果改成每两小时保存,保存占比降为约2.5%,平均回滚增加到1小时,约占4.17%。两者的和接近,但恢复时间与故障分布仍会影响选择。我们需要的是整段运行损耗最小的频率。
把间隔依次改成30、60、90和120分钟,先只合计保存停顿与故障回滚,两种代价就清楚了:
| 保存间隔 | 保存停顿占比 | 平均回滚占比 | 两项合计 |
|---|---|---|---|
| 30分钟 | 10.00% | 1.04% | 11.04% |
| 60分钟 | 5.00% | 2.08% | 7.08% |
| 90分钟 | 3.33% | 3.13% | 6.46% |
| 120分钟 | 2.50% | 4.17% | 6.67% |
存得太密,保存停顿占得多;存得太疏,故障后重算得多。这组数里,90分钟值得与现有的一小时方案一起试跑。下面的公式会把这个平衡点算得更细。
展开计算:为什么平衡点约为93分钟?
在简单的均匀故障近似下,保存阻塞时长为C、平均中断间隔为M,间隔T带来的两项损耗可以粗略写成C÷T+T÷(2M)。这给出一个比较起点T≈√(2CM)。把3分钟与24小时放进去,大约是93分钟。这个公式忽略了相关故障、恢复时间变化和异步写入冲突,项目用它筛选一小时或一个半小时的对照,再由实际记录决定。
这张表里使用的3分钟与24小时,往后随着保存停顿和中断记录更新,93分钟的平衡点也会跟着移动。第十三篇“十分钟内完整可恢复”记的是整份保存完成时间,GPU阻塞了多久要另看记录。
间隔缩短,还会把压力推向存储设备。每小时约7TB,一天约168TB逻辑写入;若缩短间隔,这笔写入会一起增加。存储容量没有变,设备工作量已经变了。
机器出错以后,自动重启到哪一步?
回到10点40分这次故障,日志里已经满是通信超时。我先保留最早的错误,确认任务停止推进,再隔离可疑节点。后面一串超时可能只是连锁反应,要追的起点在更早的GPU错误、网卡异常或进程退出里。
最后一份完整检查点已经找到了,接着确认健康机器能重新组成原来的规模。当前先由值班人员确认恢复;故障分类、节点排除与恢复验证跑稳以后,再把常见情况交给自动流程。
截至2026年11月,NVIDIA Resiliency Extension的0.7.0发布说明已经包含作业内重启、热备用与节点健康相关能力。它说明自动恢复正在成为训练系统的正式组件。本项目把这些能力放进独立验收分支:先核对与Core 0.19.2、启动方式和Slurm部署的兼容关系,再决定是否接入正式运行。
这次保持TP8、PP8和DP80不变,让备用服务器接替故障位置。改变并行规模时,检查点重分片、全局批量、优化器状态和数据顺序都要重新验证;有明确需要时再作这项调整。
恢复能够自动化,也必须知道什么时候停下来。相同材料连续触发异常、同一节点反复报错、恢复后损失持续偏离,都应停止重复重启,转入排查。这样可以避免集群整夜反复计算同一段失败任务。
热备用:已经准备好、能够较快接替故障资源的备用设备。
重分片:按新的设备分工重新分配已有模型或优化器状态。
恢复成功,要看下一次更新
加载结束,屏幕重新出现日志。我先核对检查点编号、累计样本、成功更新数和学习率,再抽查下一批材料编号。随后等一小段更新完成,与验收时的恢复对照放在一起看。
机器的状态也要跟上:所有进程是否进入相同阶段,是否有分片缺失,峰值显存和吞吐是否恢复到相近范围。替换了一台机器以后,如果整条流水线慢下来,就检查新节点的软件、GPU时钟、网卡与缓存准备。
这次共享工作区还在,恢复走的是近期存档。再把故障范围扩大到共享工作区,就得转向独立归档。它保存每日完整进度,可能需要回滚更长时间,但仍能把训练接回来。恢复演练既要从近期共享存档做一次,也要从归档取回做一次,才能知道两条路径各需要多久。
下一次成功更新完成以后,我把事件记下来:何时最后完成更新,何时检测中断,使用哪份存档,何时恢复下一次成功更新,重算了多少token。它能直接告诉我们,中断损失来自发现太慢、保存太疏,还是加载和替换太久。
10点40分中断的任务,沿着10点的完整存档接了回来。故障节点换出,材料顺序接上,重算的40分钟也留在成本账里。日志再次向前,前九天的工作没有丢。
约76天的训练,就靠这样的完整存档和恢复路径,一段一段继续。等它稳定运行,下一件值得盯住的事便是速度:机器看起来都很忙,为什么结束日期仍可能越推越远?
新文章,直接发到你的邮箱。
AI、工程与实验,每月 1–2 封。
无垃圾邮件,随时取消。