# DynamicQuant — MindSpore Signal+ 使用手册 alpha 文档

# DynamicQuant

将 FP32 输入张量按给定的 scale 和 zero point（zp）动态量化为 INT8 输出张量。 支持按整张量量化或按指定轴分段量化（per-axis dynamic quantization）。

\[q_i = \mathrm{clip}\left( \mathrm{round}\left( \frac{x_i}{scale} + zp \right), q_{min}, q_{max} \right)\]

其中：

- \(x_i\) 为输入浮点值

- \(scale\) 为量化比例因子

- \(zp\) 为零点（zero point）

- \(q_{min} = -128\)

- \(q_{max} = 127\)

当输入为 \(+\infty\) 或 \(-\infty\) 时，输出分别饱和到最大或最小量化值。

---

输入：

  - real_values - 输入 FP32 数据地址

  - element_num - 输入元素总数

  - scale - 量化 scale 数组地址

  - zp - 量化 zero point 数组地址

  - segment_num - 分段数量（用于按轴量化）

  - axis_num - 量化轴标识

      - `0`：整张量量化（per-tensor）

      - `!=0`：按轴分段量化（per-axis）

输出：

  - quant_values - 输出 INT8 量化结果地址

---

支持平台：

  `FT78NE` `MT7004`

---

备注

- 当前算子仅支持 FP32Fp16 → INT8 的动态量化

- 当 `axis_num = 0` 时，仅使用 `scale[0]` 与 `zp[0]` 进行整张量量化

- 当 `axis_num != 0` 时，输入按 `segment_num` 进行分段，每段使用对应的 `scale[i]` 与 `zp[i]`

- 分段大小通过 `UP_DIV(element_num, segment_num)` 计算，最后一段自动处理剩余元素

- 量化结果会被限制在 `[-128, 127]` 范围内

---

私有存储版本：

void fp_QuantData_p(float *real_values, int8_t *quant_values, int element_num, float *scale, int *zp, int segment_num, int axis_num)

void hp_QuantData_p(half *real_values, half *quant_values, int element_num, half *scale, int *zp, int segment_num, int axis_num)

---

C调用示例：

>      1#include <stdio.h>
>      2#include <quant.h>
>      3
>      4int main(int argc, char* argv[]) {
>      5    float *input = (float *)0x10000000;      // FP32 输入
>      6    int8_t *output = (int8_t *)0x10004000;   // INT8 输出
>      7    float scale[4] = {0.1f, 0.12f, 0.11f, 0.09f};
>      8    int zp[4] = {0, 0, 0, 0};
>      9    int element_num = 1024;
>     10    int segment_num = 4;
>     11    int axis_num = 1;
>     12
>     13    fp_QuantData_p(input, output, element_num,
>     14              scale, zp, segment_num, axis_num);
>     15
>     16    return 0;
>     17}

---

共享存储版本：

void fp_QuantData_s(float *real_values, int8_t *quant_values, int element_num, float *scale, int *zp, int segment_num, int axis_num, int core_mask)

void hp_QuantData_s(half *real_values, half *quant_values, int element_num, half *scale, int *zp, int segment_num, int axis_num, int core_mask)

---

C调用示例：

>      1#include <stdio.h>
>      2#include <quant.h>
>      3
>      4int main(int argc, char* argv[]) {
>      5    float *input = (float *)0x10000000;      // FP32 输入
>      6    int8_t *output = (int8_t *)0x10004000;   // INT8 输出
>      7    float scale[4] = {0.1f, 0.12f, 0.11f, 0.09f};
>      8    int zp[4] = {0, 0, 0, 0};
>      9    int element_num = 1024;
>     10    int segment_num = 4;
>     11    int axis_num = 1, core_mask = 0xff;
>     12
>     13    fp_QuantData_s(input, output, element_num,
>     14              scale, zp, segment_num, axis_num, core_mask);
>     15
>     16    return 0;
>     17}

---

实现说明：

- 当 `axis_num == 0` 时：

  - 对整个输入数组执行一次统一量化

  - 等价于 per-tensor quantization

- 当 `axis_num != 0` 时：

  - 输入数据按 `segment_num` 均分为多个分段

  - 每个分段使用独立的 `scale[i]` 与 `zp[i]`

  - 等价于 per-axis dynamic quantization

- 核心量化过程由 `DoQuantizeFp32ToInt8` 完成，包括：

  - 反 scale 计算

  - 四舍五入

  - 饱和裁剪

  - INF 特殊值处理