量化的核心本质——从一个连续区间到离散整数集的保序映射。
📐 数学形式化表达

可以精确地用下面的公式表达:
量化值 = clamp(round((浮点值 - range_min) / scale) + zero_point, q_min, q_max)
其中:
-
scale = (range_max - range_min) / (q_max - q_min) ← 决定映射的"缩放比例"
-
zero_point = q_min - round(range_min / scale) ← 决定映射的"平移基准"
这个公式确保了:
-
保序性:
float(x) < float(y) → quant(x) <= quant(y)(单调递增映射) -
双射区间:
[range_min, range_max]↔[q_min, q_max]是一一对应的 -
截断处理:超出
[range_min, range_max]的值会被clamp到边界
💡 为什么用更少的bit能加速?
1️⃣ 计算密度提升
# 浮点计算(32bit) conv2d_float = sum(W_f32[i] * X_f32[i]) # 每次乘法需32bit乘法器 # 整型计算(8bit) conv2d_int8 = (sum(W_i8[i] * X_i8[i]) - bias) * scale # 8bit乘法器速度快4-10倍
2️⃣ 内存带宽减负
| 数据类型 | 带宽占用 | 缓存命中率 | 理论加速比 |
|---|---|---|---|
| FP32 | 4字节/参数 | 低 | 1x |
| INT8 | 1字节/参数 | 高 | 4x |
| INT4 | 0.5字节/参数 | 极高 | 8x |
3️⃣ SIMD指令集优势
现代CPU/GPU的SIMD单元:
-
AVX2:1个指令同时处理32个INT8,但只能处理8个FP32
-
Tensor Core:单周期完成4x4 INT8矩阵乘法,比FP16快2倍
量化中可能遇到的问题汇总如下,
核心问题总览
| 问题类别 | 核心问题 | 问题描述 | 主要解决方法 |
|---|---|---|---|
| 映射过程问题 | 截断误差 | 放弃范围外的极值,导致信息永久丢失。 | 1. 最优截断:使用KL、MSE等校准算法。2. 层级均衡: LayerwiseEqualization,将大范围分布拆分到相邻层。 |
| 舍入误差 | 四舍五入导致的精度损失。 | 1. 最优截断:让分布更“挤”,格子更“密”。 2. 可学习参数: LSQ / TQT,通过训练优化舍入方式。 | |
| 溢出/饱和 | 计算时数值超出整数表示范围(通常是中间结果)。 | 1. 算子融合:QuantFusion,将多个操作合并,避免产生大数。2. 动态范围调整:自动调整 scale,预留安全边际。 | |
| 结构/分布问题 | 分布不均 | 不同通道的数据范围差异巨大(常见于深度可分离卷积)。 | Per-channel量化:为每个通道独立设置scale和zero_point。 |
| 零点漂移 | 量化ReLU等操作后,零点位置不稳定。 | 优化调度策略:Dispatcher,争议区算子用浮点计算,或做图优化。 | |
| 特殊操作问题 | 跨层合并 | 量化后的Conv + BN + Relu等操作无法直接融合。 | 算子融合:QuantFusion,将BN参数吸收进Conv,再进行量化。 |
| 激活函数处理 | 某些激活函数(如Swish, GeLU)对量化不友好。 | 调度策略:将该激活函数放到浮点域计算(异构执行)。 |

1600

被折叠的 条评论
为什么被折叠?



