← 返回题目列表

如何用长度分桶与 Packing 提升 SFT 训练吞吐?

困难 第 20 / 25 题 更新于 2026/09/25
SFTSequence PackingLength BucketingToken Budget
学习 AI 实战项目

简化版

长度分桶把相近长度样本组成 Batch,Packing 则把多条短样本装入同一上下文窗口,两者都用于减少 Padding 空算。优化时应按有效监督 Token/s、峰值显存和固定 Token 预算后的质量比较,不能只看 Step/s;严格样本隔离仍需正确的分段 Attention、位置与标签边界。

详细版

先统计样本总长度和监督长度分布,再选择策略:长度差异不大时动态 Padding/分桶已足够;大量短样本面对长窗口时再启用 Packing;长样本单独建立队列,避免被截断或拖慢所有 Batch。

slot_utilization = real_input_tokens / allocated_token_slots
supervised_utilization = loss_tokens / allocated_token_slots
throughput = supervised_tokens / wall_clock_second

若 8 条样本平均 512 Token、统一 Pad 到 4096,槽位利用率只有 512/4096=12.5%。Packing 理论上能显著提高利用率,但装箱、Varlen Kernel、通信和数据预处理会限制端到端收益,所以必须在目标硬件实测。

策略适用数据优点主要代价
动态 Padding长度较集中实现简单仍有尾部空算
Length Bucketing长度分布较宽低风险降 Padding随机性与队列管理
Offline Packing数据集固定装箱可复现预处理和 Epoch 重排复杂
Online Packing流式/持续数据灵活CPU 瓶颈与复现难度

性能比较的单位应是“固定训练 Token 预算达到什么质量、花多少时间”,不是“谁每秒跑的 Step 更多”。

完整版教学

易错点:Pack 得更满只改善槽位利用率;若监督 Token 比例、全局 Loss 权重或数据等待没有改善,端到端训练未必更快。

一、先区分槽位、输入 Token 与监督 Token

Padding 槽位可能不参加 Loss,却仍占矩形张量的计算或显存。输入 Token 中又有 System/User 等只作条件、不直接监督的位置,所以“非 Padding 比例”也不等于真正的监督密度。

训练报表至少同时记录分配槽位、真实输入 Token、参与 Loss 的 Token 和 Wall Time。否则一个包含大量长 Prompt、很短回答的 Pack 看似满载,实际每步监督信号仍很少。

二、长度分桶为什么是低风险基线

将长度相近的样本组成 Batch,可减少每批最长样本造成的 Padding,同时保持每条序列独立。它不需要把多个样本拼入同一序列,边界处理比 Packing 简单。

桶不能切得过细,否则小语种、任务类型或数据来源可能在 Batch 中长期聚集,降低随机混合。常见做法是在大缓冲区内按长度排序,再以局部窗口随机组批,而不是对全数据永久固定顺序。

三、装箱问题怎样建模

把最大序列长度看成容器容量,把每条格式化样本长度看成物品大小。First-Fit Decreasing 先按长度降序,再放入第一个容得下的包,成本低且通常比按原顺序拼接利用率高。

capacity = 16
lengths  = [9, 7, 6, 5, 4, 1]
FFD packs = [9+7], [6+5+4+1]

长度必须包含 Chat Template、BOS/EOS 与工具消息,不能用原始字符数估算。还要限制每包样本数,避免极短数据形成包含几十段边界的异常 Pack。

四、Offline 与 Online Packing 如何选择

Offline Packing 在训练前生成 Pack,容易保存 Manifest、复现每个 Epoch 和做边界单测;但数据增量、动态采样权重或多 Epoch Shuffle 会需要重新装箱。Online Packing 在 DataLoader 缓冲区实时组合,适合流式数据,却可能让 CPU 和跨 Worker 协调成为瓶颈。

维度OfflineOnline
可复现性高,Manifest 固定依赖 Worker/随机状态
预处理成本前置且可缓存每轮持续发生
动态采样较弱较灵活
调试可定位到 Pack ID需保存运行 Trace

选择不只看算法利用率,还要看数据是否持续变化、采样器是否需要按任务动态调权。

