量化推理 — 交互式学习指南
基于手算示例,逐步理解对称/非对称/Per-Channel/INT4 量化原理
§2 对称量化 (Symmetric INT8)
2.1 数学公式
量化: q = round(x / scale), clamp(q, -127, 127)
反量化: x' = q × scale
其中: scale = max(|x|) / 127
零点固定为 0——0.0 在浮点和量化空间都对应 0
2.2 手算示例:权重 [0.03, -0.05, 0.12, -0.08, 0.01]
Step 1: max(|x|) = 0.12
Step 2: scale = 0.12 / 127 = 0.000945
Step 3: 量化 (÷ scale → round)
| 原值 | 计算 | INT8 | 反量化 | 误差 |
| 0.03 | round( 31.7) | 32 | 0.0302 | +0.0002 |
| -0.05 | round(-52.9) | -53 | -0.0501 | -0.0001 |
| 0.12 | round(127.0) | 127 | 0.1200 | 0 |
| -0.08 | round(-84.7) | -85 | -0.0803 | -0.0003 |
| 0.01 | round( 10.6) | 11 | 0.0104 | +0.0004 |
2.3 Outlier 的影响
999 个值在 [-0.5, 0.5],1 个 outlier = 5.0
无 outlier
scale = 0.5/127 = 0.00394
值 0.01 → q ≈ 3
值 0.05 → q ≈ 13
值 0.10 → q ≈ 25
有 outlier (5.0)
scale = 5.0/127 = 0.0394 (×10)
值 0.01 → q = 0 ← 完全丢失
值 0.05 → q = 1
值 0.10 → q = 3
1 个 outlier 放大 scale 10 倍,256 级精度只用了不到 4 级。
解决方案:LLM.int8() 对 outlier 维度单独保留 FP16,其余 INT8。
§3 非对称量化 (Asymmetric UINT8)
3.1 数学公式
量化: q = round(x / scale) + zero_point, clamp(q, 0, 255)
反量化: x' = (q - zero_point) × scale
其中: scale = (x_max - x_min) / 255
zero_point = round(-x_min / scale)
zero_point 将数据范围精准映射到 [0, 255],无浪费
3.2 手算示例:ReLU 激活值 [0.0, 0.35, 1.20, 0.08, 2.50]
Step 1: x_min = 0.0, x_max = 2.50
Step 2: scale = 2.50/255 = 0.00980, zero_point = 0
| 原值 | 计算 | UINT8 | 反量化 | 误差 |
| 0.00 | round(0.0)+0 | 0 | 0.0000 | 0 |
| 0.35 | round(35.7)+0 | 36 | 0.3528 | +0.0028 |
| 1.20 | round(122.4)+0 | 122 | 1.1960 | -0.004 |
| 0.08 | round(8.2)+0 | 8 | 0.0784 | -0.0016 |
| 2.50 | round(255.1)+0 | 255 | 2.5000 | 0 |
3.3 同一组数据:对称 vs 非对称
| 原值 | 对称量化 (不适合) | 非对称量化 (适合) |
| q → 反量化 | 误差 | q → 反量化 | 误差 |
| 0.00 | 0→0.0000 | 0 | 0→0.0000 | 0 |
| 0.35 | 18→0.3544 | Δ0.0044 | 36→0.3528 | Δ0.0028 |
| 1.20 | 61→1.2011 | Δ0.0011 | 122→1.1960 | Δ0.0040 |
| 0.08 | 4→0.0788 | Δ0.0012 | 8→0.0784 | Δ0.0016 |
| 2.50 | 127→2.5000 | 0 | 255→2.5000 | 0 |
对称浪费 50% 范围(负数区间 [-2.5,0) 用不上),非对称 scale 减半 → 精度翻倍
§4 Per-Tensor vs Per-Channel
4.1 粒度对比
| 方式 | 粒度 | scale 数 (4096²) | 存储开销 | 精度 |
| Per-Tensor | 整个矩阵 1 个 scale | 1 | 4 B | 受 outlier 通道影响 |
| Per-Channel | 每行独立 scale | 4096 | 16 KB | 各通道自主最优 |
4.2 手算示例:2×3 矩阵
通道 0 (小值): [ 0.05, -0.02, 0.10]
通道 1 (大值): [ 1.20, -0.80, -2.50]
Per-Tensor
scale = 2.50/127 = 0.01969
通道 0:
0.05→3 → 0.059 Δ+0.009 (18%!)
-0.02→-1 → -0.020 Δ0
0.10→5 → 0.098 Δ-0.002
RMSE = 0.0054
通道 1:
1.20→61 → 1.201 Δ+0.001
-0.80→-41 → -0.807 Δ-0.007
-2.50→-127 → -2.501 Δ-0.001
RMSE = 0.0038
Per-Channel
通道 0: scale₀ = 0.10/127 = 0.000787
0.05→64 → 0.0504 Δ+0.0004
-0.02→-25 → -0.0197 Δ+0.0003
0.10→127 → 0.1000 Δ0
RMSE = 0.0003
通道 1: scale₁ = 2.50/127 = 0.01969
(与 per-tensor 相同)
RMSE = 0.0038
通道 0 精度提升 18×
额外开销仅 8 bytes
§6 INT4 量化
6.1 INT4 vs INT8
| 离散值 | 精度 | 7B HBM |
| INT8 | 256 | ≈ 0.4% | ~7 GB |
| INT4 | 16 | ≈ 6.25% | ~3.5 GB |
6.2 手算示例:INT4 Per-Tensor vs Group-Wise
8 个权重,INT4 范围 [-7, 7],16 个离散级别
前 4 个 (小值): [0.15, -0.08, 0.03, 0.12]
后 4 个 (大值): [2.10, -1.80, 1.50, -0.95]
Per-Tensor INT4
scale = 2.10/7 = 0.30
前 4 个:
0.15→1 → 0.30 (原值 0.15,偏差极大)
-0.08→0 → 0
0.03→0 → 0
0.12→0 → 0
全部塌缩到 0-1!
RMSE = 0.126
后 4 个:
2.10→7 ✓
RMSE = 0.039
Group-Wise INT4
Group 0: scale₀ = 0.15/7 = 0.0214
0.15→7 → 0.150 ✓
-0.08→-4 → -0.086 ✓
0.03→1 → 0.021 ✓
0.12→6 → 0.128 ✓
RMSE = 0.011
Group 1: scale₁ = 2.10/7 = 0.30
(与 per-tensor 相同)
RMSE = 0.039
精度恢复!
开销: 2 scale × 4B = 8B
Group-wise 用 ~3% 额外存储,换回 per-channel 级别的精度。INT4 必须搭配 group-wise。
§7 量化加速原理
7.1 显存节省 (7B 模型)
FP32
28GB
FP16
14GB
INT8
7GB
INT4
3.5GB
7.2 HBM 带宽节省
推理时需从 HBM 读取全部权重。910B3 HBM 带宽 1538 GB/s。
| 精度 | 权重大小 | 读取时间 | 加速 |
| FP16 | 14 GB | 9.1 ms | 1× |
| INT8 | 7 GB | 4.6 ms | 2× |
| INT4 | 3.5 GB | 2.3 ms | 4× |
更多交互式实验请打开 quantization_viz.html | Python 演示:python3 quantization_demo.py