2. INT8量化数学基础

要把一个 FP32 张量塞进 INT8,本质上是在做一次“带偏移的线性映射”。理解这条映射公式,是理解 TensorRT 量化校准、精度损失和调优手段的起点。本节从数学定义出发,逐步过渡到 TensorRT 中的实际映射关系。

一、量化与反量化的基本公式

设实数张量中的元素为 x,量化后的整数为 q,则最通用的仿射量化定义为:

q = round(x / scale) + zero_point
x_hat = (q - zero_point) * scale

其中 scale(缩放因子)是浮点数,表示“一个整数刻度代表多大的实数范围”;zero_point(零点)是一个整数,表示实数 0 对应的量化整数值。反量化得到的 x_hat 是 x 的近似,二者之差即为量化误差。INT8 的整数范围是 [-128, 127](有符号)或 [0, 255](无符号),TensorRT 的激活量化通常使用有符号 INT8,权重也使用有符号 INT8。

二、对称量化与非对称量化

对称量化强制 zero_point = 0,即实数 0 精确映射到整数 0。此时量化范围关于 0 对称,scale 由绝对值最大的元素决定:

scale = max(|x|) / 127
q = clamp(round(x / scale), -128, 127)

对称量化的优点是计算简单、反量化时无需减去零点,且 0 映射无误差,非常适合权重(权重分布通常近似零均值)以及卷积、矩阵乘等以乘加为主的算子。缺点是当数据分布明显不对称(例如 ReLU 之后的激活全部非负)时,会浪费一半的整数区间。

非对称量化允许 zero_point ≠ 0,把实际数据区间 [min, max] 线性映射到 [-128, 127]:

scale = (max - min) / 255
zero_point = round(-min / scale) - 128
q = clamp(round(x / scale) + zero_point, -128, 127)

非对称量化能充分利用整数区间,对 ReLU 输出、Sigmoid 输出等单边分布更友好,代价是反量化多一次减法,且零点本身会引入额外舍入误差。TensorRT 在 PTQ 校准中会为每个张量自动选择对称或非对称方案,通常权重走对称、激活走非对称。

对称量化 vs 非对称量化:实数轴到 INT8 整数轴的映射 对称量化(zero_point = 0) 0 -max|x| +max|x| 映射到 [-128, 127],0 精确对齐 非对称量化(zero_point ≠ 0) min max 0 映射到 [-128, 127],0 落在整数区间内部 TensorRT 中的映射关系 • 权重:对称量化,per-channel scale • 激活:非对称量化,per-tensor scale • scale 决定分辨率:scale 越小越精细 • zero_point 决定 0 的落点 • 反量化:x_hat = (q - zp) × scale • 饱和截断:超出范围的值被 clamp • 校准:用 KL 散度或 min-max 确定范围 • 误差来源:舍入 + 截断 + 范围估计偏差 • 精度验证:逐层对比 FP32 与 INT8 输出

三、量化误差的来源

量化误差并非单一来源,工程上通常拆成三类:

  • 舍入误差:round() 把实数压到最近整数,最大误差为 scale/2。scale 越大,单点误差越大,因此动态范围大的张量精度天然更差。
  • 截断误差:当 x 超出 [min, max] 时被 clamp 到边界,误差可能远大于 scale/2。这是离群点(outlier)最危险的地方。
  • 范围估计误差:校准阶段用有限样本估计 min/max,若校准集不能代表真实分布,scale 会偏大或偏小,导致整体分辨率下降或截断加剧。

此外,反量化时 (q - zero_point) 的整数减法本身是精确的,但乘以 scale 后重新引入浮点舍入,这一项通常可忽略。真正需要关注的是前两项。

四、饱和与截断策略

“饱和”指主动把量化范围收窄到比实际数据更小的区间,让少量离群点被截断,从而换取大多数正常点的更高分辨率。这与“直接取 min/max”是两种相反的策略:

  • min-max 策略:范围覆盖全部数据,无截断,但 scale 被离群点拉大,正常点分辨率下降。
  • 饱和策略:例如只取 99.9% 分位数作为边界,牺牲 0.1% 的离群点,换取更小的 scale。TensorRT 的 KL 校准本质上就是在寻找这个“饱和阈值”。

选择哪种策略取决于离群点的比例和重要性。如果离群点集中在少数通道且对最终输出影响大,饱和会带来明显精度下降;如果离群点是噪声,饱和反而提升整体精度。

五、TensorRT 中的实际映射

在 TensorRT 中,上述数学概念对应到具体的 API 和配置项:

数学概念TensorRT 对应说明
scaleper-tensor / per-channel scale权重默认 per-channel,激活默认 per-tensor
zero_point非对称量化时的零点权重通常为 0,激活可能非 0
饱和阈值校准算法(KL / min-max / percentile)IInt8EntropyCalibrator2 使用 KL 散度
截断clamp 到 [-128, 127]超出范围的值被饱和处理
量化误差逐层输出对比用 FP32 与 INT8 引擎输出差异评估

一个常见的实操流程是:先用 IInt8EntropyCalibrator2 在校准集上跑一遍,得到每个激活张量的 scale 和 zero_point;然后构建 INT8 引擎;最后用同一批验证数据分别跑 FP32 和 INT8,逐层或逐输出对比余弦相似度、相对误差和最终任务指标。如果某层误差突然放大,通常意味着该层的校准范围估计不准,可以尝试换校准算法、增加校准样本,或对该层回退到 FP32。

判断依据示例:若某激活层 INT8 与 FP32 输出的余弦相似度低于 0.99,或相对误差超过 5%,应优先检查该层的校准范围是否被离群点拉大。可尝试改用 percentile 校准或对该层禁用 INT8。
注意:对称量化下 zero_point 恒为 0,反量化公式简化为 x_hat = q × scale;非对称量化下必须保留 zero_point,否则会引入系统性偏移。TensorRT 在导出 Q/DQ 节点时会显式记录 zero_point,手工实现时不要遗漏。

理解这些数学关系后,后续的校准、精度验证和调优才有明确的抓手:scale 决定分辨率,zero_point 决定零点对齐,饱和策略决定离群点与正常点的取舍,而误差分析则告诉我们问题出在哪一层。