把权重从 16 位压到 4 位,为什么能变快,又会丢什么?
本课一问:第 1 课说,生成慢是因为每个 token 都要把权重读一遍。那把每个权重从 16 位压到 8 位、4 位,读的字节少了,是不是就快了?快多少?代价是什么?
这一课先不碰:FP8、FP4、MX 这些浮点格式的位是怎么排的(C9 第 4 课与 岔路);训练时就带着量化(量化感知训练,C9 岔路);把大模型的能力「教」给小模型的蒸馏(C12)。这一课只讲推理时把训好的权重压小。
从已有出发
贯穿例句的那一步 decode(写出「小王」),锚点要读 51.25 GB 权重,H100 上至少 15.30 ms。第 1 课的屋顶线告诉我们:batch 1 时这一步的时间几乎只由字节决定。于是一个直接的想法:每个权重少存几位。先把字节账算清楚:
试三件事:① B = 1 时看「相对 BF16」一列:INT8 约 1.98 倍、INT4 约 3.76 倍——都比 16 ÷ 位数略少,因为 GDN 状态与 KV 的读写不跟着权重变;② 把 B 拖到 58,INT4 只剩约 1.8 倍:每个请求自己的 KV 与状态占了大头;③ 看最后两列:INT4 让整模型从 55.6 GB 降到 14.3 GB,同一张卡能放的 4K 请求从 58 个变成 156 个——量化同时改变了第 2 课的容量账。
这里的速度来自字节,不来自算力:只量化权重时,乘法照样按 16 位算(先把 INT4 还原回来再乘)。DeepSeek-V4 报告说得很直白:它把 MoE 专家权重做成 FP4,是为了「降低部署时的显存流量、实际提速」,而在现有硬件上 FP4 × FP8 的峰值算力和 FP8 × FP8 一样 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条官方自述的动机与硬件事实;提速幅度报告没有单独给出。 出处DeepSeek-V4 报告 §1、§5.2.1(本地 PDF) ↗ 。
先自己设计:整个矩阵一个缩放,直接四舍五入
把一个权重矩阵压成 b 位整数,最直接的办法:找出整个矩阵里绝对值最大的数 m,让它对上最大的整数 2b−1 − 1;每个权重除以这个缩放、四舍五入(round-to-nearest,RTN)。拿我们项目的模型真做一遍:4 个块里全部 28 个线性层、3,162,112 个权重,量化后在整个验证集上重算 loss(不量化时 4.6405):
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
| 位数 | 整个矩阵一个缩放 | 验证 loss | 比不量化涨了 |
|---|---|---|---|
| INT8 | ±127 | 4.6401 | -0.0004 |
| INT4 | ±7 | 4.6720 | 0.0315 |
| INT3 | ±3 | 4.9085 | 0.2680 |
| 位数 | 做法 | 验证 loss | 比不量化涨了 |
|---|---|---|---|
| INT4 | 每 64 个一组 | 4.6499 | 0.0094 |
| INT4 | GPTQ,每个输出行一个缩放 | 4.6488 | 0.0083 |
| INT3 | 每 32 个一组 | 4.6798 | 0.0393 |
| INT3 | GPTQ,每 64 个一组 | 4.6704 | 0.0298 |
改进一:缩放按小组给
看一行真实权重(我们模型 blocks.0.attn.q_proj 里绝对值最大的元素所在的那一行,256 个数)被压成几位、按多大的组缩放时,会变成什么样:
试三件事:① INT4、整行一个缩放:数一数被舍入成 0 的红点;② 换成每 32 个一组:只有最大那个数所在的组还粗,其余组的格子细了,相对误差下降;③ 切到 INT2:只剩 −1、0、1 三个等级,大半权重变成 0——这就是位数再往下砍会碰到的墙。
「按组给缩放」放在锚点的真实形状里:FFN 的 Wup 按输入维每 128 个一组,每个输出列每组一个缩放:
| 维度 | 含义 | 真实规模 | 小规模 |
|---|---|---|---|
| d | 输入维 hidden_size | 5120 | 8 |
| f | 输出维 intermediate_size | 17,408 | 6 |
| g | 组数 = 5,120 ÷ 128 | 40 | 2 |
改进二:GPTQ——让还没量化的权重替已经量化的背锅
按组缩放让格子变细,但每个权重还是各自舍入、各自承担误差。GPTQ(2022)换了个角度:我们在乎的不是 ŵ 和 w 差多少,而是输出 X·ŵ 和 X·w 差多少。于是按列一个个量化,每量化一列,就用校准数据算出的 H = 2XᵀX,把这一列的误差按比例摊到还没量化的列上,让它们提前「改一点」来抵消 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条来自最优脑外科(OBS)的二阶近似:在输入 X 的统计下最小化输出的平方误差。「这样做更准」是近似推导,效果靠实验。 出处Frantar et al. 2022(ICLR 2023,需联网) ↗需联网 。
我们照论文的算法 1 实现了一个最直接的版本(不重排列、全部列一次处理,校准数据取训练集 16 个窗口,评估在不重叠的验证集上):
| 位数与缩放 | 直接四舍五入 | GPTQ |
|---|---|---|
| INT4,每个输出行一个缩放 | +0.0133 | +0.0083 |
| INT4,每 128 个一组 | +0.0109 | +0.0084 |
| INT3,每个输出行一个缩放 | +0.0746 | +0.0413 |
| INT3,每 64 个一组 | +0.0519 | +0.0298 |
同样的位数、同样的缩放方式,GPTQ 都更小。但要按实验课的规则读:INT4 时两者只差约 0.005,小于噪声底线(C14:同配置 5 次重跑极差 0.016,3σ ≈ 0.020),在我们这个规模上不能下结论;INT3 时差 0.02–0.03,才超出了它。规模一大,差距会大到决定成败:GPTQ 论文里 OPT-175B 在 WikiText2 上,FP16 困惑度 8.34;直接四舍五入到 4 位是 10.54,GPTQ 是 8.37;到 3 位,直接四舍五入是 7.3 × 10³(彻底坏掉),GPTQ 是 8.68(表 3) 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条提出方自报;单张 A100 量化 OPT-175B 用了 4.2 小时。 出处GPTQ 表 3(需联网) ↗需联网 。
🔍 GPTQ 的一步到底改了什么?
对第 j 列:先把它四舍五入,得到误差 e = wj − qj(每个输出行一个数);再用 H 的逆矩阵(先做 Cholesky 分解,数值上更稳)的第 j 行,把 −e ÷ [H⁻¹]jj 乘上 [H⁻¹]j, j+1… 加到后面各列。直觉是:如果第 j 个输入通道和第 k 个经常一起变大,把第 j 列的误差让第 k 列「预先补一点」,输出就几乎不受影响。我们的实现在 gen_c13_precomputed.py 的 gptq_quant(约 20 行)。AWQ 走的是另一条路:按激活的幅度挑出约 1% 的显著通道,把它们的权重放大、缩放缩小,舍入误差对它们的相对影响就小了(MLSys 2024 最佳论文)。
激活也要量化吗?离群值的问题
上面只压了权重:乘法时先把它还原成 16 位。如果激活也压成 INT8(W8A8),乘法本身就能用 INT8 算,大 batch、算力受限时更快。可激活有一个权重没有的麻烦:离群值。LLM.int8() 报告,模型到约 6.7B 规模时,几乎所有层里都会出现少数几个特征维,幅度可达其他维的 20 倍;每个 2,048-token 序列约有 15 万个这样的值,集中在 6 个维度里,把它们置零困惑度会变差 600%–1000% 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条按参数量画看起来像突变,按困惑度画是平滑的指数变化(论文自己的说明)。 出处Dettmers et al. 2022 §4(需联网) ↗需联网 。整张量一个缩放时,这几个大数会把其余所有值挤进同一两个格子里。
我们 3.7M 的模型有没有?逐通道看激活的最大绝对值,最不均匀的一层是 blocks.1.ffn.w2(SwiGLU 的 W2 的输入):最大 ÷ 中位数 = 6.4——远没到 LLM.int8() 说的程度。所以在我们的模型上,W8A8 用整张量一个缩放,验证 loss 只涨 0.0036;每个 token 一个缩放 +0.0003。这个规模看不到离群值的问题,下面的办法只能演示机制,不能演示收益。
SmoothQuant(2022)的办法:既然难处在激活、权重很「好压」,就把一部分难度挪过去。每个输入通道 j 选一个 sj,激活除以它、对应那一列权重乘以它:
等式严格成立 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条对角矩阵与其逆相乘为单位矩阵;误差只来自之后的量化。 出处Xiao et al. 2022 式 4(需联网) ↗需联网 ;能不能让 W8A8 在大模型上不掉点,是实验结论:论文在 OPT-175B 等模型上做到 W8A8,FasterTransformer 上 1.56 倍加速、显存减半 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条PyTorch 实现是 1.51 倍、1.96 倍;530B 模型从 16 张卡降到 8 张。 出处SmoothQuant(ICML 2023,需联网) ↗需联网 。用我们模型那一层的真实统计拖一拖 α:
KV 也能压:它同样是每步要读的字节。FP8 的 KV 让第 1 课字节条里橙色那段减半;DeepSeek-V4.1 更进一步,把主 KV 存成 FP4(每条缓存条目 288 字节,FP8 版 528 字节;R3 §1.5 e 由官方缓存格式复算;只有 4 层持有 KV、其中 3 层每 2 个 token 合 1 条,连索引 key 摊下来每 token 共 890 字节,C15 第 3 课)——C3 第 10 课、C11 讲过它怎么先把 KV 压短压少,这里是再压位数。
最后把我们模型上的全部结果放在一起(绿条 = 涨幅在 C14 的噪声底线以内):
⚠ 常见误解
「量化只省显存,不提速。」batch 1 的解码受带宽限制,要读的字节减半,就接近快一倍:锚点 INT8 的上界约 131 token/s,BF16 约 65。
「压到 4 位,就快 4 倍。」只有权重那部分字节变少:KV 与状态照读,缩放还要多占 0.125–0.5 位,反量化也有开销;batch 大了,每个请求自己的字节越来越多,只量化权重的收益越来越小(上面 B = 58 时约 1.8 倍)。
「4 位量化,每个权重就占 4 位。」每 g 个权重还有一个 16 位缩放:每 128 个一组是 4.125 位;MXFP4 每 32 个一个 8 位缩放是 4.25 位;NVFP4 每 16 个一个是 4.5 位(C9 岔路)。
「验证 loss 几乎没变,就是没有损失。」loss 是平均意义上的,长推理、代码、少见的语言可能掉得多得多。量化必须配任务评测——而评测数字本身该信多少,是 C14 的问题。
「激活离群值每个模型都有,所以一定要 SmoothQuant。」我们 3.7M 的模型最不均匀的一层也只有 6.4 倍,W8A8 用最粗的缩放也只涨 0.0036;LLM.int8() 说它在约 6.7B 以上才系统出现。先测自己的模型,再决定。
在演进地图上的位置
- 每一步把整段重新喂进模型
- KV cache
- 批处理:一次解码多个请求
- 连续批处理(迭代级调度)
- PagedAttention:KV 分块按需分配
- 投机解码:草稿猜、目标一次验
- 让模型自己当草稿:MTP 与专用草稿器
- 量化:每个权重少读几位
- 按 TTFT / TPOT / goodput 调度:分块 prefill、P/D 分离
- 采样:温度 → top-k → top-p → min-p
- 少存 KV:GQA / MLA / 线性注意力
证据三问
| 问 | 本课的回答 |
|---|---|
| ① 它解决什么问题? | 解码受带宽限制:每个权重少读几位,每个 token 就快;整模型变小,同一张卡还能多放请求 |
| ② 数学上为什么? | 字节与时间上界是记账 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条屋顶线 + 每权重位数;不含反量化开销。 出处待补 ;SmoothQuant 的变换严格等价 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条diag(s)⁻¹·diag(s) = I。 出处SmoothQuant 式 4(需联网) ↗需联网 ;GPTQ 的误差补偿来自二阶近似 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条在输入统计下最小化输出误差的近似解。 出处GPTQ §3(需联网) ↗需联网 |
| ③ 实验上呢? | 损失多少只能实测:我们的模型 INT8 各方案的变化都在 ±0.0004 以内、INT4 GPTQ +0.0083;OPT-175B 上 GPTQ 3 位 8.68 对直接四舍五入 7.3 × 10³ 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条只在各自的模型、数据与校准设置下成立。 出处我们的离线实验;GPTQ 表 3(需联网) ↗需联网 |
一句话
解码快慢看每个 token 要读多少字节;量化把权重从 16 位压到 8 位、4 位,读得少就快,代价是舍入误差——更细的缩放和误差补偿把它压小,激活里的离群值另有专门的办法。
先停在这里:记住「快来自字节,代价看分组与补偿」,就可以去第 5 课。
再深一层:展开 GPTQ 的 Dig,再读 Maarten Grootendorst 的量化图解与 GPTQ 论文算法 1。
下一个缺口
四课下来,每一招都说自己「更快」:连续批处理让整机吞吐翻几倍,投机解码让单个用户每步多拿几个 token,量化让每一步更短。可它们说的「快」是同一个东西吗?batch 开大了,整机更快、每个人却更慢;来一个很长的 prompt,别人都得等。服务快不快,到底该看哪几个数? → 第 5 课:服务快不快,该看哪几个数?
你可能会问
这一课还没有收到真实提问;你的提问会记到 05-问答记录/C13-L4.md。
- 「量化之后还能接着训练吗?」 能,那就是量化感知训练(QAT):前向用量化后的权重,反向按直通估计把梯度传给高精度的主权重。Kimi K3、DeepSeek-V4 都在后训练阶段对 MoE 专家做 FP4 的 QAT,见 C9 岔路。
- 「和蒸馏比呢?」 量化是把同一个模型存得更省;蒸馏是训一个更小的模型去模仿大模型(C12)。两者可以叠加。
- 「INT4 和 FP4 哪个好?」 同样 16 个等级,INT4 等距,FP4(E2M1)在 0 附近更密、远处更疏,更贴近权重的钟形分布;具体差多少取决于缩放方式和模型,C9 岔路对照的是 MXFP4 与 NVFP4 等块缩放 FP4;INT4 与 FP4 在同一张量上的对照本课程没有做。