跳转至

量化基础与方法

量化用更低位宽表示权重、激活或 KV Cache,目标是降低模型容量、内存流量和计算成本。文件变小不等于推理一定变快:只有目标硬件、Kernel、Packing、反量化与算子覆盖共同匹配,压缩收益才会变成端到端性能。

仿射量化

对浮点值 \(x\),常见仿射量化可写为:

\[ q = \mathrm{clamp}\left(\mathrm{round}\left(\frac{x}{s}\right)+z, q_{min}, q_{max}\right) \]
\[ \hat{x} = s(q-z) \]

其中 \(s\) 是 Scale,\(z\) 是 Zero Point,\(q\) 为低比特整数,\(\hat{x}\) 为反量化近似值。

设计维度 选择 权衡
数值格式 INT8/INT4、FP8、其他低精度 动态范围、精度、硬件指令与存储密度不同
对称性 对称 / 非对称 对称计算简单;非对称可更贴合偏移分布但有 Zero Point 开销
粒度 Per-Tensor / Channel / Group / Token 粒度越细通常误差越小,但 Scale 元数据和 Kernel 复杂度更高
对象 Weight / Activation / KV Cache 容量、带宽和误差传播位置不同
时机 静态 / 动态 静态依赖 Calibration;动态适应输入但运行时统计有成本
训练需求 PTQ / QAT PTQ 快;QAT 训练成本更高但更能适应量化噪声

常见部署记法

记法 含义 常见系统收益 主要风险
W8A8 8-bit Weight + 8-bit Activation 可减少权重/激活流量并使用整数矩阵路径 Activation Outlier、算子覆盖
W4A16 4-bit Weight + FP16/BF16 Activation 权重容量与 Decode 权重带宽显著下降 运行时解包/反量化,未必有原生 4-bit 计算
FP8 FP8 Weight/Activation 或部分张量 更大动态范围,匹配新一代矩阵硬件 Format/Scale 策略与硬件代际相关
KV8/KV4 低比特 KV Cache 长上下文和高并发下节省容量/带宽 Attention 精度、量化粒度与 Cache Kernel

Accumulator 往往保留更高精度

输入和权重使用低精度不代表累加也采用同样位宽。矩阵单元常将乘法输入与累加精度分开,以控制长 Reduction 的误差;必须以目标指令和 Kernel 的真实语义为准。

PTQ 与 QAT

flowchart LR
    FP[浮点模型] --> CHOICE{是否重新训练?}
    CHOICE -->|否| CAL[Calibration / 统计]
    CAL --> PTQ[PTQ<br/>选择 Scale / Clip / 重构]
    CHOICE -->|是| FQ[插入 Fake Quant / Observer]
    FQ --> TRAIN[QAT<br/>让权重适应量化噪声]
    PTQ --> EXPORT[量化权重 + 配置]
    TRAIN --> EXPORT
    EXPORT --> KERNEL[目标 Kernel / Runtime]
    KERNEL --> EVAL[质量 + 性能联合验收]
  • PTQ(Post-Training Quantization):不进行完整重训练,使用 Calibration 数据估计范围或做局部重构,成本低,适合快速部署。
  • QAT(Quantization-Aware Training):训练中模拟量化与反量化误差,让参数适应目标格式;通常质量更稳,但需要训练数据、算力与更复杂流程。

Calibration 集不是“随便取几条样本”。它应覆盖真实长度、领域、模态和 Activation 分布;同时必须与模型预处理、Tokenizer 和推理图一致。

LLM 常见 PTQ 思路

方法 目标 核心思路 软硬件关注点
SmoothQuant W8A8 用数学等价缩放把 Activation 的量化难点迁移到较易量化的 Weight Scale Folding、INT8 GEMM 与算子覆盖
GPTQ 低比特 Weight-only 用近似二阶信息逐步量化并补偿误差 Group Size、Packing、反量化 GEMM Kernel
AWQ 低比特 Weight-only 由 Activation 统计识别重要通道,通过等价缩放保护显著 Weight Calibration 泛化、硬件友好 Group Quant

这张表只描述方法家族,不代表“某方法永远最好”。模型结构、任务、位宽、Group Size、Kernel 和 GPU 代际都会改变结论。

误差来自哪里

flowchart TB
    D[浮点分布] --> O[Outlier / 长尾]
    D --> R[Range 选择]
    D --> G[Scale 粒度]
    O --> E[量化误差]
    R --> E
    G --> E
    E --> P[层间传播与放大]
    P --> Q[任务质量变化]

主要机制包括:

  • 范围太大时多数值被压在少量 Level;范围太小时发生 Clipping;
  • Activation Outlier 让 Per-Tensor Scale 难以兼顾普通值;
  • 低比特 Weight 误差会被输入 Activation 放大;
  • Softmax、Norm、Embedding、输出头等算子敏感性不同;
  • 量化节点插入位置和算子融合会改变舍入次数与数值顺序。

为什么压缩后可能不快

  1. 目标 GPU/CPU 没有对应低精度矩阵吞吐优势。
  2. Kernel 在计算前把 Weight 解包/反量化到高精度,开销抵消带宽收益。
  3. Shape 太小或不满足对齐,矩阵单元利用率低。
  4. 只有部分层量化,频繁 Quantize/Dequantize 形成额外 Kernel 和中间 Tensor。
  5. Batch/并发太低,Launch 与调度开销占主导。
  6. 模型原本 Compute-bound,Weight-only 压缩没有解决主瓶颈。
  7. Runtime 不支持目标 Packing/Layout,产生转换或回退路径。

联合验收矩阵

维度 必测内容
模型质量 Perplexity、任务集、长上下文、生成稳定性、敏感领域
数值诊断 层级误差、Cosine/NRMSE、Outlier、Saturation 比例
容量 模型文件、加载后显存、KV Cache、Runtime Workspace
性能 Prefill/Decode 分测、吞吐、TTFT、TPOT、P50/P99
Kernel 是否命中低精度指令、解包/反量化占比、融合与回退
资源 HBM 流量、矩阵单元利用率、寄存器/Shared Memory
可复现性 模型版本、Calibration 数据摘要、配置、Kernel/Runtime 版本

质量与性能必须使用同一量化制品

不要用一种导出格式测准确率、另一种 Runtime 重新量化后测性能。最终加载的 Weight、Scale、Zero Point、Packing 与执行图必须可追溯到同一制品。

最小实验顺序

  1. 固定浮点 Baseline 与目标硬件,分别测 Prefill/Decode。
  2. 只量化 Weight,确认模型大小、显存和权重流量变化。
  3. 检查反汇编/Profile,证明目标低精度 Kernel 实际命中。
  4. 再扩大到 Activation 或 KV Cache,逐项测质量和性能增量。
  5. 改 Group Size/Calibration/Clip 时保持其余变量不变。
  6. 最终用真实长度与并发分布做端到端验收。

延伸阅读