跳到主要内容

模型量化基础

用低精度表示高精度数值,在可控精度损失下将显存压缩 2-4 倍、推理速度提升 1.5-3 倍

核心概念(含 Mermaid 图)

什么是量化

量化(Quantization)是将连续的高精度数值映射到离散的低精度表示的过程。在 LLM 推理中,就是把模型权重、激活值、KV Cache 从 FP32/FP16/BF16 转换为 INT8/INT4/FP8 等低精度格式。

核心收益

  • 显存节省:FP16 → INT8 减半,FP16 → INT4 压缩到 1/4
  • 速度提升:低精度 GEMM 在 Tensor Core 上吞吐量更高
  • 能耗降低:低精度访存带宽消耗更小

精度演进:FP32 → FP16 → INT8 → INT4 → FP8

量化的数学原理

均匀量化公式

最常用的对称均匀量化公式:

量化: q = round(x / s) + z
反量化: x_hat = (q - z) * s

其中:
x → 原始浮点值
q → 量化后的整数(INT8 范围 [-128, 127])
s → 缩放因子 scale = max(|x|) / 127
z → 零点 zero-point(对称量化时 z=0)
x_hat → 反量化后的近似值

示例:权重范围为 [-3.2, 3.2],对称 INT8 量化

s = 3.2 / 127 ≈ 0.0252
x = 1.5 → q = round(1.5 / 0.0252) = round(59.52) = 60
反量化: x_hat = 60 * 0.0252 = 1.512 → 误差 0.012

非对称量化

当数据分布不对称时(如激活值 ReLU 后全为正),使用非对称量化:

q = round((x - x_min) / (x_max - x_min) * 255)
反量化: x_hat = q * (x_max - x_min) / 255 + x_min

此时零点 z = round(x_min / s),用于对齐浮点 0 到整数 0。

缩放粒度

粒度说明典型场景精度开销
per-tensor整个 tensor 共用一个 scale简单 PTQ较低最低
per-channel每个输出通道独立 scale权重量化
per-group每组(如 128 个)权重独立 scaleINT4 量化最高
per-token每个 token 独立 scale激活量化

为什么量化能节省显存:具体字节数对比

70B 模型在不同精度下的显存占用:

FP32: 70B × 4 bytes = 280 GB → 需要 4× A100-80G
FP16: 70B × 2 bytes = 140 GB → 需要 2× A100-80G
INT8: 70B × 1 byte = 70 GB → 1× A100-80G
INT4: 70B × 0.5 byte = 35 GB → 1× A100-80G,余量可加大 batch
FP8: 70B × 1 byte = 70 GB → 1× A100-80G/H100-80G

加上 KV Cache 后的完整显存预算(batch=16, seq=8192, GQA-8):
FP16 权重 + FP16 KV: 140 + 64 = 204 GB → OOM on 1× A100
INT8 权重 + INT8 KV: 70 + 32 = 102 GB → OOM on 1× A100
INT4 权重 + INT8 KV: 35 + 32 = 67 GB → 可行!余量给激活值

为什么量化能提升速度

NVIDIA GPU Tensor Core 理论吞吐量(TFLOPS,以 A100-80G 为例):

FP32: 19.5 TFLOPS
TF32: 156 TFLOPS (8x FP32)
FP16: 312 TFLOPS (16x FP32)
BF16: 312 TFLOPS (16x FP32)
INT8: 624 TFLOPS (32x FP32) → INT8 GEMM 是 FP16 的 2x
FP8(E4M3):1979 TFLOPS (H100) → FP8 是 FP16 的 ~6x (H100)

带宽角度(A100-80G HBM2e):
HBM2e 带宽: 2.0 TB/s
INT8 权重体积是 FP16 的 1/2 → 权重访存时间减半
对于 weight-bound 的 decode 阶段,直接转化为延迟减半

实际推理加速比(decode 阶段,batch=1):
FP16 → INT8: ~1.5-2x
FP16 → INT4: ~2-3x
FP16 → FP8 (H100): ~1.5-2x

量化精度损失的来源

精度损失的三大来源:

1. 截断误差(Clipping)
- 超过量化范围的异常值被截断到 max/min
- 影响:权重分布中的 outlier 被削平
- 缓解:扩大量化范围或使用非对称量化

2. 舍入误差(Rounding)
- round(x/s) 引入的最大误差 = s/2
- 影响:所有值都有微小扰动,累积后可能显著
- 缓解:更细粒度的 per-group/per-token 量化

3. 异常值敏感性(Outlier Impact)
- LLM 中存在少量 extreme activation(magnitude 远超其他值)
- 这些 outlier 撑大了 scale,导致普通值的量化粒度变粗
- 影响:这是 LLM 量化最大的精度杀手
- 缓解:SmoothQuant / AWQ 等异常值感知方案

Post-training Quantization (PTQ) vs Quantization-Aware Training (QAT)

维度PTQQAT
原理直接用校准数据计算 scale,不更新权重在训练中模拟量化噪声,微调权重
训练成本极低(只需少量校准数据)高(需要 full training loop)
精度INT8 接近无损,INT4 有明显损失INT4 可接近 FP16
适用场景INT8 推理、快速部署INT4 极限压缩、对精度要求极高
校准数据100-1000 条样本即可需要完整训练集或大语料
时间分钟级小时到天级
代表工具AWQ、GPTQ、SmoothQuantQLoRA、LLM-QAT

