FP32矩阵乘法的INT8量化、重量化及反量化实现问题咨询
问题解答
前置说明:现有代码的明显可修复错误
- 输入scale计算错误:当前代码写的是
255 / (torch.max(A) - torch.min(B)),应该改为255 / (torch.max(A) - torch.min(A)),误用了B的最小值会直接导致输入量化尺度完全错误 - 类型适配错误:INT8的取值范围是[-128, 127],你当前的量化逻辑没有对输出结果做截断,会出现数值溢出
- 接口混用错误:torch张量不能直接调用numpy的
np.round方法,需要用torch自带的torch.round接口,避免类型报错
问题1:偏移量设置合理性说明
- A的偏移量设为0:仅当输入A的FP32值全部为非负、且最小值恰好为0时合理。如果A包含负值,该操作会直接截断所有负半轴数值,丢失大量信息。且你用的是有符号INT8,本身支持负数值存储,强制设偏移量为0属于不必要的精度损失操作。
- AB的偏移量设为
min(AB):逻辑上符合仿射量化的偏移量计算规则,但是仅适合离线调试场景。实际部署时不可能每次推理都提前拿到矩阵乘结果的全局最小值,无法动态计算偏移量,需要提前通过校准数据集固定偏移量取值。
问题2:scale_AB计算方式说明
- 当前用
max(AB) - min(AB)的计算逻辑本身符合仿射量化的尺度计算规则,但是存在两个缺陷:一是仅适合离线调试,无法用于实际部署;二是没有做溢出校验,很容易导致量化后的结果超出INT8的取值范围。 - 更合适的计算方式分两类:
- 离线校准场景:用校准数据集跑足够多的样本,统计所有矩阵乘输出的全局最大值、全局最小值,固定scale_AB和偏移量的取值,不需要每次推理动态计算
- 部署友好场景:可以通过输入的scale直接推导输出scale,不需要依赖输出最值。公式为
scale_AB = scale_A * scale_B,其中scale_A是输入A的量化尺度,scale_B是输入B的量化尺度,配合对称量化(偏移量设为0)使用时对硬件加速更友好。
问题3:反量化操作规则
反量化是量化操作的严格逆过程,必须和你重量化阶段使用的scale、偏移量完全匹配,规则如下:
- 仿射量化场景反量化公式:
AB_dequant_fp32 = (AB_requantized / scale_AB) + AB_offset - 对称量化(偏移量为0)场景反量化公式:
AB_dequant_fp32 = AB_requantized / scale_AB - 强制要求:反量化用的scale和偏移量必须和重量化阶段的取值完全一致,不能更换其他数值,运算过程中避免不必要的精度截断,减少累积误差。
内容的提问来源于stack exchange,提问作者esse non videri
相关产品推荐
相关产品推荐

