模型量化,
究竟量化了什么?
从一个权重的舍入误差,走到 Transformer 的每一层、推理内核和显存账本。
量化是一次有损编码:把高精度张量映射到更少的可表示数值,同时尽量保持模型的输出行为。它首先是数值近似问题,然后才是文件压缩和内核加速问题。
模型训练后固定的参数。压缩它,直接降低常驻权重的存储需求。
推理时随输入产生的中间数。压缩它,才能使用部分低精度矩阵乘法路径。
每个请求累积的 Key 和 Value。长度与并发增长时,它可能成为另一笔显存大头。
01 · 一个浮点数如何变成低位整数
先看最简单的对称、按组量化。它是理解 GPTQ、AWQ 和 GGUF 块量化的起点。
对于一组浮点权重,先选缩放因子 s。每个权重 w 被映射成有限范围内的整数 q;需要用它计算时,再得到近似值 ŵ。例如 INT4 的对称表示可以用 −7 到 +7 的 15 个级别。下面的实验采用这个约定;实际格式的范围可能不同。
s = max(|wᵢ|) / (2⁽ᵇ⁻¹⁾ − 1)qᵢ = clip(round(wᵢ / s), −qmax, qmax)ŵᵢ = s · qᵢb 是编码位数。非对称量化还会引入 zero-point;不同方法可使用更复杂的缩放和误差补偿。b 是编码位数。非对称量化还会引入 zero-point;不同方法可能采用更复杂的缩放与误差补偿。位数越低,可选刻度越少。同组若出现极大的离群值,它会拉大 s,使其他小权重更容易被舍入到同一刻度。缩小分组有时能缓解这个问题,但每组都要额外保存 scale。
试着改动位数与分组
—
—
—
橙色行是离群值。这个示例只演示最简单的舍入;真实 GPTQ/AWQ 会利用样本统计进一步控制误差。有效位数计入每组一个 16 bit scale,不含其他元数据。
目标:尽量减小 ‖W·X − Ŵ·X‖单个权重误差 |W−Ŵ| 很小,也不代表乘上实际输入 X 后的输出误差一定小。单个权重误差 |W − Ŵ| 很小,并不代表乘上实际输入 X 后的输出误差一定小。量化方法通常要考虑权重对层输出的影响,而不仅是文件里每个数字的偏差。
02 · 同一层里,并非每个张量都用同一种精度
下面以典型的 GQA + SwiGLU 解码层为例。具体模型仍需查看实际的 config 和张量清单。
Attention 的矩阵
- Query 投影
Wq - Key 投影
Wk - Value 投影
Wv - 输出投影
Wo
这些矩阵是权重量化的主要对象;K/V 投影的输出还会写入 KV Cache。
MLP 的矩阵
- 门控投影
Wgate - 上投影
Wup - 下投影
Wdown
宽大的 MLP 常占一层权重的多数。MoE 模型还要分别考虑每个 expert 的这些矩阵。
其他运算与张量
- 词向量表
Embed - 归一化
Norm - 残差与 softmax
Ops - 最终输出头
lm_head
敏感层可能保留 BF16/FP16;是否量化取决于实际 checkpoint 与后端。
- 选量化对象:可能只量化线性层权重,也可能同时量化输入激活;KV Cache 是独立开关。
- 选粒度:每张量、每通道、每组或每块。粒度越细,通常越能贴合数值分布,但 scale 和计算开销会增加。
- 选精度:敏感的层、输出头或部分通道可保留更高精度。因此“4 bit 模型”常是主体权重约 4 bit,而非每个参数都严格 4 bit。
权重量化通常首先覆盖线性层的大矩阵,例如注意力投影与 MLP 投影。Embedding、Norm 和输出头是否量化,要看方案、模型敏感性和运行时支持。激活量化发生在推理计算路径中;KV Cache 则是历史 token 的注意力状态,需要单独决定精度。
03 · 算法在解决哪一种误差
“INT4”描述目标格式;“GPTQ / AWQ”描述怎样把原模型变成这个格式。
RTN
直接四舍五入到最近的刻度。无需校准样本,成本低;很低位数时容易损伤敏感权重。
GPTQ
观察校准输入,逐步量化权重并补偿其余权重,目标是减小层输出误差。[1]
AWQ
依据激活分布找出敏感权重通道,用等价缩放保护它们。[2]
SmoothQuant
针对难量化的激活离群值,把部分量化难度转移到权重,服务于 INT8 W8A8。[3]
INT8 与 FP8 都占 8 bit,但编码方式不同。INT8 用整数级别配合 scale;FP8 把位数分给符号、指数和尾数,也通常结合 scale。两者对极端数值、误差和硬件的要求不同。[4]
GGUF 的 Q3_K 是另一套权重块编码命名。单个 Q3_K 的 256 权重块有 3 bit 权重编码及分级 scale,合计约 3.4375 bit/权重;Q3_K_M 是模型级混合档位,平均位数还会更高。[5]
04 · 压缩权重如何参与一次推理
磁盘格式、显存中的布局、算子实际使用的数据类型,是三个不同层次。
仅权重量化不意味着推理时把整份权重永久还原成 BF16。高效内核通常在计算过程中处理编码和 scale。不过,解包和转换有代价,因此文件更小不保证每个 batch 都更快。W8A8 有机会直接使用低精度矩阵乘法硬件,实际收益取决于芯片、形状、batch 与内核。[6]
W4A16 ≠ FP8 KV Cache ≠ W8A8W/A 描述权重与激活;KV 描述历史注意力状态。三者可以组合,但要分别确认框架支持。W/A 描述权重与激活;KV 描述历史注意力状态。三者可以组合,但要分别确认框架支持。
05 · 文件大小和显存,要分开算
先估权重,再估 KV,最后给运行时工作区留空间。
参数数 × 有效 bits/8;按每个张量实际精度求和。
scale、zero-point、混合精度张量和对齐。
层数、上下文、并发、KV heads、head_dim 与 KV dtype。
激活、内核工作区、通信 buffer、图捕获和分配器。
权重 ≈ Σ(张量参数数 × 有效 bits/8)KV ≈ 2 × L × T × B × Hkv × Dh × 元素字节显存 ≈ 权重 + 已分配 KV + 临时激活/工作区 + 运行时KV 公式适用于普通全注意力/GQA 的基础估算;滑动窗口、MLA、分页块、scale 与张量并行会改变实际分配。约 8B 参数:只看权重
理论示例:全模型 BF16 约 14.90 GiB;若全部按 INT4、每 128 权重一个 FP16 scale,约 3.84 GiB。实际还可能保留高精度张量、存 zero-point 或额外布局。
32 层 GQA:单请求 8K token
假设 8 个 KV heads、head_dim 128:BF16 KV 的数据主体 1 GiB;FP8 的数据主体约 0.5 GiB。16 个同长度请求,主体约为 16 / 8 GiB,未计额外开销。
一个实测参照:llama.cpp 给出的 Llama 3.1 8B 文件大小约为 F16 14.96 GiB、Q4_K_M 4.58 GiB。这只是模型文件口径,不能直接当成加载后的总显存。vLLM 等服务框架还可能预分配 KV Cache,使“启动后已占用显存”大于当下请求真正使用的 KV 数据。[7][8]
06 · 资料与口径
公式中的容量例子是按明确假设推导的教学示例;量化算法、格式和运行时描述依据下列原始论文或项目文档。
- Frantar et al., GPTQ: Accurate Post-Training Quantization, 2022.
- Lin et al., AWQ: Activation-aware Weight Quantization, 2023.
- Xiao et al., SmoothQuant, 2022.
- vLLM Project, LLM Compressor: Compression Schemes.
- llama.cpp, Tensor Encoding Schemes.
- vLLM Project, Choosing the Right Compression Scheme.
- llama.cpp, Quantization README, model-size table.
- vLLM Project, KV Cache configuration.