在第 2.1 节中我们给出过一个关键公式:全精度推理时,每 1B 参数 ≈ 2 GB 显存。一个 70B 模型需要约 140 GB 显存,这决定了它是“8 卡 A100 才能跑”还是“一张消费级显卡勉强能动”。而量化(Quantization),就是把这个数字从 2 GB 压到 0.5 GB(INT4)甚至更低的核心技术。本节从开发者视角,把主流的两种精度层级(INT8、INT4)与两种代表性算法(GPTQ、AWQ)的原理、代价和实测效果讲清楚。
一、量化的基本逻辑:把高精度数字“装进”低精度容器
1. 为什么要量化?
神经网络权重和激活值在训练时通常用 FP16(16 位浮点) 或 BF16 存储。每个参数占 2 个字节。量化就是用一个更小的数据类型(如 8 位整数或 4 位整数)来近似这些浮点数,从而直接降低存储空间和显存带宽压力。
对推理的实际收益:
- 显存占用大幅降低:参数存储直接减半(INT8)或减到约 1/4(INT4)。
- 推理加速:低精度整数运算在现代 GPU(Tensor Core)上吞吐量远高于浮点运算,且内存搬运的数据量更少,缓解了带宽瓶颈。
- 能耗降低:适合端侧、边缘设备部署。
2. 量化是怎么做的?
核心操作:将一个连续的浮点范围映射到离散的整数范围,然后用一个缩放因子(Scale)和零点(Zero-Point)记录映射关系,推理时再近似还原。
最简单的例子:假设某层权重原本分布在 [-1.0, 1.0],你想用 INT8(范围 [-128, 127])表示。那么:
- 缩放因子
S = (1.0 - (-1.0)) / (127 - (-128)) ≈ 0.0078 - 零点
Z = 0(对称量化时可为零) - 量化:
q = round(W / S) - 反量化:
W' = q × S
这种映射称为对称量化。如果权重分布不对称(例如总在 0.5 附近),还可以用非对称量化,增加零点偏移来更好地利用整数范围。
3. 量化粒度
逐层(Per-tensor)用一个 Scale 管理整个矩阵最简单,但误差大;逐通道(Per-channel) 更精细,给每个输出通道独立计算 Scale,是现代量化的基本要求,否则精度损失会不可接受。
二、INT8 量化:稳如老狗的落地标配
原理与实现
INT8 量化对权重的损失通常极小。主流做法有两种:
- 训练后量化(Post-Training Quantization, PTQ):推理前在校准数据集上跑一遍,收集每一层激活值的动态范围,确定最优 Scale。不需要重新训练,几分钟就能完成。
- 量化感知训练(Quantization-Aware Training, QAT):在训练时就模拟量化误差,让模型自己适应低精度表示。精度最高,但需要完整训练流程,目前在大模型场景下较少使用,费用太高。
对于 LLM 推理,INT8 PTQ 是性价比之王。NVIDIA 的 TensorRT-LLM 和很多推理框架(如 vLLM)都提供原生 INT8 推理支持,启用门槛极低。
效果评估
- 精度损失:在大多数自然语言理解与生成任务上,INT8 的困惑度(Perplexity)上升不到 1%,端到端任务指标(如 MMLU、HumanEval)基本持平。用户体感几乎无差异。
- 显存对比:一个 FP16 的 7B 模型需约 14 GB 显存;INT8 后约 7.3 GB(权重 + 少量 KV Cache 开销)。
- 速度提升:在 GPU 支持 INT8 Tensor Core 时,推理延迟可降低 20%–40%,吞吐量显著提升。
适用场景:追求低风险、高稳定性的生产环境,以及第一轮推理尝试。“先切 INT8,再考虑往下探”是成熟的工程习惯。
三、INT4 量化:刀尖上跳舞的极致压缩
为什么 INT4 更棘手?
INT8 有 256 个可表示值,FP16 的精度压缩进去相对从容;但 INT4 只有 16 个值,直接把权重和激活值都塞进去会导致严重失真。因此,大模型 INT4 量化通常只量化权重(Weight-only Quantization),激活值保留 FP16 或 FP8,通过校准集精细计算每通道 Scale,还需要算法层做更多优化。
主流做法
- 分组量化(Group-wise):不是逐通道,而是把权重矩阵分成更小的组(如每组 128 个元素),每组独立计算 Scale 和 Zero-Point。这样粒度更细,能更好适应局部分布的波动。
- 额外的剪枝式处理:部分算法(如 SpQR)还会识别极少数的异常值(Outliers),把它们保留在高精度,其余量化到 INT4,以极小的存储开销保住整体精度。
即便如此,单纯的“均匀量化 + 分组”在 INT4 下仍有明显精度损失。于是,GPTQ 和 AWQ 这两种专门为 LLM 设计的算法成为行业标配。
四、GPTQ:一次逼近最优的权重量化
原理逐层递进
GPTQ 的前身是 90 年代的 OBS(Optimal Brain Surgeon) 剪枝算法,核心思想是:每量化一列权重,就对剩余未量化的权重做一次补偿更新,以最小化该层输出的整体误差。
具体流程(简化的开发者视角):
- 从校准数据中抽取一批样本,跑一遍模型,收集每一层 FFN 和 Attention 矩阵的输入激活值,计算 Hessian 矩阵的逆(近似二阶信息),作为权重重要性的参考。
- 按列(或按组)遍历权重矩阵:
- 将当前列量化到 INT4(找到最优的 Scale 和 Round 方式);
- 计算量化带来的输出误差;
- 用 Hessian 逆矩阵计算出如何调整剩余未量化列的权重,以补偿这个误差。
- 逐列推进,直到整层量化完毕。
这种方法把量化问题变成了一个“全局补偿”的优化过程,误差被均摊到整个矩阵上,而非局部累积。因此,即使在极端 4-bit 压缩下,GPTQ 仍能维持相当可观的精度。
开发者需要知道的关键点
- 需要校准集:约 128 个样本即可,一般从 C4 或 WikiText-2 中随机抽取。样本内容与推理场景越接近越好,但算法对此不极端敏感。
- 分组大小:通常设为
group_size=128。组越小精度越高,但存储 Scale 的开销越大,实际压缩率会从纯权重的 4-bit 略降至约 4.25-bit。 - 运行时间:对 7B 模型,在单张 A100 上完成 GPTQ 量化大概需要 10–20 分钟;70B 模型需要数小时。属于一次性成本。
- 激活值保持 FP16:推理时需解量化权重到 FP16 再与激活值矩阵相乘,引入了少量计算开销。但显存节省是实打实的。
GPTQ 在 vLLM/TGI 等框架中的集成
GPTQ 格式有标准化的模型仓库(如 HuggingFace 上的 TheBloke 提供的各类模型)。使用 vLLM 或 TGI 部署时,直接加载 GPTQ 量化版权重,无需额外操作,框架会自动执行反量化并调用 GPU 内核。
五、AWQ:激活感知的权重量化
核心洞察:不是所有权重通道都平等
AWQ(Activation-aware Weight Quantization)的研究者发现,LLM 中权重的重要性与对应激活值的分布紧密相关。有些通道的激活值异常大(称为“显著通道”),如果这些通道的权重量化误差稍大,整个输出就会严重失真。传统均匀量化对所有通道一视同仁,于是会硬吃这个损失。
AWQ 的解决思路很巧妙:不保留异常权重(那样打破量化格局),而是在量化前,对异常通道的权重先施加一个 per-channel scaling,使它们变得更“鲁棒”,量化后再通过调整相邻层或矩阵乘法补偿回来。
具体做法:
- 跑校准集,找到激活值幅度异常大的输入通道。
- 基于激活幅度,自动搜索一个最优的 per-channel scaling factor,放大这些通道的权重(相当于让它们相对更耐受量化误差)。
- 将 scaling 因子吸收进前一层 LayerNorm 或后一层矩阵乘法中,不会增加额外推理开销。
- 执行标准的组量化(Group-wise INT4)。
AWQ 的实质,是用极低代价(只引入 per-channel scaling,没有复杂的二阶优化)达到甚至超越 GPTQ 的精度。
与 GPTQ 的直观对比
| 对比维度 | GPTQ | AWQ |
|---------|------|-----|
| 核心思想 | 逐列量化 + 全局误差补偿(二阶信息) | 激活感知的通道缩放 + 标准量化 |
| 校准集需求 | 需要,计算 Hessian | 需要,但主要用于搜索 scaling |
| 量化速度 | 中等(需计算 Hessian 逆) | 更快(无二阶优化) |
| 推理开销 | 反量化到 FP16 | 反量化到 FP16(scaling 已融合) |
| 精度(同 4bit) | 极高,广泛验证 | 优秀,通常与 GPTQ 持平或略优 |
| 框架支持 | vLLM、TGI、AutoGPTQ 等主流 | vLLM 原生支持,TGI 现也支持 |
| 多模态/Long Context | 适应性好 | 特别适合,因激活模式差异大时 AWQ 能自适应 |
简单选型指南:如果框架支持 AWQ,优先尝试 AWQ(速度快、精度略优、更适合长上下文或多模态);如果已有成熟的 GPTQ 量化模型仓库或硬件兼容性要求,GPTQ 同样极其可靠。
六、实战效果对比与显存速算
效果衰减一览(以 Llama 3 8B 与 70B 为例,取自公开评测与社区反馈)
| 精度 | 权重存储 | 8B 困惑度涨幅 | 8B 常识/推理任务降幅 | 70B 困惑度涨幅 | 70B 推理任务降幅 |
|------|---------|--------------|-------------------|---------------|------------------|
| FP16 | 16 位 | 基线 | 基线 | 基线 | 基线 |
| INT8 | 8 位 | < 0.5% | 不可感知 | < 0.3% | 不可感知 |
| GPTQ 4bit (g128) | 4.25 位 | 1%–3% | 1%–3% (MMLU/GSM8K) | < 1% | 基本持平 |
| AWQ 4bit (g128) | 4.25 位 | 1%–2.5% | 1%–2% 或略优 GPTQ | < 1% | 基本持平 |
| 纯均匀 INT4 逐通道(无补偿) | 4 位 | 5%–10%+ | 明显劣化 | 3%–8% | 部分任务崩溃 |
注意:小模型(8B)对 4bit 量化比大模型(70B)更敏感。70B 参数冗余度更高,压缩后精度更容易保持。
显存速算(以 Llama 3 8B 为例,单卡推理,不含长上下文 KV Cache)
| 方案 | 参数显存 | KV Cache(以 4K 上下文为例) | 总计约 | 推荐最低 GPU 显存 |
|------|---------|----------------------------|--------|------------------|
| FP16 | 约 16 GB | 约 1 GB | 17 GB | 24 GB (RTX 3090/4090) |
| INT8 | 约 8 GB | 约 1 GB | 9 GB | 16 GB (RTX 4060 Ti 16G) 稳定 |
| GPTQ/AWQ INT4 | 约 4 GB | 约 1 GB | 5 GB | 8 GB 甚至更低(但 KV Cache 随长度增长仍需关注) |
核心结论:INT8 几乎零代价;INT4 在小模型上需要测试验证,但在 30B 以上模型上可以放心作为生产方案。GPTQ 和 AWQ 目前是 4-bit 量化的双雄,选择一个取决于你用的部署框架和校准成本偏好。
七、开发者落地 checklist
- 先试 INT8:如果你的 GPU 显存刚好擦边,INT8 是最低风险的选择。在 vLLM 中加
--quantization int8即可。 - 4-bit 量化请用 GPTQ 或 AWQ:不要自己手动写均匀量化,直接用社区成熟的量化脚本(AutoGPTQ、llm-awq)或 HuggingFace 上现成的量化版模型权重。
- 校准集最好与业务数据分布一致:虽然算法不极端敏感,但若你主要处理中文医疗文本,用英文 Wiki 校准会有额外波动。用 100–200 条目标域句子是最佳实践。
- 长上下文场景优先验证:KV Cache 在长上下文(> 32K)时可能占用比量化权重还多的显存。此时显存优化重心会转向 KV Cache 量化(8-bit 或 4-bit),权重量化的相对收益会缩小。
- 混合精度策略:部分框架支持“关键层保留 FP16 + 其他层 INT4”的混合量化。如果你对某个具体任务精度敏感,可尝试定位导致崩溃的层,手动排除或提升其精度。
在第 22.3 节中,我们将讨论如何将量化后的模型与 KV Cache 优化、连续批处理等技术结合,在保持低延迟的前提下进一步提升吞吐量。量化是推理成本优化的起点,而非终点。