五、长样本为什么要单独治理

少量接近最大长度的样本会降低装箱空间,也可能让同一 Batch 的显存峰值突然升高。可以建立长度 Bucket 或 Long-Sequence Queue,为长样本使用更小 Micro Batch 和独立梯度累积。

超过窗口的样本不能静默截断。多轮对话应按协议裁剪且保留 System 与有效回答,代码/文档任务则可能需要分块或专门长上下文训练;每种处置都要统计丢弃和监督 Token 损失。

六、怎样平衡多卡 Token 负载

数据并行若只让各 Rank 获得相同 Pack 数,实际 Token 数仍可能差异很大,短卡要等待长卡同步。调度器应尽量让每卡的总输入 Token 或估算 FLOPs 接近,而不只是样本数相同。

假设四张卡分别处理 16k、16k、8k、8k Token,同步步耗时由前两张决定,后两张近一半时间空等。把 Pack 重排为每卡约 12k Token,理论计算总量不变,却能降低 Straggler;实际还要考虑通信和序列形状对 Kernel 效率的影响。

七、Loss 归一化与采样权重不能被悄悄改变

按 Token 平均时,长回答自然贡献更多梯度;按样本平均时,每条样本权重接近。Packing 后如果框架先对每个 Pack 求平均再跨卡等权聚合,不同监督 Token 数的 Pack 会获得错误权重。

global_token_mean = sum(all_valid_token_losses)
                  / sum(all_valid_token_counts)

应跨 Rank 汇总 Loss 总和与有效目标数,再按预定口径归一化。若业务希望每个任务等权,应通过显式采样或任务权重实现,不要依赖 Pack 恰好包含多少 Token。

八、如何做公平吞吐基准

固定模型、精度、最大长度、总有效训练 Token 和优化器更新口径,分别测试静态 Padding、动态 Padding、分桶与 Packing。预热后报告监督 Token/s、输入 Token/s、峰值显存、GPU 利用率、DataLoader 等待和 P50/P95 Step Time。

例如方案 A 为 40k 输入 Token/s、监督比例 40%,得到 16k 监督 Token/s;方案 B 只有 35k 输入 Token/s,但监督比例 70%,实际得到 24.5k 监督 Token/s。只看原始输入吞吐会错误选择 A。

九、性能提升后为什么还要做质量等价验证

Packing 会改变每步有效 Token、Batch 构成和梯度噪声,若仍按相同 Step 训练,候选实际见到的数据更多。公平质量对比应固定总训练 Token,并重新核对学习率调度与梯度累积。

边界正确性用专门题验证:修改同 Pack 前一独立样本,后一段有效 Logits 不应改变;标签集合与独立运行一致。这里保持简洁,因为跨样本 Mask 的推导应由专门的边界题展开。

十、常见误区与追问

  • 误区:Padding 位置不算 Loss 就没有计算浪费。 Dense Kernel 仍可能处理对应张量位置,需看实际算子。
  • 误区:Packing 利用率高就一定更快。 装箱、DataLoader、Varlen Kernel 与通信都可能成为新瓶颈。
  • 误区:相同 Step 数可公平比较 Packing。 每步有效 Token 不同,应固定总 Token 与更新口径。
  • 误区:每卡 Pack 数相同就负载均衡。 序列长度和有效 Token 不同仍会产生 Straggler。
  • 误区:在线装箱天然优于离线装箱。 它更灵活,但复现与 CPU 开销更复杂。
  • 追问:什么时候只做分桶就够? 长度方差中等、吞吐已达标或后端不支持严格分段 Attention 时。
  • 追问:最有业务意义的吞吐指标是什么? 固定质量与 Token 预算下的监督 Token/s、总训练时长和成本。

十一、加强记忆

先量三种 Token:槽位、真实输入、有效监督;再选三级手段:动态 Padding、长度分桶、Sequence Packing。装箱用真实模板后长度,长样本单独治理,多卡按 Token/FLOPs 平衡;Loss 用全局有效目标数归一化。最后用固定总 Token 做质量—吞吐对照:Pack 得更满只是手段,监督 Token 更快且任务语义不变才是成功。