已关闭
int8 池化内核重量化结果窄化回绕,负值窗口输出翻转(MaxPoolingInt8 / MaxPoolingInt8V1) #448
李浩林创建于  8月29日关闭于  9月12日
李浩林
李浩林成员
8月29日 创建

现象

全量化 int8 模型推理时,MaxPool 输出张量中的个别元素发生数量级翻转:本应为 -128(饱和下限)的元素变成 +112~+127。在 WS63(RISC-V)单算子全量化测试中,[1,64,6,6]、kernel 2×2/stride 2×2 规格的 576 个输出中恰有 1 个元素翻转,导致输出与 golden 的余弦相似度从 0.9999 降至 0.9947。

根因

mindspore-lite/src/litert/kernel/cpu/nnacl_c/int8/pooling_int8.c 中,重量化结果被直接赋给 int8_t 中间变量后再做饱和 clamp:

int8_t tmp_max = INT8_MIN;
...  // 窗口求 max
tmp_max = (int)round((tmp_max - input_zp) * real_multiplier + output_zp);  // ← 窄化点
int8_t real_out = tmp_max < out_min ? out_min : tmp_max;                   // ← clamp 失效
real_out = real_out > out_max ? out_max : real_out;

当 requant 结果超出 int8 范围(典型如 -129 ~ -144)时,int → int8_t 的窄化截断使数值回绕为正值(如 -144 → +112),恰好落在 (out_min, out_max] 区间内,上下限饱和双双失效,错误值直接写出。

受影响的函数(同写法两处):

  • MaxPoolingInt8
  • MaxPoolingInt8V1

触发条件(三者叠加)

  1. 池化窗口 max 为负值;
  2. 输出量化 zero-point 负偏移较大(本例 zp_out = -25,常见于 MAX_MIN 校准);
  3. 输入/输出 scale 比值使结果越过 -128(本例 real_multiplier ≈ 1.19)。

真实 CNN 中 pool 常跟在 conv/ReLU 后(输入非负、zp 近 0),故长期未暴露;随机数据全量化单算子测试可稳定复现。

likedislike
李浩林李浩林成员
8月29日 修改标题为 “int8 池化内核重量化结果窄化回绕,负值窗口输出翻转(MaxPoolingInt8 / MaxPoolingInt8V1)”,原标题为“pool算子micro的精度不达标”
李浩林李浩林成员
8月29日 修改了issue 的描述
李浩林李浩林成员
8月29日 修改了issue 的描述
MindSpore-BotMindSpore-Bot成员
8月29日 关闭了 issue
MindSpore-BotMindSpore-Bot成员
8月29日 重新打开了 issue
李浩林李浩林成员
9月12日 issue状态由 TODO 改变为 DONE
李浩林李浩林成员
9月12日 关闭了 issue