第4章:量化
掌握 W8A8(SmoothQuant)、INT4(GPTQ/AWQ)、KV Cache 量化和 FP8 量化的原理与选型决策
量化是推理优化”用精度换显存 / 带宽 / 算力”的核心手段——一个 70B FP16 要 140 GB 显存,INT4 量化后只剩 35 GB,单卡就能跑;FP8 GEMM 算力是 BF16 的 2 倍。本章系统覆盖 W8A8(SmoothQuant)、INT4(GPTQ/AWQ)、KV Cache 量化、FP8 量化的原理与工程选型。
📑 目录
- 1. 量化基础概念
- 2. W8A8:SmoothQuant
- 3. Weight-only INT4:GPTQ 与 AWQ
- 4. KV Cache 量化:长上下文救星
- 5. FP8:Hopper 时代的新宠
- 6. 选型决策与精度评估
- 自我检验清单
- 参考资料
1. 量化基础概念
1.1 量化的数学
把 FP16 张量 量化到 INT8:
- (scale):缩放因子
- (zero point):零点(对称量化时为 0)
1.2 对称 vs 非对称
| 类型 | 公式 | 适用 |
|---|---|---|
| 对称 | 权重(分布对称) | |
| 非对称 | , 调整 | 激活(ReLU 后偏正) |
1.3 量化粒度
| 粒度 | 共享 scale 范围 | 精度 | 速度 |
|---|---|---|---|
| Per-tensor | 整个 tensor 一个 scale | 低 | 最快 |
| Per-channel | 每个输出通道一个 scale | 中 | 快 |
| Per-group | 每 g 个权重一个 scale(g=32/64/128) | 高 | 中等 |
| Per-token (动态) | 每个 token 一个 scale(激活用) | 高 | 较慢 |
🌟 经验:权重 per-channel 或 per-group,激活 per-token,综合最佳。
1.4 PTQ vs QAT
| 方法 | 全称 | 流程 | 适用 |
|---|---|---|---|
| PTQ | Post-Training Quantization | 训练后用少量校准数据求 scale | 大模型主流(快、省) |
| QAT | Quantization-Aware Training | 训练时模拟量化,反传梯度 | 精度敏感场景 |
LLM 几乎全部用 PTQ——QAT 对 100B+ 模型代价太高。
2. W8A8:SmoothQuant
2.1 直接量化激活的问题
LLM 激活有显著的 outlier(某些通道的值是其他通道的 100 倍以上),直接 per-tensor 量化会让大部分通道精度损失严重(scale 被 outlier 拉得太大)。
2.2 SmoothQuant 的等价变换
把激活的”难度”(outlier)转移到权重上——权重容易量化,激活变得 smooth。
scale 的选择:
是常用值,效果稳定。
2.3 收益
- W8A8 整张图(GEMM 用 INT8 算力)
- 显存:模型大小 ÷ 2
- 算力:INT8 Tensor Core ≈ FP16 的 2×
- 精度:LLaMA-7B 在 WikiText 困惑度上升 < 0.5%
2.4 用法
from vllm import LLM
llm = LLM(model="...", quantization="smoothquant", ...)
或预量化好的 GGUF / safetensors 文件:
llm = LLM(model="path/to/llama-7b-w8a8")
3. Weight-only INT4:GPTQ 与 AWQ
3.1 思路
只把权重量化到 INT4(激活仍 FP16),compute 时把 INT4 权重 dequant 回 FP16 再算:
INT4 权重(磁盘/显存)
↓ dequant 到 FP16
GEMM (FP16 × FP16)
- ✅ 显存大幅降低(权重 ÷ 4)
- ✅ HBM 带宽降低(memory bound 算子加速明显)
- ❌ Compute 不加速(因为还是 FP16 GEMM)
适合 memory bound 场景:Decode 阶段、batch 小的服务。
3.2 GPTQ:基于 Hessian 的逐层量化
逐层处理,基于二阶信息(Hessian)选 scale,使量化误差对最终输出的影响最小。
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
quantize_config = BaseQuantizeConfig(
bits=4, group_size=128, desc_act=False,
)
model = AutoGPTQForCausalLM.from_pretrained("Llama-7b", quantize_config)
model.quantize(calib_dataset) # 几十条样本即可
model.save_quantized("Llama-7b-gptq-int4")
3.3 AWQ:基于 Activation 分布保护重要权重
观察:权重的重要性由对应的激活幅值决定——激活大的通道,对应权重的精度更重要。AWQ 给重要通道更宽的 scale 范围,精度更好。
from awq import AutoAWQForCausalLM
model = AutoAWQForCausalLM.from_pretrained("Llama-7b")
model.quantize(quant_config={"w_bit": 4, "q_group_size": 128})
model.save_quantized("Llama-7b-awq")
3.4 GPTQ vs AWQ
| 维度 | GPTQ | AWQ |
|---|---|---|
| 精度 | 中-高 | 高 |
| 速度(校准) | 较慢(算 Hessian) | 快 |
| 推理速度 | 一致 | 一致 |
| 工业偏好 | 老 | 新项目首选 |
3.5 Marlin Kernel:让 INT4 真正快
朴素的”INT4 dequant 到 FP16 再 GEMM”在小 batch 下反而比 FP16 慢,因为 dequant 开销太大。
Marlin 是 INT4 × FP16 的高性能融合 kernel:
- 避免显式 dequant,直接 fused 运算
- batch=1-32 时 1.5-2× FP16 性能
- 工业级实现,vLLM、TensorRT-LLM 都集成
llm = LLM(model="...-awq", quantization="awq_marlin") # 启用 Marlin
4. KV Cache 量化:长上下文救星
4.1 动机
长上下文(32K-128K)场景,KV Cache 占显存的大头甚至超过权重。把 KV 从 BF16 量化到 INT8 / INT4 / FP8,显存直接 ÷ 2 / ÷ 4,并发能力翻倍。
4.2 KIVI:2-bit KV 量化
KIVI 论文证明:Key 用 per-channel 量化,Value 用 per-token 量化——这样可以做到 2-bit,精度损失 <1%。
| 量化方式 | KV 大小 | 精度 |
|---|---|---|
| BF16 | 100% | 基线 |
| INT8 | 50% | -0.1% |
| INT4 | 25% | -0.5% |
| KIVI 2-bit | 12.5% | -0.8% |
4.3 工程实现
# vLLM
llm = LLM(model="...", kv_cache_dtype="fp8") # 或 "fp8_e5m2"
需要专门的 paged attention kernel 支持 mixed-precision——FlashInfer / vLLM 都已实现。
5. FP8:Hopper 时代的新宠
5.1 FP8 两种格式
| 格式 | 指数 | 尾数 | 范围 | 精度 | 用途 |
|---|---|---|---|---|---|
| E4M3 | 4 | 3 | 较高 | 权重 / 激活(forward) | |
| E5M2 | 5 | 2 | 较低 | 梯度(范围更重要) |
5.2 FP8 GEMM 优势
H100 的 FP8 Tensor Core 算力 = 1979 TFLOPS = 2× FP16。Decode 阶段可以:
- 显存:权重 + KV 都 FP8,显存 ÷ 2
- 算力:GEMM 速度 2×
5.3 动态 Scaling
FP8 范围窄,每个 tensor 的 scale 必须动态调整。NVIDIA Transformer Engine 自动处理:
import transformer_engine.pytorch as te
from transformer_engine.common.recipe import Format, DelayedScaling
fp8_recipe = DelayedScaling(fp8_format=Format.HYBRID)
with te.fp8_autocast(enabled=True, fp8_recipe=fp8_recipe):
out = te_module(x)
5.4 vLLM FP8
llm = LLM(model="...-fp8", quantization="fp8", kv_cache_dtype="fp8")
DeepSeek-V3、LLaMA-3 都有官方 FP8 权重发布,直接用即可。
6. 选型决策与精度评估
6.1 决策树
目标?
├─ 单卡装下大模型(显存优先)
│ ├─ 略微精度损失可接受 → AWQ INT4
│ └─ 不能损失 → SmoothQuant W8A8 / FP8
│
├─ 加速 Decode(batch 小)
│ └─ AWQ + Marlin (memory bound 加速)
│
├─ 加速 Prefill / 大 batch (compute bound)
│ ├─ Hopper(H100) → FP8
│ └─ Ampere(A100) → SmoothQuant W8A8
│
├─ 长上下文(32K+)
│ └─ KV Cache 量化(INT8 / FP8 / KIVI)
│
└─ 多种叠加
└─ 权重 INT4 + KV INT8 + FP8 GEMM(各自独立)
6.2 精度评估三件套
# 1. 困惑度 PPL(技术指标)
def calculate_ppl(model, dataset):
total_loss, total_len = 0, 0
for text in dataset:
ids = tokenizer.encode(text, return_tensors='pt').cuda()
with torch.no_grad():
loss = model(ids, labels=ids).loss
total_loss += loss.item() * ids.shape[1]
total_len += ids.shape[1]
return math.exp(total_loss / total_len)
# 2. Benchmark 集(MMLU / HumanEval / GSM8K)
# lm-eval-harness:https://github.com/EleutherAI/lm-evaluation-harness
# 3. 人工对比(关键!)
# 准备 50 条业务相关 prompt,FP16 vs 量化版结果并排,人工打分
🌟 量化的金科玉律:所有量化必须在你的目标场景上做精度验证,不要相信论文上的”无损”。
6.3 实测对比模板
| 配置 | 显存 | TTFT | TPOT | Throughput | MMLU | 人工评价 |
|---|---|---|---|---|---|---|
| FP16 | 140 GB | 100ms | 30ms | 3000 tps | 65.2 | 5.0 |
| W8A8 | 70 GB | 80ms | 25ms | 4500 tps | 64.8 | 4.9 |
| AWQ INT4 | 35 GB | 95ms | 22ms | 5500 tps | 63.5 | 4.7 |
| FP8 | 70 GB | 60ms | 18ms | 6000 tps | 65.0 | 5.0 |
✅ 自我检验清单
- 量化数学:能写出对称量化的公式和 zero point 含义
- 粒度选择:能解释为什么权重 per-channel / 激活 per-token 是最佳实践
- SmoothQuant 直觉:能解释”把激活的难度转移到权重”的等价变换
- GPTQ vs AWQ:能对比两者的核心差异,以及为什么 AWQ 是新项目首选
- INT4 反直觉:能解释为什么 INT4 不一定比 INT8 快(dequant 开销)
- Marlin 作用:能解释为什么 INT4 + Marlin 才能在小 batch 下真正加速
- KV 量化:能解释为什么 Key per-channel + Value per-token 的 KIVI 设计
- FP8 vs INT8:能列出 FP8 在 H100 上相对 INT8 的优势(算力、原生 Tensor Core 支持)
- 选型实战:给一个”70B 单卡 80GB”的需求,能给出最优量化方案
- 精度验证:能设计一套量化前后的对比评估方案
📚 参考资料
论文
- SmoothQuant (Xiao et al., 2022):https://arxiv.org/abs/2211.10438
- GPTQ (Frantar et al., 2022):https://arxiv.org/abs/2210.17323
- AWQ (Lin et al., 2023):https://arxiv.org/abs/2306.00978
- KIVI (Liu et al., 2024):https://arxiv.org/abs/2402.02750
- Marlin (Frantar et al.):https://arxiv.org/abs/2408.11743
- FP8 Formats for Deep Learning (Micikevicius et al., 2022):https://arxiv.org/abs/2209.05433
工具
- AutoAWQ:https://github.com/casper-hansen/AutoAWQ
- AutoGPTQ:https://github.com/AutoGPTQ/AutoGPTQ
- Transformer Engine:https://github.com/NVIDIA/TransformerEngine
- lm-evaluation-harness:https://github.com/EleutherAI/lm-evaluation-harness