DaVinci 950 量化 (Quantization) API 与注意事项
1. 量化在 950 中的两条路径
路径 A: Cube 端量化 (FIXP 硬件管线)
CUBE MMAD (S32/FP32 累加) → FIXP DEQ/REQ → OUT(GM) / L1 / UB
适用: 矩阵乘法后直接量化, 零额外计算开销
路径 B: Vector 端量化 (VEC Core 软件)
VEC VALU 类型转换指令 → VREG → UB → GM
适用: 非 Cube 场景, 灵活但消耗 VALU 周期
2. 路径 A: FIXP 量化 (CUBE 后处理)
2.1 支持的量化操作
| FIXP 操作 |
转换方向 |
模式 |
用途 |
| REQ8 |
S32 → S8 |
标量 + 向量 |
INT8 量化推理 |
| REQ4 |
S32 → S4 |
标量 + 向量 |
INT4 量化推理 |
| DEQF16 |
S32 → FP16 |
标量 |
INT 累加→FP16 输出 |
| QS322BF16 |
S32 → BF16 |
标量 + 向量 |
INT 累加→BF16 输出 |
| QF32_2_B8 |
FP32 → S8/U8 |
标量 + 向量 |
FP32 训练→INT8 部署 |
| QF32_2_S4 |
FP32 → S4 |
标量 + 向量 |
FP32→INT4 部署 |
| QF32_2_HiF8 |
FP32 → HiF8 |
标量 + 向量 |
FP32→HiFloat8 |
| QF32_2_E4M3 |
FP32 → FP8 E4M3 |
标量 + 向量 |
FP32→FP8 量化 |
| QF32_2_E5M2 |
FP32 → FP8 E5M2 |
标量 + 向量 |
FP32→FP8 量化 |
| QF32_2_BF16 |
FP32 → BF16 |
标量 + 向量 |
FP32→BF16 精度转换 |
| QF322F16 |
FP32 → FP16 |
标量 + 向量 |
FP32→FP16 精度转换 |
旁路模式 (不量化):
- FP32 bypass: FP32 → FP32 (直通)
- S32 bypass: S32 → S32 (直通)
2.2 FIXP 量化参数缓冲
| 缓冲 |
大小 |
用途 |
| Bias |
1024×4B = 4KB |
偏置加法参数 |
| RELU-pre |
512×4B = 2KB |
RELU 阈值/斜率 |
| Quantization-pre |
512×8B = 4KB |
量化 scale/offset 参数 |
2.3 FIXP 量化与 RELU 的串联
CUBE MMAD → L0C (S32/FP32)
│
▼
FIXP-PRE:
1. BIAS 加法 (可选)
2. DEQ 量化 (scale×data + offset)
3. RELU/Clip-RELU (可选, 在 FP32 域)
│
▼
MEM_RIF: 数据重排
│
▼
MEM_WIF:
NZ2ND (NC1HWC0 → NHWC) + 量化类型转换
│
▼
OUT → GM
2.4 FIXP 量化并行度
| 路径 |
并行度 (elem/cycle) |
说明 |
| L0C→OUT (S32/F32 bypass) |
32 |
不量化, 直通 |
| L0C→OUT (量化后 b8/b4) |
64 |
量化后每 cycle 输出 64 元素 |
| L0C→L1 (S32/F32 bypass) |
64 |
直通 |
| L0C→L1 (量化后) |
128 |
量化后每 cycle 输出 128 元素 |
| L0C→UB (S32 bypass) |
32 |
直通 |
| L0C→UB (FP32 dual source) |
64 |
双源写入 UB0+UB1 |
3. 路径 B: Vector Core 量化 (VALU 类型转换)
3.1 API — FP32 → 低精度 (量化)
| API 函数 |
目标类型 |
舍入模式 |
说明 |
Cast(dst, src, CAST_RINT, count) |
FP16 |
rint |
FP32→FP16, 就近舍入 |
Cast(dst, src, CAST_ROUND, count) |
FP16 |
round |
FP32→FP16, 四舍五入 |
Cast(dst, src, CAST_FLOOR, count) |
FP16 |
floor |
FP32→FP16, 向下取整 |
Cast(dst, src, CAST_CEIL, count) |
FP16 |
ceil |
FP32→FP16, 向上取整 |
Cast(dst, src, CAST_RINT, count) |
BF16 |
rint |
FP32→BF16, 就近舍入 |
Cast(dst, src, CAST_ROUND, count) |
BF16 |
round |
FP32→BF16, 四舍五入 |
3.2 API — 低精度 → FP32 (反量化)
| API 函数 |
源类型 |
说明 |
Cast(dst, src, CAST_NONE, count) |
FP16→FP32 |
精确扩展, 无舍入 |
Cast(dst, src, CAST_NONE, count) |
BF16→FP32 |
扩展到 FP32 |
CAST_NONE 表示无舍入操作, 用于精度扩展场景。
3.3 API — 完整类型转换覆盖
| C API 函数 |
目标类型 |
舍入模式 |
适用架构 |
Float2Half(dst, src, mask) |
FP16 |
rn/rd/ru/rz/rna/ro |
全部 |
Float2Bfloat16(dst, src, mask) |
BF16 |
rn/rd/rna/ru/rz |
全部 |
Float2Int32(dst, src, mask) |
S32 |
rn/rd/ru/rz/rna |
全部 |
Float2E4m3(dst, src, mask) |
FP8 E4M3 |
rn |
3510 ONLY |
Float2E5m2(dst, src, mask) |
FP8 E5M2 |
rn |
3510 ONLY |
Float2Hif8(dst, src, mask) |
HiF8 |
rh/rna |
3510 ONLY |
Half2Int8(dst, src, mask) |
S8 |
rn/rd/ru/rz/rna |
全部 |
Half2Int4x2(dst, src, mask) |
S4×2 packed |
rn/rd/ru/rz/rna |
3510 ONLY |
Half2Hif8(dst, src, mask) |
HiF8 |
rh/rna |
3510 ONLY |
Bfloat162E2m1x2(dst, src, mask) |
FP4 E2M1×2 |
rn/rd/rna/ru/rz |
3510 ONLY |
Bfloat162E1m2x2(dst, src, mask) |
FP4 E1M2×2 |
rn/rd/rna/ru/rz |
3510 ONLY |
Half2Float(dst, src) |
FP32 |
无 |
全部 |
E4m32Float(dst, src) |
FP32 |
无 |
3510 ONLY |
E5m22Float(dst, src) |
FP32 |
无 |
3510 ONLY |
Hif82Float(dst, src) |
FP32 |
无 |
3510 ONLY |
3.4 通用舍入函数
| API 函数 |
等价数学 |
适用类型 |
Ceil(dst, src, count) |
⌈x⌉ |
FP16, BF16, FP32 |
Floor(dst, src, count) |
⌊x⌋ |
FP16, BF16, FP32 |
Round(dst, src, count) |
四舍五入 |
FP16, BF16, FP32 |
Rint(dst, src, count) |
就近整数 |
FP16, BF16, FP32 |
Trunc(dst, src, count) |
截断 |
FP16, BF16, FP32 |
3.5 舍入模式详解
| 模式 |
枚举/缩写 |
数学含义 |
典型用途 |
| Round to nearest even |
rn / CAST_RINT |
四舍五入到最近偶数 |
训练 (无偏) |
| Round down |
rd / CAST_FLOOR |
向负无穷取整 |
量化范围下界截断 |
| Round up |
ru / CAST_CEIL |
向正无穷取整 |
量化范围上界截断 |
| Round toward zero |
rz / — |
向零取整 |
推理量化 |
| Round to nearest away |
rna / CAST_ROUND |
四舍五入 (远离零) |
部署量化 |
| Round to odd |
ro |
四舍五入到奇数 |
特殊场景 |
| Round hybrid |
rh |
混合舍入 (HiF8专用) |
HiFloat8 量化 |
4. 量化 API 对应关系总览
┌──────────────────────────────────────────────────────────────────┐
│ 量化场景 API 选择 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ 场景 1: Cube 矩阵乘后直接量化 │
│ MMAD(S32/F32) → FIXP DEQ/REQ → GM │
│ 配置: FixPipeParams / FIXP 指令参数 │
│ 量化参数: 从 L1 加载 Quantization-pre (4KB) │
│ │
│ 场景 2: 向量端 FP32→FP16 量化 │
│ Cast(dst, src, CAST_ROUND, count) │
│ │
│ 场景 3: 向量端 FP32→BF16 量化 │
│ 场景 4: 向量端 FP32→FP8 量化 (3510 ONLY) │
│ 场景 5: 向量端 FP32→HiF8 量化 (3510 ONLY) │
│ 场景 6: 向量端 FP16→INT8 量化 │
│ 场景 7: 向量端 FP16→INT4 量化 (3510 ONLY, packed) │
│ 场景 8: BF16→FP4 MX 量化 (3510 ONLY) │
│ 场景 9: FP8→FP32 反量化 (3510 ONLY) │
│ 场景 10: FP16→FP32 反量化 │
│ Basic C++: Cast(dst, src, CAST_NONE, count) │
│ 场景 11: MX Matmul 量化 (3510 ONLY, CUBE端) │
│ Basic C++: Matmul(l0c, l0a, l0b, mx_params) │
│ 输入: FP4 E2M1/E1M2 + FP8 E8M0 scale │
│ 累加: FP32 → FIXP 可进一步量化输出 │
│ │
└──────────────────────────────────────────────────────────────────┘
5. 量化注意事项
5.1 FIXP 量化约束
| # |
约束 |
原因 |
违反后果 |
| 1 |
L0C 数据 不能是 denormal |
FIXP 内部用 FP32 域处理 |
量化结果错误 |
| 2 |
量化参数 不能是 denormal/INF/NaN |
参数在硬件中直接使用 |
量化结果错误 |
| 3 |
量化后数据写入 OUT: 字节对齐 |
OUT 接口特性 |
数据错位 |
| 4 |
量化后数据写入 L1/UB: 32B 对齐 |
L1/UB 写对齐要求 |
硬件异常 |
| 5 |
L0C 读对齐: FP32/S32 64B, FP16 32B |
L0C bank 粒度 |
性能损失/数据错误 |
| 6 |
L1/UB/OUT 不能同时写 |
FIXP 资源互斥 |
指令丢弃 |
| 7 |
Quantization post type 不支持 |
硬件限制 |
不可用 |
| 8 |
N 方向 dummy data 不删除 |
FIXP 只删 M 方向 |
输出含垃圾数据 |
| 9 |
量化参数 只从 L1 加载 |
FIXP 硬件设计 |
无法加载 |
| 10 |
参数源 32B 对齐, 目的 64B 对齐 |
MEM_RIF 接口要求 |
硬件异常 |
5.2 Vector Core 量化约束
| # |
约束 |
原因 |
解决方案 |
| 1 |
DataCopy count 必须 32B 对齐 |
硬件搬运约束 |
FP16≥16, FP32≥8, INT8≥32, 尾部 padding |
| 2 |
FP8/FP4 类型只在 3510 可用 |
2201 无这些类型 |
#if (__NPU_ARCH__ == 3510) 条件编译 |
| 3 |
FP4 是 packed ×2 (8bit 存 2 个 FP4) |
紧凑存储格式 |
一次转换得到 2 个值, 需拆包 |
| 4 |
FP8 E8M0 只用作 MX scale |
无尾数, 只有指数 |
仅配合 MX Matmul 使用 |
| 5 |
反量化 (→FP32) 无舍入模式 |
精度扩展无损失 |
Cast(dst, src, CAST_NONE, count) |
| 6 |
INT8 量化依赖 mask 控制有效元素 |
INT8 与 FP16 位宽不同 |
构造对应宽度的 predicate mask |
| 7 |
量化指令消耗 VALU 周期 |
走 VALU 流水线 |
尽量用 FIXP 路径替代 |
| 8 |
舍入模式选择影响 量化精度 |
不同舍入偏差不同 |
训练用 rn, 推理用 rz |
5.3 舍入模式选择指南
┌──────────────────────────────────────────────────────────────┐
│ 舍入模式决策树 │
│ │
│ 是否是训练场景? │
│ ├── 是 → rn / CAST_RINT (round to nearest even, 无偏) │
│ └── 否 (推理/部署) │
│ ├── 是否要求无偏量化? │
│ │ ├── 是 → rn / CAST_RINT │
│ │ └── 否 → 性能优先? │
│ │ ├── 是 → rz (trunc, 最快) │
│ │ └── 否 → rna / CAST_ROUND (精度好) │
│ └── HiF8 场景 → rh (hybrid, HiF8专用) │
│ │
│ 特殊场景: │
│ 量化范围上界截断 → ru / CAST_CEIL │
│ 量化范围下界截断 → rd / CAST_FLOOR │
│ 混合精度累加 → ro (round to odd, 保持精度) │
└──────────────────────────────────────────────────────────────┘
5.4 量化精度陷阱
| 陷阱 |
现象 |
原因 |
修复 |
| 溢出截断 |
INT8 量化后最大值全是 127 |
scale 太小, FP32 值远超 127/scale |
调大 scale 或用 saturation |
| 全零输出 |
量化后输出全为 0 |
scale 太大, 所有值量化后 < 0.5 被截断 |
调小 scale |
| 非对称量化偏移 |
有符号量化不对称 |
未正确处理 zero-point |
用 U8 + offset 做对称化预处理 |
| BF16 精度低 |
梯度更新不收敛 |
BF16 只有 7-bit 尾数 |
用 FP32 累加 + 最后一步转 BF16 |
| FP4 精度不足 |
量化误差 > 50% |
FP4 E2M1 只有 1-bit 尾数 |
配合 MX scale (E8M0) 分组补偿 |
| denormal 输入 |
量化结果不可预测 |
denormal 在 FP32 域处理异常 |
输入数据先 flush-to-zero |
| 混合精度链 |
串联量化精度衰减 |
每次量化引入舍入误差 |
减少量化次数, 合并为一步 |
| NZ2ND 尾部垃圾 |
N 不对齐时输出含无效数据 |
FIXP 不删 N 方向 dummy |
N 按 C0 向上对齐, 或用 NZ2DN |
所有评论(0)