在我们自己的模型上,把缓存、采样、投机、量化的账都对一遍
这节实验课做什么:把本章五课的结论,放到我们自己从 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 快几倍?写下你的数,再看实测:
只快 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 省下的重算就显出来了。
这正是本章一再强调的:屋顶线给的是上界,前提是计算与读写足够大、能把硬件喂饱 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条我们项目的实测;设备只有一台,没有测别的机器。结论只说明「这个规模上开销主导」,不能外推成大模型上 cache 只快 1.16 倍。 出处待补 。拿小模型测出来的 token/s,只能比较同一台机器上的相对快慢,不能推到大模型上。
实验 2:温度 × top-p 的分布与重复率
对照岔路课的采样实验台:同一个 checkpoint、同一个提示「孔明曰:「」,在浏览器里用章内预计算的 logits 重算,熵与保留个数应该和上表逐项相同(例如温度 1、top-p 0.9:熵 4.895、保留 352 个)。选一组设置核对:
读这张表时注意:重复率低不等于写得好。温度 1.3 时重复率是 0,可样例里满是不通的句子——那是长尾在起作用(岔路课)。我们的模型只有 3.7M 参数,这里只能比「重复」,不能比「质量」。
实验 3:给我们的模型配投机采样
目标 ref_baseline,草稿用 c1_dim64(332,352 参数)还是 c1_dim128(1,066,112)?每轮猜几个?先预测哪一组的理论加速最高,再看 12 组真跑:
三件事可以直接读出来:① 公式 (1 − αk+1) ÷ (1 − α) 代入实测接受率,与真跑的「每次目标前向产出」相差不到 1%;② 按参数量估草稿代价,小草稿 k = 3 最好;③ 大草稿接受率更高,但 k 一大就比不投机还慢。贪心下,投机输出与目标自己贪心解码逐 token 相同 16 / 16。墙钟时间我们没有测:实验 1 已经说明,这个规模上每次前向的耗时与参数量不成比例,「按参数量估代价」在这台机器上并不成立。
实验 4:权重量化到几位
用规则 ③ 读:绿条都在噪声底线 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、采样、投机解码、量化四代:
- 每一步把整段重新喂进模型
- KV cache
- 批处理:一次解码多个请求
- 连续批处理(迭代级调度)
- PagedAttention:KV 分块按需分配
- 投机解码:草稿猜、目标一次验
- 让模型自己当草稿:MTP 与专用草稿器
- 量化:每个权重少读几位
- 按 TTFT / TPOT / goodput 调度:分块 prefill、P/D 分离
- 采样:温度 → top-k → top-p → min-p
- 少存 KV:GQA / MLA / 线性注意力
一句话
每个结论都带上条件:哪个模型、哪台机器、测了几次、和谁比。
下一个缺口
我们只能在这个小模型上比「重复率」「验证 loss」;真到了大模型,量化掉的那一点、服务端的各种调度,会不会在某些任务上悄悄掉分(投机解码按构造不改输出分布,第 3 课)?分数能信吗? → C14 评测
你可能会问
- 「为什么不在这台机器上把锚点也跑一下?」 锚点的 BF16 权重就有 55.6 GB,本课程不下载模型权重;锚点的数字全部是 config 现算加屋顶线上界,页面上都标了「上界」「推演」。
- 「噪声底线为什么取 0.020?」 同配置、同种子的两个 run(baseline 与 ref_baseline)最终验证 loss 是 4.6263 与 4.6405,差 0.014,EXPERIMENTS.md 记录了这件事;C14 又重跑到 5 次:标准差 0.0066、极差 0.016,差距小于 3σ 不下结论。本章的量化结论用 0.014 还是 0.020 当底线,结果一样。