quantization(量化)就是把模型参数从高精度数值(如 FP16,每个参数 2 字节)改用低精度表示(INT8 1 字节、INT4 半字节)。它之所以可行,靠的是两个互相独立的事实。
事实一:权重是冗余的。神经网络严重过参数化,单个权重的精确数值并不重要,重要的是它们共同构成的函数。把一个权重从 0.1374 近似成 0.14,对最终输出的影响通常小到看不见——只要这个误差不系统性地累积。量化的全部技术难度都在「怎么让误差不累积」上。
事实二:推理是访存受限的。如 1.3 所述,解码阶段的瓶颈是把权重从显存搬进计算单元。参数从 2 字节压到 0.5 字节,要搬的数据直接少了 4 倍——即使计算时再解压回高精度做乘法,也仍然更快。这就是所谓 weight-only quantization(仅权重量化)能加速的原因:它省的是带宽,不是算力。
请注意这个计算真正的含义:量化改变的往往不是「快多少」,而是「能不能跑」。它把一个模型从「需要 A100」变成「一张消费级卡就够」,或者把省下的显存让给 KV cache 从而支持更大的并发——后者常常才是生产环境里更值钱的收益。
量化的基本操作是把一段浮点数值范围线性映射到有限的整数格子上。这个映射的精度取决于范围:范围越宽,每个格子代表的区间越大,误差越大。而 Transformer 的激活值里存在outlier(离群值)——极少数维度上的数值比其他维度大出几个数量级。
一个离群值就足以把整个张量的数值范围撑大几十倍,导致其余 99.9% 的正常值全部被挤进极少数格子里,信息几乎损失殆尽。这就是为什么「INT8 在小模型上好好的,换到大模型就崩了」——离群值现象随模型规模增长而涌现。
| 维度 | 选项 | 关键差别 |
|---|---|---|
| 量化什么 | 仅权重 / 权重+激活 / KV cache | 仅权重省带宽与显存,是低并发场景的主力;权重+激活才能用上低精度算力单元,高并发大 batch 收益更大;KV cache 量化直接放大并发上限(见 1.2) |
| 什么时候量化 | PTQ 训练后 / QAT 训练时 | PTQ(post-training quantization)拿现成模型直接压,几分钟到几小时,是绝大多数应用层场景的默认选择;QAT(quantization-aware training)在训练中模拟量化误差,质量更好但要重训,成本高得多 |
| 粒度多细 | per-tensor / per-channel / per-group | 分组越细,离群值的污染范围越小、质量越好,但元数据开销和 kernel 复杂度越高。per-group(如每 128 个权重一组)是常见折中 |
面试与实践中最常见的混淆是第一条:「量化后更快」这句话必须问清是哪种量化、什么 batch。仅权重量化在 batch=1 的本地推理上提速明显,但在大 batch 的服务端场景里,瓶颈已经从带宽转向算力,此时若计算仍要解压回 FP16 进行,加速会明显缩水甚至反向。
LLM.int8() 首先把问题指认清楚。Dettmers 等人发现离群特征是系统性涌现的,而非随机噪声:
这组数字的分量在于:占比 0.1% 的一小撮维度,删掉就让模型崩溃——它们不是可以被平均掉的噪声,而是模型功能的关键载体。解法随之确定:把这 0.1% 单独用高精度矩阵乘法算,其余 99.9% 走 INT8,两部分结果再合并。
GPTQ 换了一条路:更聪明地逼近。它基于近似二阶信息逐层做一次性量化,把误差沿权重矩阵有序补偿掉。论文报告可在约 4 个 GPU 小时内把 175B 规模的模型量化到 3–4 bit;对 OPT-175B 做 3-bit 量化后困惑度为 8.68,全精度基线为 8.34。这使得 175B 模型首次得以在单张 GPU 上做生成式推理。
AWQ 则从「哪些权重重要」入手。它的核心观察是权重并非同等重要——保护约 1% 的显著权重就能大幅降低量化误差;而判断哪些权重显著,要看激活值分布而不是看权重本身。它通过搜索逐通道缩放系数来保护这部分权重,不需要反向传播或重建,因而不易过拟合校准集。论文报告其实现相对 HuggingFace FP16 实现取得超过 3 倍的加速,并获 MLSys 2024 最佳论文奖。
把三者放在一起看,你会看到同一个问题的三种应对姿势:隔离(LLM.int8())、补偿(GPTQ)、重分配(AWQ)。这个「异常值要么隔离、要么补偿、要么归一」的模式在系统工程里到处都是——记住模式比记住方法名有用得多。
GPTQ / AWQ:4-bit 仅权重量化的两大主流 PTQ 方案,主流推理框架普遍支持,社区已有大量预量化权重可直接下载。AWQ 因不依赖反向传播,通常被认为对校准集更鲁棒。
FP8:较新硬件(Hopper 及之后的 NVIDIA GPU 等)提供原生 FP8 算力,可同时量化权重与激活,能真正吃到低精度算力单元的加速,在高并发服务端场景优于仅权重的 INT4。代价是需要对应的硬件。Blackwell 起还原生支持 4-bit 浮点格式 NVFP4 / MXFP4,可降低被量化张量的占用;整机显存、带宽与速度的收益取决于配方、模型、负载和后端。注意区分格式本身和具体配方:同一种 FP4 格式,有的模型只量化权重(W4A16),有的权重与激活一起量化(W4A4),能否吃到 FP4 算力取决于所用模型与推理后端,质量需按任务评测。
GGUF / llama.cpp 系:面向本地与 CPU/端侧推理的格式,提供从 2-bit 到 8-bit 的多档方案,命名如 Q4_K_M;社区经验一般认为 4-bit 及以上档位在多数任务上可用,2-bit 档位质量风险明显。
KV cache 量化:与权重量化正交,可叠加。FP8 / INT8 KV cache 已在主流框架落地,直接换来更大并发或更长上下文——在显存受限的服务端,这一项的性价比常被低估。
选型顺序建议:先问「是显存装不下,还是速度不够?」显存问题优先考虑 4-bit 仅权重 + KV cache 量化;速度问题且硬件支持,则在目标硬件、模型与负载上比较 FP8 和可用的 FP4 配方,实测吞吐、延迟与质量后再选。无论选哪条,都必须在自己的 eval 集上跑回归——公开榜单上的平均分掩盖不了你特定任务上的退化。
权重:FP16 = 13B × 2 = 26 GB → 根本装不下,24GB 卡直接出局。INT4 = 13B × 0.5 ≈ 6.5 GB,加上量化元数据与运行时开销按 7.5 GB 估。
留给 KV cache:24 − 7.5 − 激活/框架开销(保守留 2 GB)≈ 14.5 GB。
换算成 token 预算:套 1.2 的公式,per-token = 2 × 40 × 5120 × 2 bytes ≈ 800 KB。14.5 GB / 800 KB ≈ 约 1.9 万 token——例如 9 条 2K 上下文的并发请求。
进一步:若同时启用 INT8 KV cache,per-token 减半,token 预算翻倍到约 3.8 万。注意这里发生了什么:权重量化决定了「能不能跑」,KV cache 量化决定了「能跑多少并发」——两个不同的问题,需要两个不同的旋钮。
因为两个场景的瓶颈不同。本地 batch=1:解码严格受显存带宽限制,权重搬运量减少 4 倍直接转化为提速。服务端大 batch:一次权重读取被摊薄到几十条序列上,瓶颈已从带宽转向算力;此时若 kernel 仍需把 INT4 解压回 FP16 做乘法,反而增加了解压开销,净收益可能很小。
推论:服务端要拿到真加速,需要的是权重与激活同时低精度、并有原生低精度算力支持的方案(如 FP8)。这也是「量化能加速吗」这个问题必须先问「batch 多大、量化什么」的原因。
错误是用平均分代替了任务级回归测试。公开基准的综合分是大量异质任务的平均,1% 的整体下滑完全可能由某一类能力的显著退化构成,而这类能力恰好是你的产品依赖的。
格式遵循、长程一致性、少数语言的能力、工具调用参数的准确性——这些「窄而关键」的能力在综合基准里权重很低,却往往是量化后最先受损的部分。
正确做法:量化是一次模型变更,必须走和换模型同等规格的流程——用你自己的、覆盖真实任务分布的 eval 集做回归(6.4),关键指标(如 JSON 可解析率)单独设阈值,并优先灰度而非全量切换。另外,格式稳定性问题本身也有比「不量化」更直接的解法:constrained decoding(约束解码)。
核心是离群特征随规模涌现。LLM.int8() 的测量显示,在 6.7B 参数规模上,离群特征开始在所有 Transformer 层中一致地出现(更小的模型里,各层对「用哪个维度承载大数值」尚未达成一致)。这些离群值只占约 0.1% 的特征,却承载着关键信息——把它们置零会让困惑度劣化 600–1000%。
而量化的精度取决于数值范围,一个比其余值大几个数量级的离群值会把范围撑爆,让 99.9% 的正常值挤进极少数量化格子。所以难点不是「参数多」,而是「参数的数值分布出现了长尾结构」。
能补一句会更好:这也解释了为什么解法都围绕范围做文章——隔离离群值(混合精度)、缩小分组范围(per-group)、或把离群值的影响等价地转移出去(缩放)。