量化
量化是把 LLM 的权重从高精度浮点数(通常是 16 位 bfloat 或 float)转换为低精度整数或浮点数(8 位、4 位,有时 2 位)的过程,它缩减了内存占用、加快了推理速度,而质量只受到很小的损失。现代开源部署,包括 llama.cpp、Ollama、vLLM、GPTQ、AWQ,几乎全都运行在量化模型上。
量化是把 LLM 的权重从高精度浮点数(通常是 16 位 bfloat 或 float)转换为低精度整数或浮点数(8 位、4 位,有时 2 位)的过程,它缩减了内存占用、加快了推理速度,而质量只受到很小的损失。现代开源部署,包括 llama.cpp、Ollama、vLLM、GPTQ、AWQ,几乎全都运行在量化模型上。
为什么重要
一个 700 亿参数的模型在原生 16 位格式下需要约 140 GB 的 GPU 显存,单张消费级显卡无法企及。同一个模型在 4 位量化下只占约 35 GB,可以装进两张消费级 GPU、一张工作站显卡,甚至一台 Mac Studio。量化正是让本地 LLM 变得可行的关键:Llama 3 70B、Mixtral 8×22B 和 DeepSeek-V3 之所以能跑在 3000 美元的硬件上,正是因为有量化。对于开发者而言,这是"我们负担不起自托管"与"我们能部署自己的模型"之间的分水岭。
工作原理
精度等级:
- FP32(32 位浮点):训练的默认精度。每个权重 4 字节。很少用于推理。
- FP16 / BF16(16 位):推理的默认精度。每个权重 2 字节。
- INT8(8 位整数):内存减半,质量几乎一致。
- INT4 / FP4(4 位):内存减至四分之一,质量略有损失(基准上通常为 1% 至 3%)。
- INT2(2 位):内存减至八分之一,在大多数任务上有明显的质量损失。
量化过程:
- 校准:在一个小数据集上运行模型,以观察激活值的范围。
- 缩放因子与零点计算:为每个权重张量计算缩放因子,将原始范围映射到整数范围。
- 权重转换:每个权重被量化,存储为一个整数加上逐组或逐通道的缩放因子。
- 推理时反量化:在计算时,权重会在矩阵乘法之前被重新展开回浮点数。
量化方法
RTN(四舍五入到最近值):最笨的方法。只是把权重四舍五入到最近的量化值。快,但质量低。
GPTQ:逐组的训练后量化,最小化重建误差。是 4 位的开源标准。
AWQ(激活感知权重量化):保留处理大激活值的权重,对其余权重则更激进地量化。在 4 位 LLM 中非常流行。
GGUF(Q4_K_M、Q5_K_M 等):llama.cpp 的逐块量化格式家族。K_M 变体在体积和精度之间取得平衡。Q4_K_M 是本地推理的默认格式。
SmoothQuant:把激活异常值转移到权重中,使两者都能被干净地量化。让大模型无需太多精度损失即可实现 INT8。
QAT(量化感知训练):在训练时将量化纳入流程。质量最佳,但需要重新训练。
FP8:一种由 H100/H200 GPU 支持的硬件原生 8 位浮点格式。在训练和推理上都比 INT8 更快。
权衡取舍
质量 vs 压缩:精度越低,模型退化越多。8 位几乎是免费的;4 位是不错的默认选择;2 位会带来肉眼可见的损失。
任务敏感度:相比对话或摘要,数学、代码和长程推理受量化的冲击更大。
速度 vs 内存:量化能节省内存,但在算力充裕的 GPU 上未必总能加快推理。在内存受限的硬件(消费级 GPU、Apple Silicon)上,它能带来巨大的提速。
校准数据质量:糟糕的校准会悄无声息地毁掉量化模型。请使用有代表性的提示。
何时用哪种
跑在消费级 GPU(8 至 24 GB)上:4 位 GGUF(Q4_K_M)或 AWQ。
跑在 H100/H200 上:FP8,或配合 SmoothQuant 的 INT8。
端侧 / 移动端:激进的 4 位或 2 位 GGUF;接受质量损失。
基准研究:保留 FP16/BF16 作为参照基准;只为部署对比而量化。
高风险生产环境:8 位或 16 位。其边际成本值得换取质量保障。
常见误区
跨精度比较基准却不加说明:一个量化模型的 MMLU 分数无法与同一模型的 FP16 分数直接相提并论。
忽视困惑度漂移:即便基准看起来没问题,量化也可能损害特定能力(尤其是数学)。请在你真实的工作负载上测试。
操之过急、过于激进:从 FP16 直接跳到 INT2 而不在中间测试,会掩盖质量在何处崩坏。
使用过时的校准数据:仅在英文上校准的模型,在中文提示上会损失质量。
不测端到端延迟:量化同时影响内存加载和计算。有时吞吐量并未改善,因为瓶颈在别处。
Sources: