从0训练LLM · 现代大模型体系 实验 实验 ≈ 40 分钟 页内实验 ×5
C13 推理:生成为什么慢、怎么变快 实验课

在我们自己的模型上,把缓存、采样、投机、量化的账都对一遍

实验课:在我们的模型上把推理的账对一遍
本章第三层交互:全部用我们项目自己训练的模型。KV cache 在 3.7M 的小模型上(Apple GPU)只快 1.17–1.32 倍、换到 CPU 上快 2.87–5.79 倍——小到每一步都是调度开销,屋顶线不成立;温度 × top-p 的重复率表从贪心的 47% 到高温的 0%;投机采样 12 组真跑与公式相差不到 1%;22 种量化方案里,INT8 与 INT4 GPTQ 都在重跑噪声以内(C14 的 5 次重跑)。每个结论都带上模型、机器、次数和对照。
🧪

这节实验课做什么:把本章五课的结论,放到我们自己从 0 训练的模型上逐条核对。用到两份真实数据:项目实验 exp_c13_inference.py 导出的 c13-inference.json(有 / 无 KV cache 的速度、温度 × top-p 的分布与重复率),以及本章的预计算 gen_c13_precomputed.py(同一个 checkpoint 加两个更小的草稿模型,离线真跑投机采样与量化)。模型:ref_baseline,3,688,704 个参数,4 层、d = 256,《三國志演義》语料,验证 loss 4.640542。

三条规则(和 C5 实验课一样):① 每次只改一项;② 先写下预测,再看结果;③ 报告结论时带上模型、机器、测了几次、和谁比;差距小于噪声底线(0.020,C14 用同配置 5 次重跑定的 3σ;baseline 与 ref_baseline 这一对差 0.0142)就不下结论。

实验 1:KV cache 在我们的模型上快几倍?

先预测:第 1 课说大模型的解码受带宽限制、KV cache 把计算从平方降到线性。我们的模型生成到第 256 个 token 时,有 cache 比没 cache 快几倍?写下你的数,再看实测:

项目实测 · 有 / 无 KV cache 的生成速度(Apple M5 Max · MPS · batch 1 · 贪心 · 5 次取中位数)
项目实测 · 有 / 无 KV cache 的生成速度

只快 1.17–1.32 倍,而且和长度几乎无关(独占 GPU 测得,测前等其他任务让出了 481 秒)。这不是 KV cache 没用(两种方式的输出逐 token 相同,cache 也确实只存了每 token 8,192 字节),而是这个规模上,时间不花在计算上,也不花在读权重上:整份权重只有 14.8 MB(FP32),有 cache 时每步约 5.3 ms、没 cache 时约 6.2–7.2 ms,差的只是那一点点多出来的计算。最可能的解释是:一次前向无论算 1 个还是 256 个位置,主要时间都花在把几十个 GPU 内核依次发射出去的固定开销上(我们没有用 profiler 逐个内核验证,这是推断)。旁证:同一个模型换到 CPU 上跑,cache 的收益随长度从 2.87 倍涨到 5.79 倍——计算量一占主导,cache 省下的重算就显出来了。

这正是本章一再强调的:屋顶线给的是上界,前提是计算与读写足够大、能把硬件喂饱 。拿小模型测出来的 token/s,只能比较同一台机器上的相对快慢,不能推到大模型上。

实验 2:温度 × top-p 的分布与重复率

项目实测 · 同一提示下 T × top-p 的熵与保留个数
项目实测 · 下一个 token 的分布

对照岔路课的采样实验台:同一个 checkpoint、同一个提示「孔明曰:「」,在浏览器里用章内预计算的 logits 重算,熵与保留个数应该和上表逐项相同(例如温度 1、top-p 0.9:熵 4.895、保留 352 个)。选一组设置核对:

采样实验台:同一组真实 logits,温度与截断各改了什么
① logits(不随温度变)
② 温度 + 截断之后的概率
③ 这个分布有多「散」

项目实测 · 4 个提示 × 8 条 × 128 个 token 的重复率
项目实测 · 采样设置与重复率

读这张表时注意:重复率低不等于写得好。温度 1.3 时重复率是 0,可样例里满是不通的句子——那是长尾在起作用(岔路课)。我们的模型只有 3.7M 参数,这里只能比「重复」,不能比「质量」。

