03|训练系统内部:数据、优化器、显存与分布式代价
目标:读懂训练报告的因果链,能估计资源,能区分优化失败、数据泄漏与目标设计错误。实验:
train_tiny_lm.py,是真实训练,但不是大模型能力复现。
本章目录
沿着对象与状态理解本章
显存账必须分参数、梯度、优化器状态、激活与临时工作区;下图先教训练状态如何产生。
下方图解的固定输入在“输入与适用条件”中声明。它用于解释本章机制,不与本章其他独立例子的数值暗中接续。
训练:给每个位置一道“下一项”题
为什么训练看完整句,生成却只能往前走?
训练时答案放在试卷的评分区,所以各位置的题目可以同时准备;mask负责不让模型读到自己的答案。生成时后续Token还未决定,下一题的前缀依赖本题选择。两者共享因果预测目标,但已知信息不同。
输入与适用条件:标签对齐使用5项序列;单位置交叉熵与PAD平均分别是明确独立的小例,不假称那些概率来自对齐图的模型。
1 / 5 · 把输入和目标错开一格
窄屏可左右滑动图形,或点击“放大图形”。文字解释紧随图后。
完整教学序列为“我/爱/学习/!/EOS”。输入用前四项,目标用后四项。每个输入位置预测的是其后一个真实Token。
输入=[1,2,3,5];目标=[2,3,5,6]默认静止。用“下一步”看完解释再继续;播放到最后一步自动停止。键盘聚焦播放器后,可用左右键逐步查看、空格播放/暂停。图中颜色辅助区分,含义同时用文字注明。
为什么需要
用清晰的预测任务,把参数更新与语言序列关系连接。
怎样实现
正确移动标签、限制可见性、屏蔽无效目标、按有效数归一化。
可能的代价与误解
偷看未来会产生漂亮但虚假的训练成绩;训练样本重复或泄漏也会高估泛化。
如何判断是否做对
用极小固定序列验证每个输入位置和目标位置,再验证PAD不影响有效损失。
1. 数据管线是模型行为的一部分
预训练不是把原始网页直接塞进GPU。需要确定采样范围、清洗与去重策略、编码、序列拼接、长度分布、训练验证划分和可追溯的数据版本。每一步都改变模型实际看到的分布。例如过度删除短行,可能误伤代码;按网页URL去重,可能保留大量镜像;随机按段落划分训练测试,可能把同一文档不同版本分到两侧。
最小数据清单应能回答:样本来自哪一快照、应用了哪些过滤、由何种Tokenizer编码、有效Token计数如何计算、验证集是否在去重前隔离。证明模型会解一道题,必须排除答案或高度相似解法已经泄入训练/检索数据的解释;不能只看最终正确率。
当应用业务数据微调模型,权限与删除责任从原始数据延伸到训练工件。单纯删除数据库中的记录,不代表模型参数已经忘记了这条信息。这也是敏感、频繁变化的业务事实往往应留在权限控制的外部检索层,而不盲目进入训练集的理由。
2. 一次训练步的具体数据流
采样一批序列 → 构造输入/标签/mask → 前向得到logits
→ 稳定交叉熵 → 反向计算梯度 → 梯度累计/同步
→ 反缩放与非有限检查(若使用损失缩放)
→ 梯度裁剪 → 优化器更新 → 清梯度 → 更新训练状态
AdamW分别维护梯度的一阶、二阶矩,偏差修正后用于归一化步长;解耦权重衰减是在参数更新中直接施加缩减,不应把它与所有参数统一施加L2惩罚简单等同。不同实现对哪些参数衰减、何时累计、学习率调度都有约定,复现实验要保存这些配置,而不只保存一个学习率数字。
梯度累计将多个microbatch的贡献组合成一次优化更新。等价性取决于损失归一化、随机算子以及调度计步方式。长短序列有效Token数量不同,用“每个microbatch均值的简单均值”可能不同于全体有效Token均值。要先说明优化目标按样本还是按Token加权,再设计累计逻辑。
3. 为什么显存不只是参数量乘2字节
训练可能同时持有模型权重、梯度、优化器矩、主权重副本、中间激活、临时算子缓冲和通信buffer。常见混合精度Adam实现中的某些配置可接近每参数16字节的模型状态开销,但这不是普遍常数:是否保留FP32主权重、梯度dtype、分片、量化优化器都会改变它。
估算应写出分项:M_total = M_weights + M_grads + M_optimizer + M_activations + M_workspace + M_communication。仅根据“7B×2字节=14GB”判断能否训练是错误的;这至多是某种dtype下的权重存储估计。序列长度增长也会提高激活负担,即使模型参数完全不变。
激活检查点通过不保存部分中间值、反向时重新计算,换取更低显存。这里的checkpoint是自动求导内存优化,不是Agent任务断点,也不是训练状态持久化。相同英文词在三个系统层次含义不同,必须明确。
4. 分布式训练如何划分工作
数据并行让各设备处理不同样本,再同步梯度;张量并行拆分单层矩阵运算,需要层内通信;流水线并行拆分层,microbatch在阶段间流动,会产生流水线空泡;专家并行把MoE专家分配到设备,路由使Token跨设备移动。它们解决不同约束,不能用“多卡等于训练速度线性增加”概括。
选择并行方式时,先确认瓶颈是单卡放不下、矩阵计算量大,还是跨设备网络。把大矩阵切得太细,可能提高通信比例;把流水线阶段切得不均,最慢阶段会限制整体;把专家负载分布忽略,少数热门专家会排队。第06章将从roofline和带宽继续解释这些取舍。
分片优化器状态、梯度、参数能够减少单设备持有状态,但相应引入收集与通信。检查点恢复还需要保存优化器状态、随机数状态、数据位置与调度计数,否则“从同一权重继续”不一定重现同一训练轨迹。生产恢复追求的是明确的恢复语义,不必对所有硬件强求逐位一致。
5. Scaling Laws应该怎样使用
训练损失与参数量、数据量、计算量存在可拟合的经验关系,但它们依赖数据、架构、优化与预算范围。Chinchilla研究讨论了固定训练计算预算下参数与数据的分配;不能把其特定研究设置中的比例当成任何模型、任何语言、任何推理成本下的永恒最优值。[N37]
还应区分训练计算最优与部署总成本最优。若模型会被调用很多次,花更多训练Token训练一个较小模型,可能换取长期推理成本下降。反过来,一个只做一次探索的模型项目未必值得为推理节省投入大量额外训练。真正的目标函数包含训练、服务和质量收益,而不只是一条损失曲线。
评估报告还要分开训练损失、验证损失与业务成功率。验证交叉熵略有改善,不保证工具调用权限判断也改善;代码通过率提高,可能集中在某类语言。能力扩展必须由分层评测证明,而不是由参数规模推断。
6. 本书真实训练实验的读法
train_tiny_lm.py包含两层因果Transformer,18,320个参数,CPU训练100步。数据是作者构造的16符号循环序列;任务是学习“下一个符号等于当前符号加一再模16”。这使梯度、mask和更新过程可验证,又不会把实验冒充通用语言模型。
配套运行记录中,训练交叉熵从约2.8468降到0.00345,训练Token准确率达到1.0。它证明这段代码能够沿定义的目标优化并记住/拟合这个简单规则,不证明测试泛化、多步推理或真实编码能力。修改未来输入后,前缀logits误差为零,另行验证因果掩码。
进一步实验不应只增加训练步:把验证序列改成逆序、换符号映射、增加不同规律;比较训练内分布与分布外结果。检查失败来源到底是模型容量、数据覆盖还是任务不可识别。保留训练种子和配置,至少重复几个种子,才能判断某项优化是否只是初始化巧合。
7. 资深工程师的结论标准
看见“数据更多、模型更强”的报告,应追问有效训练Token、去重与污染、计算预算、部署代价和任务范围。看见“显存不足”,应分解占用,而不是直接缩小batch。看见“loss不下降”,应先检查标签、mask、梯度、学习率与数值,再改变架构。每一项排查必须对应可观察变量,这才是训练系统内部的理解。
四个微批累积梯度,为什么不一定等于四倍学习率
输入与条件。有效批包含4个等大微批,损失按样本平均;各微批一个参数的平均梯度分别为1、2、3、4。
| 步骤与对象 | 内部动作 | 中间结果 / 新状态 |
|---|---|---|
| 1目标梯度 | 完整有效批的平均 | (1+2+3+4)/4=2.5。 |
| 2直接累积错误 | 每次平均损失反传但不除4 | 梯度和10,放大4倍。 |
| 3正确缩放 | 每个微批损失先除4 | 累计2.5。 |
| 4更新时机 | 四次backward后一次step | 不是每个微批都更新后再把结果当同一个大批。 |
| 5等价边界 | 含跨样本BatchNorm、随机层或不同优化器步数 | 数值与动力学可能不同,不能无条件声称完全等价。 |
把过程连起来。累积梯度必须明确损失归约分母、微批大小和优化器更新次数。
边界与反例。不等大微批需要按样本或有效Token数量加权,不应仍机械除微批个数。
依据与适用范围:[DERIVE]。示例输入和场景由本书明确设定。
用1000个参数算清ZeRO究竟分摊哪份状态
输入与条件。假设全部使用FP32:1000个参数P占4000字节,梯度G占4000字节,Adam的一阶和二阶矩合计8000字节。两张设备均匀分摊;只计算这三类状态。
| 步骤与对象 | 内部动作 | 中间结果 / 新状态 |
|---|---|---|
| 1普通数据并行 | 每张设备各有P、G、两个矩 | 每张4000+4000+8000=16000字节。 |
| 2ZeRO-1式分摊 | 仅优化器状态均分两张设备 | 每张4000+4000+4000=12000字节。 |
| 3ZeRO-2式分摊 | 梯度与优化器状态均分,参数复制 | 每张4000+2000+4000=10000字节。 |
| 4ZeRO-3式分摊 | 参数、梯度、优化器状态都均分 | 每张2000+2000+4000=8000字节。 |
| 5补上限制 | 计算某层时仍需拿到相应参数,产生通信和临时材料 | 上表不是实际峰值显存,不能据此断言两卡一定装得下。 |
把过程连起来。先画出参数、梯度和优化器状态三份数据,再讨论“切分”;否则很容易把不同阶段的节省量混在一起。
边界与反例。忽略激活、通信缓冲、临时聚合、分片不均、额外主权重及框架开销。这里是状态记账,不是设备实测。
依据与适用范围:[ZERO]。示例输入和场景由本书明确设定。