各主流模型对量化的原生支持

模型INT8 PTQINT4 PTQFP8推荐方案
Llama 3/3.1 8B✅ 无损✅ MMLU -0.5AWQ INT4
Llama 3.1 70B✅ 无损✅ MMLU -1.0AWQ INT4
Qwen2.5 7B/72B✅ 无损GPTQ INT4
Mistral 7B✅ 无损AWQ INT4
Mixtral 8x7B⚠️ MoE 量化复杂SmoothQuant INT8
DeepSeek-V3⚠️ MLA 特殊⚠️✅ H100原生 FP8
GPT-4 / ClaudeN/AN/AN/A闭源

部署视角

量化决策树

生产环境量化检查清单

  • 在目标硬件上测试量化后推理速度(不要只看理论 TFLOPS)
  • 用 200+ 条校准数据跑 PTQ,覆盖典型输入分布
  • 量化后跑 MMLU/GSM8K/代码生成等关键 benchmark,确认损失 < 2%
  • 验证极端长上下文场景(quantization 对长序列更敏感)
  • INT4 量化后检查 token 生成质量(是否有重复、乱码)
  • 监控量化后推理的 P99 延迟(确保无退化)

量化与 vLLM/SGLang 的兼容性

引擎INT8 权重INT4 权重INT8 KV CacheFP8
vLLM✅ (AWQ/GPTQ)✅ (H100)
SGLang✅ (AWQ/GPTQ)✅ (H100)
TensorRT-LLM
Ollama✅ (GGUF)

面试视角

面试官常问问题

Q1: "简单解释一下量化是什么?为什么 LLM 可以量化?"

满分回答要点:

  • 量化 = 用低精度整数近似高精度浮点,核心公式 q = round(x/s) + z
  • LLM 可以量化是因为权重分布相对集中,大部分值在 [-3, 3] 范围内
  • INT8 有 256 个离散值,步长约 0.02,对多数权重来说足够精细
  • 激活值中存在 outlier 是主要挑战,需要特殊处理

Q2: "INT8 量化会导致多少精度损失?什么情况下损失最大?"

满分回答要点:

  • 标准 PTQ INT8 在 Llama/Mistral 等模型上 MMLU 损失 < 0.5%
  • 损失最大的场景:激活值 outlier 严重(per-tensor 量化时 scale 被 outlier 撑大)
  • 模型越大,量化越友好(大模型本身有冗余容量)
  • 长文本生成比分类任务对量化更敏感

Q3: "量化的 trade-off 是什么?什么时候不该量化?"

满分回答要点:

  • Trade-off 三角:精度 vs 压缩率 vs 部署成本
    • INT8:精度几乎无损,压缩 2x,部署成本极低 → 首选
    • INT4:压缩 4x,但 MMLU 可能掉 1-3%,需要仔细验证
    • FP8:需要 H100 硬件,但精度接近 FP16,吞吐大幅提升
  • 不该量化的场景
    • 数学推理、代码生成等对精度极度敏感的任务
    • 模型本身已经很小(7B 以下),量化收益有限
    • 硬件不是瓶颈(显存充足、吞吐满足 SLA)
    • 需要 FP16 做后续微调或 LoRA adapter

Q4: "为什么 INT8 GEMM 比 FP16 GEMM 快?"

满分回答要点:

  • 硬件层面:INT8 Tensor Core 每个 cycle 可以处理更多 MAC 操作(INT8 是 FP16 的 2x 吞吐)
  • 访存层面:INT8 权重占 FP16 一半内存,HBM 带宽减半 → weight-bound 的 decode 阶段直接受益
  • 但注意:在 compute-bound 的 prefill 阶段,加速比可能小于 2x
  • 实际加速比还取决于是否 fused dequantize(反量化是否和 GEMM 融合)

Q5: "per-tensor、per-channel、per-group 量化各适用于什么场景?"

满分回答要点:

  • per-tensor:最简单,适合激活值量化(同一 batch 内分布相近),但对 outlier 敏感
  • per-channel:每个输出通道独立 scale,适合权重量化(不同 neuron 的 magnitude 差异大)
  • per-group:如每 128 个权重一个 scale,适合 INT4(16 级量化需要更细粒度补偿)
  • 选择原则:精度要求越高,粒度越细,但计算/存储 overhead 越大

最佳实践

量化入门推荐

  • 第一步:先用 INT8 AWQ 或 SmoothQuant,几乎无损,部署简单
  • 第二步:如果显存仍然紧张,尝试 INT4 AWQ,验证精度
  • 第三步:如果有 H100,直接上 FP8,精度和速度兼得

避坑指南

  • INT4 量化后用 GSM8K 和代码生成验证,不要只看 MMLU
  • 校准数据要覆盖业务真实分布(不能只用 Wikipedia)
  • per-group INT4 的 group_size 设为 128 是 sweet spot(64 太碎,256 太粗)
  • 量化后第一次推理可能很慢(dequantize kernel 预热),多做几次 warmup
  • MoE 模型量化要特别注意,router 权重对精度极其敏感,建议 INT8 而非 INT4
  • GGUF 格式(llama.cpp)的量化和 AWQ/GPTQ 不同,量化等级标记方式不同(Q4_K_M vs Q8_0)

下一节:量化方案详解