量化基础与方法¶
量化用更低位宽表示权重、激活或 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、输出头等算子敏感性不同;
- 量化节点插入位置和算子融合会改变舍入次数与数值顺序。
为什么压缩后可能不快¶
- 目标 GPU/CPU 没有对应低精度矩阵吞吐优势。
- Kernel 在计算前把 Weight 解包/反量化到高精度,开销抵消带宽收益。
- Shape 太小或不满足对齐,矩阵单元利用率低。
- 只有部分层量化,频繁 Quantize/Dequantize 形成额外 Kernel 和中间 Tensor。
- Batch/并发太低,Launch 与调度开销占主导。
- 模型原本 Compute-bound,Weight-only 压缩没有解决主瓶颈。
- 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 与执行图必须可追溯到同一制品。
最小实验顺序¶
- 固定浮点 Baseline 与目标硬件,分别测 Prefill/Decode。
- 只量化 Weight,确认模型大小、显存和权重流量变化。
- 检查反汇编/Profile,证明目标低精度 Kernel 实际命中。
- 再扩大到 Activation 或 KV Cache,逐项测质量和性能增量。
- 改 Group Size/Calibration/Clip 时保持其余变量不变。
- 最终用真实长度与并发分布做端到端验收。