训练系统(Training Systems)
所属:01-fundamentals / 06-agent-infra
面试权重:★★★
来源:《深入理解 AI Infra:量化分析与系统设计》第 10 章(李博杰,github.com/bojieli/ai-infra-book);章内所有数字都带任务条件(Qwen3-8B 全参、100B token、8,192 序列长),非本仓库测量
相关知识点:batching-parallelism.md(那篇讲并行怎么切,这篇讲切完怎么跑起来、坏了怎么恢复)、07-distributed-inference.md(同一套分析方法用在推理侧)、02-post-training/(算法侧 —— RL 的 loss 与优势怎么算,本篇讲它的系统侧)、../00-toolchain.md(训练与后训练层的点名表:Verl / TRL / Megatron-LM / DeepSpeed / FSDP / PEFT·LoRA / Unsloth / LLaMA-Factory / Axolotl)
一句话#
训练系统的设计问题可以压成一句话:「每步预算 ÷ 每步要做的工作」。显存决定能不能开始跑,计算决定能不能按期跑完,而 checkpoint 与故障恢复决定已经做过的工作有多少要重做。理解它的最小抓手是三个数:每参数 16 bytes 的常驻训练状态、流水线的气泡、最优保存间隔 。
为什么重要(面试角度)#
- 它是「算法题」之外的另一半,而且面试官默认你会。 问 LoRA / DPO / GRPO 时他在考算法;一旦问到「8B 全参要几张卡、多少天、坏了怎么办」,考的是系统。仓库此前的并行策略只讲到「怎么切」,没讲切完的每步耗时、显存峰值和恢复代价 —— 这篇补的正是那一层。
- 它有一批能当场算出来的数字:16 bytes/参数、ZeRO 四阶段的容量公式、流水线气泡 、最优保存间隔。答案是可以推导的,不是背的。
- 它的反直觉特别多,正好用来分层:分片数翻倍显存峰值并不减半;通信处理时间更短训练步不一定更短;卡数翻倍且 batch 跟着翻倍,完成时间并不减半。能说清这三条为什么,就说明你真的理解了这个系统。
- 它接得上仓库已有的两块:
02-post-training/讲 RL 的算法,08-agentic-rl.md讲多轮 RL 的缝;这篇补的是 RL 的系统侧 —— 三阶段流水、训推一致性、异步盈亏平衡点。面试问「你的 RL 训练为什么慢」,答算法是答偏了。
⚠️ 边界声明:本篇是《AI Infra》第 10 章的知识梳理,不是一手经验。你没有训练过 8B 全参模型、没搭过 48 卡集群、没做过 checkpoint 恢复。面试时按「这套账我会这么算」讲,不要说成「我们训练时就是这么配的」。你在 RL 侧的真实经验是 HKJC 的单轮 RLVR(Verl 两阶段),那是小规模、单轮的,与本篇的千卡级训练不是一回事 —— 这条边界要自己先说。
核心内容#
1. 常驻训练状态:每参数 16 bytes#
这是全篇最该记住的一个数。混合精度 Adam 下,一个参数要占五份状态:
| 状态 | 每参数字节 | Qwen3-8B(8.19B 参数) | 用在哪 |
|---|---|---|---|
| BF16 模型权重 | 2 | 16.4 GB | 前向与反向矩阵运算 |
| BF16 梯度 | 2 | 16.4 GB | 反向产生,算新参数时用 |
| FP32 主权重 | 4 | 32.8 GB | 保存新参数,再转 BF16 副本 |
| Adam 一阶矩 | 4 | 32.8 GB | 跨迭代保留梯度方向历史 |
| Adam 二阶矩 | 4 | 32.8 GB | 跨迭代保留梯度平方历史 |
| 合计 | 16 | 131.1 GB |
一句话记住量级:常驻训练状态约等于八份 BF16 权重。 8B 模型推理只要 16.4 GB,训练却要 131 GB —— 这是「单卡能推理 ≠ 单卡能训练」的根源。
两个容易答错的细节:
- 「混合精度」不规定梯度格式。 梯度改用 FP32 就是每参数 18 bytes,这是数据格式的选择,不是混合精度定义的一部分。
- 峰值不等于各分量之和,而是同一时刻的最大重叠:8 GiB 激活与 4 GiB 收集缓冲同时出现就要 12 GiB;先释放激活再收集参数,同一片空间可以复用。所以容量优化有两条路:减小张量本身,或减少同时驻留的数量 —— 后面的分片、重计算、卸载分别从这两条路下手。
精度与数值风险(这张表能答出「为什么需要 FP32 主权重」):
| 格式 | 矩阵运算权重(含 scale) | Qwen3-8B 读取量 | 缩放管理 | 主要风险 |
|---|---|---|---|---|
| FP16 | 2 bytes | 16.4 GB | 全局损失缩放(因子 8–32K) | 梯度下溢、缩放溢出 |
| BF16 | 2 bytes | 16.4 GB | 不需要 | 尾数短,靠 FP32 累加器补偿 |
| FP8(E4M3)操作数副本 | 约 1.0002 bytes | 约 8.2 GB | 分块缩放 + 定期高精度累加 | 块内舍入、scale 过期 |
- FP16 为什么必须配 FP32 主权重:它只有 5 位指数,最小正规数 ,小于 直接归零。混合精度训练论文实测:语音识别模型的权重梯度约 5% 的值指数小于 −24,会变成零。
- BF16 为什么不用损失缩放:8 位指数与 FP32 相同,表示范围一致,代价是尾数只有 7 位。
- FP8 的关键限定:它改变的是送入矩阵单元的那份权重副本(8.2 GB vs 16.4 GB),主权重、梯度、优化器状态仍以高精度保存 —— 上面 16 bytes/参数 的常驻状态不会降到 1 byte。DeepSeek-V3 的做法是激活按 块、权重按 块求 scale,矩阵单元每累加 128 个元素就转 FP32,与 BF16 对照训练的相对损失误差低于 0.25%。
训练偏离的表现形式是损失尖峰(loss spike,起因可能是缩放失效、数据异常或硬件错误)。处理方式是回滚到上一份 checkpoint 重训 —— 于是「训练稳定性」这个问题最终变成了保存周期问题,代价由下面的 checkpoint 模型给出。这条链路(数值 → 尖峰 → 回滚 → 保存周期)是面试里很好用的一段因果。
2. 三个旋钮:分片、重计算、卸载#
2.1 状态分片(ZeRO / FSDP)#
设 DP 组有 张卡,每卡常驻训练状态:
| 配置 | 每卡常驻状态() | 仍完整复制的部分 |
|---|---|---|
| 普通 DP | 122.1 GiB | 权重、梯度、优化器状态 |
| ZeRO-1 | 42.0 GiB | 权重、梯度 |
| ZeRO-2 | 28.6 GiB | 权重 |
| ZeRO-3 | 15.3 GiB | 全部已分片 |
执行路径:每个模块先 AllGather 取回完整参数 → 前向/反向 → ReduceScatter 汇总梯度并分片 → 各自更新自己负责的参数。
⚠️ 最大的坑:分片数翻倍,显存峰值并不减半。 分片只缩小常驻的那部分;执行时完整权重缓冲区与原有分片同时存在,而完整缓冲区的大小由模块本身决定,与卡数无关。FSDP2 的 CPU 小实验直接量到了:进程从 2 增到 4,常驻状态 18 → 9 MiB(减半),但执行峰值只从 39 → 30 MiB(减 23%),因为执行中还有约 21 MiB 的其他张量与缓冲区。所以「加卡就能装下」这句话要靠峰值算,不能靠常驻状态算。
2.2 激活重计算#
原理:反向要算 ,需要前向输入 。保留 就要让它从前向一直驻留到反向用完;释放 则要在反向需要前重算。
一个具体算例:Qwen3-8B 的 MLP 中,门控结果 与上投影 相乘得 ,下投影反向需要 。若已为非线性算子反向保留了 ,就可以在下投影反向前重新相乘得到 ,不必一直保留它:
- 的形状 、FP32 → 6 MiB,重建约需 157 万次乘法;
- 另两个归一化加权输出各 、各 2 MiB 也可重建;
- 每层省 MiB,九层流水阶段省 90 MiB(约 94 MB);该阶段从 135 MiB 降到 45 MiB。
关键在生命周期:重建只需一块 6 MiB 工作区,逐层复用;而等待反向的 micro-batch 越多,长期保存的数据越多(四个 micro-batch 同时等待时省 MiB)。所以重计算与流水调度是同一件事的两面 —— 反向开始得越早,需要保存的激活越少。
2.3 卸载:把显存问题换成传输问题#
一份状态大小 、链路带宽 、从可开始传输到算子需要它有 秒:
一个很好用的判据算例:梯度该在 CPU 还是 GPU 上转换格式? 门控投影梯度 ,BF16 为 MiB,FP32 为 192 MiB。两条路径:
RTX 4090 经 PCIe 4.0 x16(32 GB/s):CPU 路径约 ms,GPU 路径约 ms —— GPU 转换更快,却更慢整体,因为要多传 96 MiB。求两者相等:
147 GB/s 高于 PCIe 5.0 x16 的每方向 64 GB/s,所以经 PCIe 连接的卡都该「先传 BF16、在 CPU 上转」。 换成 GH200 的 NVLink-C2C(450 GB/s),多传 96 MiB 只多约 0.22 ms,GPU 转换才划算。这就是「转换速度 vs 传输量 vs 缓冲区」的三方权衡(GPU 转换时输入输出共存,峰值 288 MiB,还多要 192 MiB 缓冲)。
2.4 三种办法放在一起怎么选#
| 方法 | 减少什么 | 增加什么 | 收益取决于 |
|---|---|---|---|
| 状态分片 | 重复保存的权重/梯度/优化器状态 | 参数收集、梯度归约并分片 | 收集能否赶在模块执行前完成 |
| 激活重计算 | 前向到反向之间保存的中间值 | 重建计算 | 重建是否延迟关键路径上的反向 |
| 状态卸载 | 加速器上暂时不用的状态 | 主机↔加速器传输 | 数据能否在使用前传回 |
一个可解的取舍:RTX 4090 每卡可用 22 GiB,Qwen3-8B ZeRO-3 八卡每卡 15.3 GiB,若激活与缓冲区同时要 10 GiB → 总计 25.3 GiB,超 3.3 GiB。两条路:用重计算省下这 3.3 GiB,或者加到十六卡把常驻降到 7.6 GiB(总计 17.6 GiB)。前者增加计算,后者增加卡数并改变通信组 —— 先按容量筛出可行方案,再比每步耗时。
3. 每步时间:流水线调度与通信重叠#
3.1 气泡#
个平衡阶段、每阶段前向 、反向 、 个 micro-batch,填满排空(fill–drain)需要
时 。 项是真实工作, 项是填充与排空的浪费。
3.2 五种调度的同一算例对照(这张表是本篇最值钱的一页)#
条件统一:Qwen3-8B 的 36 层分四个九层阶段、8 个 micro-batch、每阶段前向 10 ms、反向 20 ms、边界传输 1 ms、参数更新 1 ms。
| 调度 | 完成时间 | 每卡空闲 | 阶段 0 激活峰值 | 用什么换气泡 | 主要代价 |
|---|---|---|---|---|---|
| 填满排空 | 337 ms | 96 ms | 1,840 MiB | —(不压气泡) | 激活驻留最高,容量紧时跑不了 |
| 1F1B | 347 ms | 106 ms | 921 MiB | 无(气泡相同) | 比填满排空慢约 3% |
| 交错式 1F1B() | 298 ms | 57 ms | 1,329 MiB | 每卡层块拆成 段 | 前向消息 24 → 56 次 |
| 零气泡 ZB-H1 | 283 ms | 42 ms | 921(阶段 3 达 1,226) | 延后填进空隙 | 靠后阶段的激活要留到 执行 |
| DualPipe | 306 ms | 65 ms | 1,228(阶段 1、2 达 1,612) | micro-batch 从两端相向流动 | 每卡参数两份 |
这张表最该记住的不是哪个最快,而是「没有一种在两轴上同时占优」:完成时间最短的是零气泡(283 ms),最大单阶段峰值最低的却是 1F1B(921 MiB)。
反直觉一:1F1B 在时间上更慢,只在显存上赢。 从 346 ms 变 347 ms(约 +3%),但激活与收发缓冲峰值从 2.57 GB 降到 0.97 GB(−62%)。所以「1F1B 优于填满排空」只在显存这根轴上成立。若只给中间结果留 1 GB,只有提前反向的调度能跑完这一步;容量充裕时填满排空反而更早完成。显存驻留往往不是快慢问题,而是能不能跑的问题。
压气泡的三种思路(同一算例):
- 交错式把每卡的层块拆成 段,气泡比例从 降到 :347 → 298 ms,每卡空闲 106 → 57 ms。代价是每个 micro-batch 多穿 4 条边界,全步前向消息 24 → 56 次。
- 零气泡把反向拆成输入梯度 (在关键路径上,要尽早算)和权重梯度 (只进本层累积,可延后填空隙):1F1B 气泡 ,ZB-H1 降到 ,ZB-H2 再降到 。本例 时 ZB-H2 的气泡下界是 0。代价落在靠后阶段(阶段 3 的峰值 308 → 约 1,226 MiB)。
- DualPipe 让 micro-batch 从流水线两端相向注入,气泡 ;代价是每卡保存两份参数。
越大,压气泡越不值。 16 个 micro-batch 时,1F1B 的气泡占比已从 37.5% 降到 18.8%,而交错式增加的通信次数、零气泡增加的激活驻留、DualPipe 增加的参数量都不随 缩小。
3.3 通信重叠:桶大小与提前发送#
反向逐层产生梯度,实现上把多个张量合成通信桶再发。桶越大越可能等最后生成的梯度;桶越小启动次数越多。
反直觉二:通信处理时间更短,训练步不一定更短。 一个具体算例:72 MiB 的 FP32 专家梯度环形 AllReduce,整桶约 4.55 ms,放不进一个 2 ms 的空闲时段 → 这段通信落到计算之后,延长训练步。切成三个 24 MiB 子桶后,每桶约 1.53 ms,总处理时间反而增加到 4.59 ms,但每桶都能在计算结束前传完,所以训练步更短了。决定训练步的是通信何时完成,不是通信花了多久。 (换 400 Gbit/s 网卡整桶仍需 2.28 ms,放不进 2 ms 空隙,切桶依然必要 —— 说明这不是「带宽不够」的问题。)
能藏住的通信有多少? ZeRO-3 每个 micro-batch 三次集合通信:前向前一遍 AllGather、反向前再一遍、反向后 ReduceScatter。每卡收发 ,48 卡时约 16.0 GB,一步 GB。逐层看,收集一层约 0.39 GB 只要约 12 ms,远短于这一层的计算,所以大部分能落在计算里。真正藏不住的只剩第一步的 AllGather 和最后一步的 ReduceScatter —— 它们都作用于约 1.24 GB 的词嵌入(前向第一层、反向最后一层),合计约 0.08 s。
这条给优化划了上限:暴露的通信只有 0.08 s,即使完全消除也只省 0.08 s。若还差 0.5 s 才能达标,就必须同时缩短别的关键路径工作。
扩展效率的实测参照(MegaScale):175B 模型保持全局 batch 6144,卡数 3072 → 12288,每步 23.7 s → 6.3 s,总加速 3.7×,扩展效率约 93%(理想 4× 应是 5.9 s)。差的那 0.4 s 来自跨组同步与负载不均 —— 卡越多,等待最慢一组的时间占比越大,这是扩展本身带来的工作。
4. MoE 与长上下文带来的调度变化#
① 容量因子(capacity factor)。 路由不均时,每个专家的输入矩阵行数上限是
超出的 dispatch 被丢弃:这些 token 该层不处理,表示经残差直接传给下一层;容量没用满的槽位补零,仍然占计算和通信。Qwen3-235B-A22B(、、8,192 token、一半专家 1.5 倍热):
| 容量因子 | 每专家容量 | 丢弃的 dispatch | 补零行占执行量 |
|---|---|---|---|
| 1.0 | 512 | 25% | 25% |
| 1.25 | 640 | 12.5% | 30% |
| 1.5 | 768 | 0 | 33% |
| 2.0 | 1,024 | 0 | 50% |
这是一个没有免费选项的旋钮: 小则丢 token(改变了模型看到的信息), 大则一半的计算花在补零上。路由越均衡,需要的 越接近 1 —— 这就是辅助损失和无辅助损失动态偏置(DeepSeek-V3)在做的事。
② 相同 token 总数,序列长度分布会改变注意力计算量。 因果注意力下长度 的序列有 个配对:两条 4096 合计约 1,680 万对;同样 8192 个 token 改成 7168 + 1024,配对数增至约 2,620 万,增加约 56%。长三角形的增加面积超过短三角形的减少面积 —— 这部分是真实注意力关系,删填充 token 消不掉。所以打包(减少无效填充)、按长度分组(让各卡承担的面积接近)、上下文并行(把长序列分到多卡)三者解决的是不同的问题。
5. checkpoint 与故障恢复:训练系统的「长期账」#
5.1 什么才算可恢复状态#
只有权重是不够的 —— 权重能推理,但不足以确定下一次更新。checkpoint 要保存与同一训练进度对应的全部状态:权重、一阶矩、二阶矩、步数、学习率状态、随机状态、下一批数据的组成,以及打包器里剩余的 token。
一个具体的坑:打包器保留了 2,000 个 token,下一份数据给 6,192 个,两者拼成下一条 8,192 的序列。丢掉这 2,000 个 token,就只能从后续数据里多取补齐 —— 改变了这条序列的前缀、注意力关系和标签。 与「batch 位置」相比,这一项最容易被漏掉。 同理还有数据预取与训练进度的错位:加载器已经把任务派到第 108 个 batch,训练只完成第 100 个 —— 恢复时若直接从第 109 个开始,就跳过了八个 batch。
每参数要存的是权重 2 + 主权重 4 + 两份 Adam 状态 8 = 14 bytes,Qwen3-8B 的 checkpoint 约 115 GB。
恢复时可能要改并行布局:TP4 → TP8 的重分片按全局行坐标做( 的权重四分每片 3072 行、八分每片 1536 行;目标 rank 读旧分片 ,偶取前半、奇取后半)。该矩阵在 checkpoint 里的全部状态是 MiB。权重的内容与顺序不变,变的只是各卡负责的行范围。
5.2 同步 vs 异步保存:提交(commit)才算可用#
- 同步保存:先生成内容固定的快照,写完再继续训练 —— 前台停顿 = 写完整份的时间。
- 异步保存:快照复制到独立缓冲后训练就恢复,后台再写。但训练恢复执行时快照可能还没写完 —— 只有写入并提交完成后,这份 checkpoint 才能用于恢复。
反直觉三:异步保存的调用返回 ≠ 已有进度可恢复。 一个算例:每份 112 GB,存储写入 7 GB/s(一份 16 s)。每 20 s 捕获一份、各花 0.5 s 复制,则两份分别在 36.5 s、56.5 s 提交。第 50 s 故障时只能恢复到第 20 s,重做 30 s。 换 20 GB/s 的存储,两份在 26.1、46.1 s 提交,同一故障可恢复到第 40 s,只重做 10 s。 前台暂停都是 1 秒,重做量却是 30 s vs 10 s —— 差别全在后台写入的完成时刻。 另外要注意:数据文件之外还有元数据提交(实测保存 API 约 7 ms 返回,恢复元数据约 48 ms 才提交;提交前进程终止,恢复程序会选上一份完整的 checkpoint)。
5.3 最优保存间隔:#
设每次保存耗时 、保存之间完成 秒有用训练、作业故障率 、恢复耗时 ,单位有用训练时间的附加成本:
(第一项是保存频率的代价,第二项是故障平均落在间隔中点、丢半个间隔,第三项是恢复次数 × 恢复时长。两项一减一增,所以有最优点。)
实测输入:Meta 统计的研究集群,1024 卡作业平均 7.9 小时中断一次,中断率与卡数成正比(≈每卡 337 天一次故障);任一卡故障即中断整个作业。 s(115 GB @ 7 GB/s)、 s → s,约 16 分钟。
| 有用训练间隔 | 保存成本 | 重做成本 | 恢复成本 | 合计 |
|---|---|---|---|---|
| 300 s | 5.5% | 0.5% | 0.4% | 6.4% |
| 900 s | 1.8% | 1.6% | 0.4% | 3.8% |
| 1800 s | 0.9% | 3.2% | 0.4% | 4.5% |
最低点比较平缓,可以选附近方便的间隔。 两个可导出的推论:卡数翻倍 → 翻倍 → 缩短为 ;保存速度翻倍 → 减半 → 同样缩短 。
损失尖峰要走同一个模型。 尖峰不损坏硬件,但处理方式相同(丢弃参数、回到快照),于是
翻转条件由两个发生率的相对大小给出:尖峰越频繁最优周期越短; 时保存周期几乎只由数值稳定性决定,而不是硬件可靠性。
5.4 掉队者:步时间由最大值决定,不是均值#
同步数据并行每步要等最慢的卡,步时间是 个样本的最大值。 个独立正态样本最大值的期望约为 加若干倍 :
| 卡数 | (倍 ) | 每步() | 每步() |
|---|---|---|---|
| 8 | 1.42 | 54.3 s | 56.5 s |
| 48 | 2.23 | 55.1 s | 58.6 s |
| 1024 | 3.25 | 56.2 s | 61.3 s |
无波动时每步约 52.8 s。 卡越多,最大值的期望越大:48 卡在 时每步多约 5.8 s,吃掉本方案 14.4 s 余量的四成。慢卡可以从通信等待里检测出来:一张卡在梯度桶 AllReduce 上等的时间 = 步结束时刻 − 自己算完的时刻。
三种响应,各有代价(这段最容易被追问):
| 响应 | 做法 | 代价 |
|---|---|---|
| 等待 | 本步按慢卡结束 | 一张 的卡: 时 8 卡多等约 1.72 s,48 卡多等约 0.81 s,1024 卡时其余卡的最大值本身已超过 ,多等为零 |
| 重分配 | 把慢卡的活摊给其余 张 | 均值变 :48 卡约 56.2 s、8 卡约 61.6 s,都高于同一 下等待的期望(55.1 / 54.3 s) —— 摊派让每卡多做 ,卡越少越不划算 |
| 驱逐 | 移出作业、从上一个 checkpoint 重启 | : s、 s 时约 420 s ≈ 八步。一次 抖动只损失几秒 —— 只有慢卡持续多步时驱逐才值得 |
真实世界的规模感(这几个数很有说服力):Meta 集群上 1024 卡作业平均无故障 7.9 小时,8 卡作业 47.7 天;MegaScale 报告约 0.5% 的机器明显变慢。
中断到底值多少钱(MiMo-V2.6 的公开看板):Pro 与 Flash 的 RL 后训练分别约 260 万和 90 万美元(每小时约 2.06 万和 1.03 万美元)。Pro 共重启 14 次,中断区间累计约 30.1 h,占总运行时间 23.6%,折合约 61.9 万美元;其中一次 infra 错误未被及时检出,直到完成第 17 步后才从第 15 步重训,第 16、17 步的约 4 h 随之作废。重启原因主要是三类:硬件(显存双比特错误)、服务(容器崩溃、评分服务网络不通)、内存不足(推理时 KV 耗尽、训练时专家负载不均导致显存溢出、打包时主机内存不足)。
一段能讲出判断力的话:把中断总耗时砍一半,同样工作少用约 15 h,按费率省约 31 万美元。 这可以来自两条完全不同的路 —— ① 消除反复触发的故障(MiMo 团队就调整过训练并行方式、降低激活显存以容纳专家负载峰值);② 更早发现、更快恢复,用更近的 checkpoint 减少重做(缩短 或丢掉的间隔)。这两条比「买更快的卡」更常是被忽略的 ROI 来源。
6. RL 训练的系统侧(与 02-post-training/ 互补)#
前三节假定数据已给定。RL 让模型参与产生下一批数据 —— 系统从「处理固定数据的流水」变成反馈循环,新问题集中在三处:各阶段处理速度、切换时的状态重叠、以及样本究竟由哪一版策略产生。
6.1 三阶段流水:扩哪个?#
生成 → 验证 → 学习是首尾相接的三道工序,设三者能力为 、验证后符合策略版本的比例为 :
算例:生成 12 条/s、验证 6 条/s、学习 8 条/s、验证后保留 75% → 实际进学习的是 条/s。把生成翻倍到 24 条/s,进学习仍是 4.5 条/s(验证是瓶颈);把验证翻倍到 12 条/s,进学习到 9 条/s,此时学习端的 8 条/s 成为瓶颈。 所以 RL 训练慢的第一诊断不是「卡不够」,而是先找出当前最慢的那道工序。
6.2 训推一致性:三个策略版本#
- :实际行为分布(采样时真正用的策略,含版本滞后、采样配置、跨引擎差异);
- :本轮优化起点;
- :当前被优化的策略。
右边第一项是本轮参数优化带来的概率变化,第二项是采样分布与起点策略的差异。这两项必须分开,否则训练端会把「计算差异」当成「策略变化」。
一个能把数字背下来的算例:若行为策略与当前策略对该 token 的 logprob 都是 ,比值是 1;若误用重新算出的 logprob()代替行为策略原先记录的值,比值变成 —— 参数没变,样本权重却放大了约 28%。 在 PPO 一类更新里,概率比既决定优势对梯度的权重,也参与裁剪判断 —— 所以误用会同时造成权重错误和错误触发裁剪;而用序列概率比时各位置 logprob 之差会相加,轨迹越长积累的偏差越大。
为什么第二项天然不等于 1:生成端逐 token decode 并读 KV,训练端整段轨迹并行输入、重算概率再反向 —— 不同的注意力实现、归约次序、batch 形状、权重与 KV 精度都会让 logprob 不同(第 5 章实测过:同一行输入按不同段数归约,平方和相差 166 个 ULP,而段数取决于当时的 batch 大小)。采样配置也要存:温度、top-k / top-p 会改变 Softmax 分布,所以应保存变换后的概率及采样配置;训练端要用相同的分词、对话模板、位置编号、掩码、EOS/截断位置重建输入。
MoE 把数值差异放大成路径差异。 专家选择是离散的:top-2 下,专家分数 0.500 / 0.301 / 0.300 选专家 1、2;第三个分数因计算次序变成 0.302,就改选 1、3 —— 极小的分数变化换了另一个专家的权重矩阵,影响沿后续层继续传播。解法是路由重放(Routing Replay):记录生成时选中的逻辑专家 ID,训练时按这些 ID 选专家,离散路径重放、数值用当前权重算。记录成本很小(Qwen3-30B-A3B 48 层 top-8、8192 token、uint16 → ),但记录要跟着 token 走(序列打包改变位置、上下文切分改变卡、重计算要再读同一层)。NVIDIA 的 R3 验证报告四组开关各训 100 步:开启后对数概率误差中位数均下降,每步总耗时中位数略长,训练奖励没有一致提高 —— 减少的是不一致,不是直接买来奖励。
6.3 异步训练:盈亏平衡点是丢弃率#
同步循环的周期是「生成 + 学习 + 权重同步」。异步让生成下一批与学习上一批重叠:一个具体例子,生成 40 s、学习 16 s、同步 4 s,同步周期 60 s;异步稳态周期 。
但生成得更早意味着样本可能来自较旧的权重。 设每批 条等效轨迹、异步后保留比例 ,则有效吞吐从 变成 ,异步更快要求
时有效样本吞吐提高约 9%; 时虽然每批更早结束,有效吞吐反而减少约 5%。 —— 异步不是默认更优,它有一个明确的盈亏平衡点。
长轨迹还要考虑恢复:生成期间的持续 的轨迹能完整生成的概率是 ,轨迹越长越容易被中断丢掉,于是进学习的数据比例下降、并产生长度偏移(长轨迹被系统性丢弃)。做法是逐 token 记录生成进度和策略版本,恢复后继续生成同一条轨迹。注意 KV 是「给定权重对前缀的执行结果」:相同权重可以续用已保存的 KV,换权重就必须重新 prefill —— Qwen3-8B 的 8K BF16 KV 是 1.125 GiB,所以恢复方案要在取回时间与重建时间之间比。
7. 把账合起来:一阶完成时间模型#
( 是每步训练时间,已含单卡计算、通信等待与输入等待; 是保存与恢复的附加比例; 是计划性停顿。)章首任务(Qwen3-8B 全参、100B token、8,192 序列长、30 天期限、预留 5 天):
| 设计项 | 32 卡方案 | 48 卡方案 |
|---|---|---|
| 每卡预计显存占用 / 可用 | 13.8 / 22 GiB | 12.5 / 22 GiB |
| 每步单卡计算 | 78.3 s | 52.2 s |
| 每步 ZeRO-3 链路时间 | 17.9 s | 12.0 s |
| 每步通信等待 | 0.08 s | 0.08 s |
| 每步输入等待 | 0.5 s | 0.5 s |
| 每步训练时间 | 78.9 s | 52.8 s |
| 保存+重做+恢复附加 | 1.02% | 1.08% |
| 最终完成时间(含 5 天预留) | 34.3 天 | 24.6 天 |
结论:选 48 卡。 两者容量都够;32 卡超过 30 天期限被排除;48 卡约 24.6 天,余约 5.4 天。增加卡数的主要价值是减少每卡承担的工作,额外故障成本只抵消很小一部分收益(附加比例从 1.02% 到 1.08%,只差 0.06 个百分点)。
余量怎么用(这是设计题真正的答案)。 48 卡每步上限 s,本方案 52.8 s,余量约 14.4 s/步。固定单卡计算 52.2 s、输入等待 0.5 s,则总通信等待最多可到约 14.5 s,而实际只有 0.08 s —— 即使预取完全失效、12.0 s 链路时间全部暴露,每步约 64.8 s,仍在上限内。
换硬件用 Amdahl 判:
( 是该资源占原每步耗时的比例, 是能力倍数。)本例暴露通信只占每步 0.14% —— PCIe 带宽减半,每步从 52.8 s 增到 52.9 s,几乎不变。反过来,单卡计算效率从 40% 降到 30%,单卡计算变 69.6 s、每步约 70.2 s,直接超过 67.2 s 的目标。
所以对这套方案,决定能否按期完成的是单卡计算效率,不是带宽。 带宽只有在预取失效、通信整段暴露时才变成 较大的那一项。「更强的单项指标是否值得买,取决于它能减少多少完成时间或卡数」 —— 这就是 Amdahl 在采购决策上的用法。
最后一道外推:稠密模型粗略算量 ,固定 T token、40% MFU、期限 ,则
对 1T 参数模型、90 天期限、16,384 张卡:A100 / H100 / B200 在 40% MFU 下分别约需 679 / 214 / 94 天 —— 三者都超期(B200 也超约 4 天,需增至约 17,147 张)。只有 MFU 达到 50%,B200 才降到约 75 天,余下 15 天可分配给停顿与恢复。MFU 差 10 个百分点,就决定了 16,384 张 B200 能否在 90 天内训完 1T。
注意固定数据量时的尺度:参数量增至五倍 → 计算量增至五倍;若同时取 ,则 ,参数量增至五倍,计算量增至 25 倍。规模问题的答案由模型和数据共同决定。
常见面试问法#
Q:训练一个 8B 模型要多少显存?为什么单卡能推理不能训练? A:常驻训练状态每参数 16 bytes —— BF16 权重 2 + BF16 梯度 2 + FP32 主权重 4 + Adam 一阶矩 4 + 二阶矩 4。8.19B 参数 → 131.1 GB,约等于八份 BF16 权重。推理只要 16.4 GB,所以能推理的卡远不够训练。要补两点:① 「混合精度」不规定梯度格式 —— 梯度改 FP32 就是 18 bytes/参数;② 峰值不等于各项之和,而是同一时刻的最大重叠 ,8 GiB 激活与 4 GiB 收集缓冲同时出现要 12 GiB,先释放激活再收集参数就能复用同一片空间。
Q:ZeRO 的三个阶段各分片什么?加卡能把显存降下来吗? A:、、、; 时每卡 122.1 / 42.0 / 28.6 / 15.3 GiB。ZeRO-1 分 FP32 主权重与两份 Adam 状态(12 bytes/参数),ZeRO-2 再分梯度(只剩 BF16 权重完整复制),ZeRO-3 连权重也分。执行是 AllGather 取参数 → 前向/反向 → ReduceScatter 分梯度 → 各更各的。 但要提醒一个坑:分片数翻倍,显存峰值并不减半。 分片只缩小常驻部分;执行时完整权重缓冲区与原有分片同时存在,而缓冲区大小由模块本身决定、与卡数无关。FSDP2 的小实验量到:进程 2→4,常驻 18→9 MiB(减半),峰值只从 39→30 MiB(减 23%),因为执行中另有约 21 MiB 其他张量。所以「加卡能不能装下」必须按峰值算。
Q:显存不够,你会先加卡、加重计算,还是卸载? A:先按容量筛可行方案,再比每步耗时 —— 三种办法减少的东西不同(分片减少重复保存的状态、重计算减少前向到反向之间保存的中间值、卸载把暂时不用的状态挪到主机内存),增加的工作也不同(收集/归约、重建计算、传输)。具体算例:RTX 4090 每卡可用 22 GiB,ZeRO-3 八卡每卡 15.3 GiB,若激活与缓冲区同要 10 GiB 就超 3.3 GiB —— 可以用重计算省这 3.3 GiB,或加到十六卡把常驻降到 7.6 GiB,前者增计算、后者增卡数并改通信组。 重计算的收益取决于生命周期:Qwen3-8B 的 MLP 里重建 每层省 10 MiB(九层阶段 135 → 45 MiB),因为重建只需一块 6 MiB 工作区逐层复用,而保留它要每个等待反向的 micro-batch 各留一份(四个并行等待就省 360 MiB)——所以重计算和流水调度是同一件事的两面。 卸载的判据是 ,一个漂亮的例子:梯度该在 CPU 还是 GPU 转 FP32?临界带宽 147 GB/s,高于 PCIe 5.0 x16 的 64 GB/s,所以经 PCIe 的卡都该先传 BF16、在 CPU 上转;只有 GH200 那种 NVLink-C2C(450 GB/s)才轮到 GPU 转换赢。
Q:流水线并行的气泡怎么算?1F1B 是不是一定比填满排空好? A:填满排空气泡是 ,利用率 ( 时约 72.7%)。但「1F1B 更好」只在一根轴上成立 —— 同一算例中填满排空 337 ms、1F1B 347 ms(慢约 3%),因为交错引入依赖等待;而 1F1B 的激活与收发缓冲峰值从 2.57 GB 降到 0.97 GB(−62%)。 所以先确定约束在时间还是容量:只给 1 GB 中间结果时只有提前反向的调度能跑;容量充裕时 337 ms 的填满排空反而更早完成。压气泡的三种手段各有代价:交错式 1F1B 298 ms(前向消息 24→56 次)、零气泡 ZB-H1 283 ms(把 延后填空隙,靠后阶段激活峰值升到约 1,226 MiB)、DualPipe 306 ms(每卡参数两份)。没有任何一种在两轴上同时占优:时间最短的是零气泡,最大单阶段峰值最低的是 1F1B。而且 越大压气泡越不值(16 个 micro-batch 时 1F1B 气泡占比已从 37.5% 降到 18.8%)。
Q:通信是不是训练的主要瓶颈? A:要看暴露了多少,而不是链路时间有多长。 通信大多能被计算盖住:ZeRO-3 逐层预取参数、反向一结束就归约梯度,一层 0.39 GB 只要约 12 ms,远短于该层计算。本例一步链路时间 12.0 s,但真正藏不住的只剩第一步 AllGather 和最后一步 ReduceScatter,合计约 0.08 s(都作用于 1.24 GB 的词嵌入)。 这给优化划了上限:暴露只有 0.08 s,消除它最多省 0.08 s,若还差 0.5 s 就得动别处。还有个反直觉的判据:通信处理时间更短,训练步不一定更短 —— 72 MiB 整桶 AllReduce 约 4.55 ms 放不进 2 ms 空隙,切成三个子桶总时间反而升到 4.59 ms,但每桶都能在计算结束前传完,所以训练步更短。决定训练步的是通信何时完成,不是它花了多久。
Q:checkpoint 该多久存一次? A:( 是每次保存耗时、 是故障率)。实测输入:Meta 集群 1024 卡作业平均 7.9 小时中断一次,中断率与卡数成正比(≈每卡 337 天一次);115 GB checkpoint 按 7 GB/s 保存 s;恢复 s → s,约 16 分钟。三档对照:300 s 合计 6.4%、900 s 合计 3.8%、1800 s 合计 4.5% —— 最低点很平缓,可以选附近好用的间隔。 两个可导出的推论:卡数翻倍( 翻倍)→ 最优间隔缩短为 ;保存速度翻倍( 减半)→ 同样缩短 。 还要补三点:① 损失尖峰要走同一个模型, 换成 —— 尖峰越频繁,保存周期越短, 时保存周期几乎只由数值稳定性决定;② 恢复点由「提交」决定,不是由保存调用返回决定 —— 同一 1 秒前台暂停可以对应重做 30 s 或 10 s,差别全在后台写入何时完成;③ checkpoint 不只有权重 —— 还要步数、学习率状态、随机状态、下一批数据组成,以及打包器里剩余的 token(丢了它就用后续数据补齐,改变了序列前缀、注意力关系和标签)。
Q:训练时某张卡一直慢,你怎么处理? A:先意识到步时间由最大值决定,不是均值。 张卡时步时间的计算部分是 个样本的最大值: 时 约为 倍 。、48 卡时每步多约 5.8 s,吃掉本方案 14.4 s 余量的四成。慢卡可以从通信等待里检出来:一张卡在梯度桶 AllReduce 上等的时间 = 步结束时刻 − 自己算完的时刻。 三种响应各有代价,而且结论反直觉:① 等待 —— 一张 的卡, 时 8 卡多等约 1.72 s、48 卡约 0.81 s,1024 卡时其余卡的最大值本身已超过它,多等为零;② 重分配 —— 把活摊给其余 张,48 卡约 56.2 s、8 卡约 61.6 s,都高于等待(55.1 / 54.3 s),因为每卡多做 的增量超过了一张慢卡的等待,卡越少越不划算;③ 驱逐 —— 从上一个 checkpoint 重启,代价约 (600 s 间隔 + 120 s 恢复 ≈ 420 s ≈ 八步),一次 的抖动只损失几秒,只有慢卡持续多步才值得驱逐。
Q:RL 训练慢,是不是该加生成资源? A:先找出最慢的那道工序。 生成 → 验证 → 学习是首尾相接的三道工序:。生成 12 条/s、验证 6 条/s、学习 8 条/s、验证后保留 75% → 进学习只有 4.5 条/s;生成翻倍到 24 条/s 仍是 4.5 条/s,验证翻倍才把瓶颈推到学习端。 RL 还有两个纯系统侧的问题:① 训推一致性 —— 三个策略版本 ,概率比要分解成 ;误用重算的 logprob 代替行为策略记录的值,比值会从 1 变成约 1.28,样本权重放大 28%,在 PPO 里还会错误触发裁剪。② 异步有盈亏平衡点 —— 生成 40 s、学习 16 s、同步 4 s 时同步周期 60 s、异步 44 s,但 异步才划算( 时有效吞吐反而降约 5%)。
易错点#
| 易错说法 | 问题 | 应该说 |
|---|---|---|
| 「分片数翻倍,显存峰值就减半」 | 只看了常驻状态 | 分片只缩小常驻部分;执行时完整权重缓冲区与分片并存。FSDP2 小实验:常驻 18→9 MiB(减半),峰值只 39→30 MiB(−23%) |
| 「8B 训练要 131 GB,那 16 张 80G 卡就够」 | 只算了常驻状态 | 还要算 ,以及通信组与拓扑带来的约束 |
| 「混合精度训练一定用 FP16 梯度」 | 把「混合精度」当成规定 | 「混合精度」不规定梯度格式;本例梯度是 BF16,改 FP32 就是 18 bytes/参数 |
| 「FP8 训练能把状态降到 1 byte/参数」 | 混淆了「操作数副本」与「常驻状态」 | FP8 只改送入矩阵单元的权重副本(16.4 → 约 8.2 GB);主权重、梯度、优化器状态仍高精度保存 |
| 「1F1B 比填满排空好」 | 只看了一根轴 | 1F1B 时间上慢约 3%(347 vs 337 ms),只在显存轴上占优(2.57 → 0.97 GB)。先确定约束在时间还是容量 |
| 「零气泡调度全面最优」 | 忽略了激活驻留 | 零气泡完成时间最短(283 ms),但靠后阶段的激活峰值升到约 1,226 MiB;最大单阶段峰值最低的是 1F1B |
| 「通信更快 → 训练步更短」 | 把「处理时间」当成「完成时刻」 | 三个小桶总时间 4.59 ms > 整桶 4.55 ms,但训练步更短 —— 决定训练步的是通信何时完成 |
| 「链路时间是通信瓶颈」 | 忽略了重叠 | 一步链路 12.0 s,真正暴露的只有 0.08 s(首尾两次词嵌入通信)。优化上限就是这 0.08 s |
| 「异步保存的 API 返回了,进度就保住了」 | 漏了「提交」 | 只有写入并提交完成后 checkpoint 才可用。同一 1 秒前台暂停,可对应重做 30 s 或 10 s |
| 「checkpoint 存权重就够了」 | 漏了优化器状态与数据位置 | 还要一阶/二阶矩、步数、学习率状态、随机状态、下一批数据组成,以及打包器里剩余的 token(丢了会改变序列前缀与标签) |
| 「保存间隔越短越安全」 | 忽略了保存成本也有上限 | :300 s 总附加 6.4%、900 s 3.8%、1800 s 4.5% —— 两边都贵,中间最省 |
| 「卡数翻倍、batch 也跟着翻倍,完成时间就减半」 | 撞上临界 batch size | 超过 后步数不再明显下降:batch 从 315 万放大到约一亿(1536 卡),时间只从 19.4 天降到 12.1 天,上限 1.64×。只有保持 batch 不变的强扩展不受此限 |
| 「慢卡就把它踢掉重来」 | 没算驱逐成本 | 驱逐代价 (600 s + 120 s ≈ 八步),一次 抖动只损失几秒;而重分配在卡少时反而比等待更贵(8 卡 61.6 s vs 等待 54.3 s) |
| 「RL 训练慢就加生成资源」 | 搞错了工序 | —— 先找最慢的那道工序;生成翻倍常常毫无收益 |
| 「异步 RL 一定比同步快」 | 漏了过期样本 | 有明确盈亏平衡点:同步 60 s / 异步 44 s 时需 , 反而慢约 5% |
| 「MoE 容量因子取大一点就不会丢 token」 | 忽略了补零成本 | 丢 25% 的 dispatch; 不丢但补零占执行量 50%。这是一个没有免费选项的旋钮 |
| 把本章的 48 卡方案说成「我们线上就是这么训的」 | 触碰仓库硬规矩 | 这是书里的设计算例;你的真实 RL 经验是 HKJC 的单轮 RLVR、小规模,两者不是一回事,要自己先说这条边界 |
自测#
1. 有人问你「训一个 8B 模型,单卡 80G 够不够」。请给出完整的容量分析,并说明为什么「常驻状态能放下」不等于「能训练」。
答案
① 先算常驻训练状态:混合精度 Adam 下每参数 16 bytes —— BF16 权重 2 + BF16 梯度 2 + FP32 主权重 4 + Adam 一阶矩 4 + 二阶矩 4。Qwen3-8B(8.19B 参数):
一张 80 GB 卡(约 74.5 GiB)连常驻状态都放不下,所以「单卡 80G」直接不够。
② 但真正的答案是「要按峰值算,不是按常驻算」:
同一时刻驻留的还有激活与临时缓冲区(参数收集缓冲、重计算工作区等)。关键在「同一时刻」:8 GiB 激活与 4 GiB 收集缓冲同时出现就要 12 GiB;先释放激活再收集参数,同一片空间可以复用。所以容量优化有两类手段 —— 减小张量(精度、分片)或减少同时驻留的数量(调度、重计算、卸载)。
③ 还要看分片以后是不是真的够了: 时 ZeRO-3 每卡 GiB,看似宽裕;但执行时要收集完整权重,完整权重缓冲区与原有分片同时存在,而缓冲区大小由模块决定、与卡数无关。FSDP2 的小实验:进程 2→4,常驻 18→9 MiB(减半),峰值只从 39→30 MiB(减 23%)。所以「加卡就能装下」这句话必须按峰值验证。
④ 最后一层:显存够只是能不能开始;还有通信组与拓扑的约束(卡间有没有 NVLink/P2P 会决定集合通信走哪条路),以及算不算是按期跑完 —— 那要另算每步耗时。
2. 你的训练任务显存不够,缺约 3.3 GiB。同事说「加到两倍卡就行」。请给出两种方案并说明各自的代价。
答案
用第 10.2.4 节的算例:RTX 4090 每卡可用 22 GiB,Qwen3-8B ZeRO-3 在八卡上每卡常驻约 15.3 GiB,留给其他张量与缓冲区约 6.7 GiB;若激活与临时缓冲区同时需要 10 GiB,总计约 25.3 GiB,超出约 3.3 GiB。
方案 A:八卡不变,用重计算省下这 3.3 GiB。
- 做法:把「前向产生、反向才用」的中间值改成反向需要前重建。例如 MLP 里重建 ( FP32 = 6 MiB)+ 两个归一化加权输出(各 2 MiB),每层省 10 MiB;九层流水阶段从 135 MiB 降到 45 MiB。
- 关键性质:重建只需一块工作区逐层复用(最大 6 MiB);而保留它要每个等待反向的 micro-batch 各留一份 —— 所以等待反向的 micro-batch 越多,重计算省得越多(四个并行等待就省 MiB)。
- 代价:增加重建计算;只有它落在非关键路径上时才不延长每步时间。
方案 B:加到十六卡,把常驻状态从 15.3 GiB 降到约 7.6 GiB,总计降到约 17.6 GiB。
- 代价:多八张卡;而且分片数改变会改变通信组(AllGather/ReduceScatter 的规模与拓扑变化),要重新验证通信能否被计算盖住。
- 注意:加卡不会把峰值等比降下来 —— 降的是常驻那部分,执行时的完整权重缓冲区大小不变。
正确的决策顺序:先用容量筛出可行方案,再比这些方案的每步耗时。 时间有余量就用重计算省卡;时间紧张就加卡并重新核对通信预算。另外别忘了:如果显存已经足以保存所需张量,就不必再为省显存而增加额外工作 —— 这是第 10.6.2 节调优时的原则。
3. 有人主张「流水线用零气泡调度,因为它完成时间最短」。你会怎么回应?
答案
完成时间最短是对的,但这不是充分理由 —— 流水线调度要在两根轴上同时看。
同一算例(四阶段、8 个 micro-batch、前向 10 ms、反向 20 ms、边界传输 1 ms、参数更新 1 ms):
| 调度 | 完成时间 | 每卡空闲 | 阶段 0 激活峰值 |
|---|---|---|---|
| 填满排空 | 337 ms | 96 ms | 1,840 MiB(阶段 3 达 2,448) |
| 1F1B | 347 ms | 106 ms | 921 MiB |
| 交错式 1F1B | 298 ms | 57 ms | 1,329 MiB |
| 零气泡 ZB-H1 | 283 ms | 42 ms | 921 MiB(阶段 3 达 1,226) |
| DualPipe | 306 ms | 65 ms | 1,228 MiB(阶段 1、2 达 1,612) |
零气泡的机制是把反向拆成两段:(输入梯度)在关键路径上、要尽早算;(权重梯度)只进本层累积,可以延后填进空隙。1F1B 气泡 → ZB-H1 → ZB-H2 (本例 时 ZB-H2 下界为 0)。
代价就在那张表的最后一列:靠后阶段的 比 晚执行,那段激活要按完整一份保留 —— 阶段 3 的峰值从 1F1B 的 308 MiB 升到约 1,226 MiB(约 4 倍)。 所以:
- 完成时间最短的是零气泡,最大单阶段峰值最低的是 1F1B —— 没有任何一种调度在两轴上同时占优;
- 选择的第一步是确定约束在哪边:容量紧张时先按峰值排除不可行的调度,再比时间;容量充裕时零气泡/交错式的收益才拿得到;
- 还要看 :micro-batch 翻倍到 16 时,1F1B 的气泡占比已从 37.5% 降到 18.8%,拆细带来的相对收益在缩小,而交错式增加的通信次数、零气泡增加的激活驻留、DualPipe 增加的参数量都不随 缩小;
- 最后还有链路争用这条边界:交错式每个 micro-batch 多出的四次跨界传输,在链路已被梯度归约占满时会直接延长关键路径。
一句话回应:「零气泡在时间轴上确实最好,但它把成本挪到了靠后阶段的激活驻留上 —— 我会先确认显存约束在哪一侧,再在可行集合里选时间最短的那个。」
4. checkpoint 该多久存一次?请给出模型、一个真实量级的算例,以及你会主动补充的三个细节。
答案
模型:设每次保存耗时 、保存之间完成 秒有用训练、作业故障率 、恢复耗时 ,
三项分别是保存频率的代价、故障平均落在间隔中点导致丢半个间隔、恢复次数 × 恢复时长;前两项一减一增,所以有最优点。
真实量级算例:Meta 统计的研究集群上,1024 卡作业平均 7.9 小时中断一次,且中断率与卡数成正比(≈每卡 337 天一次),任一卡故障即中断整个作业。115 GB 的 checkpoint 以 7 GB/s 保存, s;设 s:
三档对照:300 s 合计附加 6.4%、900 s 合计 3.8%、1800 s 合计 4.5% —— 最低点平缓,可选附近好用的间隔。两个推论:卡数翻倍使 翻倍 → 最优间隔缩短为 ;保存速度翻倍使 减半 → 同样缩短 。
主动补充的三个细节:
① 损失尖峰也回滚,要走同一个模型。 数值不稳定导致的 loss spike 不损坏硬件,但处理方式相同(丢参数、回快照),所以 。翻转条件由两个发生率的相对大小给出:尖峰越频繁最优周期越短; 时保存周期几乎只由数值稳定性决定,与硬件可靠性无关。
② 恢复点由「提交」决定,不是由保存调用返回决定。 异步保存时,快照复制到独立缓冲后训练就恢复,但只有写入并提交完成后这份 checkpoint 才能用于恢复。同一个 1 秒前台暂停,可以对应重做 30 s 或 10 s —— 差别全在后台写入何时完成(112 GB @ 7 GB/s 时第 50 s 故障只能恢复到第 20 s;换 20 GB/s 存储则可恢复到第 40 s)。另外元数据提交也有延迟(实测保存 API 约 7 ms 返回,恢复元数据约 48 ms 才提交;提交前终止进程,恢复程序会选上一份完整 checkpoint)。
③ checkpoint 不只是权重。 还要一阶/二阶矩、步数、学习率状态、随机状态、下一批数据的组成,以及打包器里剩余的 token。特别是最后一项:若打包器留着 2,000 个 token、下一份数据给 6,192 个,丢了这 2,000 就只能用后续数据补齐,从而改变这条序列的前缀、注意力关系和标签。同理还有预取与训练进度的错位(加载器派任务到第 108 个 batch、训练只完成第 100 个,恢复时若从 109 开始就跳过八个 batch)。
5. 一个 48 卡的训练方案,每步预算 67.2 s,实测每步 52.8 s。有人提议把 PCIe 换成更新的接口。你支持吗?还有,如果要在这个任务上省时间,你会先动哪里?
答案
先算清这套方案的时间构成(Qwen3-8B 全参、100B token、8,192 序列长、48 卡):
| 项 | 时间 |
|---|---|
| 每步单卡计算 | 52.2 s |
| 每步 ZeRO-3 链路时间 | 12.0 s |
| 每步实际通信等待(暴露部分) | 0.08 s |
| 每步输入等待 | 0.5 s |
| 每步合计 | 52.8 s |
| 每步上限 | 67.2 s(余量约 14.4 s) |
① 换更快的 PCIe:不支持。 用 Amdahl 形式的判据 ( 是该资源占原每步耗时的比例):暴露的通信只占 0.14%,所以 PCIe 带宽减半时每个 micro-batch 的链路时间从 1.50 s 升到约 3.0 s(仍短于该 micro-batch 6.53 s 的计算),暴露部分翻倍到约 0.15 s,每步从 52.8 只增到 52.9 s,几乎不变。反过来,这项变化的收益也几乎为零 —— 买更快的接口在这套方案上买不到时间。
② 先动哪里:先确认单卡计算效率,再核对网卡配置。
- 单卡计算效率是本方案的真正瓶颈。 计算占 52.2 s / 52.8 s ≈ 99%。若效率从 40% 降到 30%,单卡计算变 69.6 s、每步约 70.2 s,直接超过 67.2 s 上限。所以任何影响 kernel 效率的工作(算子融合、精度格式、并行切法)都直接反映在完成时间上。
- 其次是网卡配置的稳健性(不是速度,是冗余):12.0 s 链路时间的前提是每卡一张 200 Gbit/s 网卡。若一台主机的八张卡共用一张网卡,环形集合通信的割集要承载每卡全部收发,48 卡每步约 385 GB 都走这张 25 GB/s 的卡,链路时间约 15.4 s,超过 14.5 s 的通信上限;预取一旦失效,每步约 68.1 s,方案超期。两种配置的差别是:共用网卡把按期完成押在「重叠一定生效」上,每卡一张则不依赖重叠。
- 最后才是输入等待(0.5 s)与故障恢复附加(1.08%)。
③ 更大的方向:这套方案还有 14.4 s/步 的余量没被用掉。 与其优化已经不构成瓶颈的项,不如把这笔余量换成更少的卡数或更短的基础训练时间 —— 例如回到 32 卡方案就需要把单卡效率从 40% 提到约 47%(已高于 Llama 3 公开报告的最高 43%),这比加两台主机难得多。这也是第 10.6.2 节的原则:先算清预算,再决定是增卡还是提效率,而不是先买硬件。