实验 3:给我们的模型配投机采样

目标 ref_baseline,草稿用 c1_dim64(332,352 参数)还是 c1_dim128(1,066,112)?每轮猜几个?先预测哪一组的理论加速最高,再看 12 组真跑:

真模型实测 · 12 组投机采样(4 提示 × 3 种子 × 96 个新 token,温度 1)
一轮能产出几个 token:公式与真跑

三件事可以直接读出来:① 公式 (1 − αk+1) ÷ (1 − α) 代入实测接受率,与真跑的「每次目标前向产出」相差不到 1%;② 按参数量估草稿代价,小草稿 k = 3 最好;③ 大草稿接受率更高,但 k 一大就比不投机还慢。贪心下,投机输出与目标自己贪心解码逐 token 相同 16 / 16。墙钟时间我们没有测:实验 1 已经说明,这个规模上每次前向的耗时与参数量不成比例,「按参数量估代价」在这台机器上并不成立。

实验 4:权重量化到几位

真模型实测 · 22 种量化方案的验证 loss(整段验证集,离线真算)
我们的模型:量化之后验证 loss 变了多少

用规则 ③ 读:绿条都在噪声底线 0.020 以内——INT8 的全部方案,INT4 除「整个矩阵一个缩放」之外的全部方案;超出的是 INT4 整个矩阵一个缩放(+0.0315)和全部 INT3 方案。INT4 里 GPTQ(+0.0083)最小,可它和按组缩放的差距也在波动以内——按规则 ③,这个规模上不下「INT4 时 GPTQ 更好」的结论,要靠更大的模型(GPTQ 论文的 OPT-175B)。这台机器上我们没有 INT4 的矩阵乘内核,只测了质量,没有测速度;速度的账在第 4 课用锚点与屋顶线算。

验收(对应 MILESTONES「C13 推理」)

✅
  • 生成到 256 个 token 时有 / 无 cache 的速度比(上面实验 1 的最后一行),same_output 全为 true;能用一句话解释它为什么远小于第 1 课的推算。
  • 温度 × top-p 的重复率表齐全;选定一组默认设置,理由里引用表中的数与岔路课的保留个数;说明要不要改用 min-p。
  • 投机采样:选定草稿与 k,理由里引用实测产出与理论加速;贪心下逐 token 相同 16 / 16。
  • 量化:选定位数与方法,验证 loss 的涨幅小于噪声底线 0.020;并写明「只测了质量」。

在演进地图上的位置

实验课覆盖整条链,四个实验分别对应 KV cache、采样、投机解码、量化四代:

推理加速的演进:每一代都被上一代的某个真数字逼出来(点名字去那一课;完整版在章首页)
  1. 每一步把整段重新喂进模型
  2. KV cache
  3. 批处理:一次解码多个请求
  4. 连续批处理(迭代级调度)
  5. PagedAttention:KV 分块按需分配
  6. 投机解码:草稿猜、目标一次验
  7. 让模型自己当草稿:MTP 与专用草稿器
  8. 量化:每个权重少读几位
  9. 按 TTFT / TPOT / goodput 调度:分块 prefill、P/D 分离
  10. 采样:温度 → top-k → top-p → min-p
  11. 少存 KV:GQA / MLA / 线性注意力
数字口径:锚点 Qwen3.8-27B 的字节与时间是 H100 SXM 上的屋顶线上界(不是实测),由 anchor-model.json 现算;调度、投机、量化、采样的数字来自我们项目的 3 个小模型(章内 precomputed.json,脚本 gen_c13_precomputed.py,2026-09-26);vLLM、DeepSeek-V3 的数字出自本地 PDF,Orca、DistServe 出自论文原文,均为提出方自报。

一句话

📌

每个结论都带上条件:哪个模型、哪台机器、测了几次、和谁比。

下一个缺口

我们只能在这个小模型上比「重复率」「验证 loss」;真到了大模型,量化掉的那一点、服务端的各种调度,会不会在某些任务上悄悄掉分(投机解码按构造不改输出分布,第 3 课)?分数能信吗? → C14 评测

你可能会问