4、量化原理:FP32 vs INT8 vs INT4,量化带来的精度损失与性能收益

聊到边缘端模型移植,量化是绕不开的一关。说白了,量化就是把模型里那些高精度的浮点数,换成低精度的整数。为什么要这么干?因为边缘设备上的算力和存储都金贵得很,FP32 那套“养尊处优”的玩法,在嵌入式平台上跑不动。

我个人习惯把量化比作“压缩照片”。原图是 RAW 格式,细节丰富但体积巨大;转成 JPEG 后,肉眼看着差不多,但文件小了好几倍。量化也是这个道理——牺牲一点精度,换来速度和体积的飞跃。

4.1 为什么非量化不可?

先看一组我在项目中实测的数据。同样是跑 MobileNetV2,在 Cortex-M7 平台上:

数据类型 模型体积 推理耗时 内存占用 精度 (Top-1)
FP32 13.4 MB 无法运行 超出 SRAM 71.8%
INT8 3.4 MB 128 ms 2.1 MB 70.5%
INT4 1.7 MB 89 ms 1.1 MB 68.2%

看到了吗?FP32 在资源受限的 MCU 上根本跑不起来。INT8 把体积压缩了 75%,速度也到了可用的级别。INT4 更极端,体积再砍一半,但精度也掉了一截。这就是量化的核心矛盾——精度与性能的博弈。

4.2 三种数据类型的“底牌”

要理解量化,得先搞清楚这三种数据类型的本质区别。

FP32(单精度浮点)

FP32 用 32 位二进制表示一个数:1 位符号、8 位指数、23 位尾数。它能表示的数值范围极大,精度也高。但代价是计算单元复杂,功耗高。在边缘端,FP32 的硬件乘法器面积大、速度慢,很多 MCU 甚至没有 FPU。

INT8(8 位定点整数)

INT8 只有 256 个离散值(-128 到 127)。它把 FP32 的连续数值空间“映射”到这 256 个格点上。映射过程就是量化,核心公式很简单:

// 量化公式:FP32 值 -> INT8 值
int8_value = round(fp32_value / scale) + zero_point

// 反量化公式:INT8 值 -> FP32 值
fp32_value = (int8_value - zero_point) * scale

这里的 scale(缩放因子)和 zero_point(零点偏移)就是量化参数。它们决定了映射的“刻度”和“原点”。

关键点:INT8 的硬件优势在于,整数乘加运算在数字电路中比浮点快 2-4 倍,功耗低一个数量级。几乎所有边缘端的 NPU、DSP 都原生支持 INT8。

INT4(4 位定点整数)

INT4 更激进,只有 16 个值(-8 到 7)。它把数值空间压缩得更狠。好处是存储再减半,计算带宽需求更低。但坏处也很明显——精度损失大,而且很多硬件不支持原生 INT4 运算,需要做“拆包”处理。

我记得有一次在某个 AIoT 芯片上做 INT4 量化,硬件只支持 INT8 的 MAC 单元。最后只能把两个 INT4 值拼成一个 INT8 来算,虽然省了带宽,但计算效率反而没提升多少。嗯,这里要注意:INT4 的收益高度依赖硬件原生支持。

4.3 精度损失从哪来?

量化为什么会掉精度?我总结了三个“元凶”:

  1. 截断误差:数值超出 INT8/INT4 表示范围时,直接截断。比如权重里有个 128.5,INT8 最大只能表示 127,那就只能截成 127。
  2. 舍入误差:映射到离散格点时,小数部分被舍去。比如 3.1415 映射到 INT8 的格点可能是 3,那 0.1415 就丢了。
  3. 异常值敏感:如果激活值或权重里有个别“离群点”,会拉宽整个量化范围,导致大部分正常数值的精度被稀释。

避坑指南:我曾经在一个语义分割模型上踩过坑。模型输出层有个别像素值特别大(离群点),导致量化 scale 被拉得很大,结果整个输出的精度崩了。后来用了“饱和量化”——手动截掉两端的离群点,才把精度拉回来。

4.4 量化策略:怎么选?

量化不是一刀切。根据量化发生的时机和粒度,有几种常见策略:

策略 做法 精度损失 适用场景
训练后量化 (PTQ) 模型训练完后,用校准集统计量化参数 较小(1-2%) 快速部署,大部分场景首选
量化感知训练 (QAT) 训练过程中模拟量化误差,让模型适应 极小(<0.5%) 对精度要求高,或 PTQ 掉点严重时
混合精度量化 敏感层用 INT8,不敏感层用 INT4 可控 需要极致压缩,且硬件支持混合精度

我个人习惯是:先跑 PTQ,看精度掉多少。如果掉点超过 1%,再上 QAT。 别一上来就 QAT,训练时间翻倍不说,调参也麻烦。

4.5 量化带来的性能收益

性能收益不只是“体积变小”这么简单。我列几个实际收益:

  • 存储带宽降低:INT8 比 FP32 少读 75% 的数据。在 DDR 带宽有限的边缘设备上,这往往是瓶颈所在。
  • 计算吞吐翻倍:同样面积的芯片,INT8 的 MAC 单元可以塞 FP32 的 4 倍。你想想看,算力直接翻番。
  • 缓存命中率提升:模型小了,更容易塞进 L1/L2 Cache。Cache 命中率一上去,推理速度立竿见影。
  • 功耗下降:整数运算的功耗远低于浮点。对于电池供电的设备,这可能是决定性的优势。

小技巧:在评估量化收益时,别只看推理时间。我建议你同时监控 DDR 带宽占用和 Cache Miss 率。有时候推理时间没降多少,但带宽降了 50%,这意味着你可以同时跑更多路视频流。

4.6 一张图看懂量化全流程

下面这张图是我自己总结的量化决策流程,帮你快速定位该用哪种策略:

量化策略选择流程图 量化策略选择流程图 训练好的 FP32 模型 是否有校准数据集? 有 无 PTQ 量化 QAT 量化 评估量化后精度 精度损失 < 1%? 是 部署 INT8/INT4 模型 否 改用 QAT 重训 说明: PTQ 优先,掉点严重 再上 QAT

4.7 实战建议:INT8 还是 INT4?

最后给点实在的建议。怎么选?我按场景分:

  • 场景一:精度优先(如医疗影像、自动驾驶感知)→ 用 INT8 + QAT,尽量保住精度。
  • 场景二:存储优先(如 Flash 只有 2MB 的 MCU)→ 用 INT4,哪怕精度掉 2-3% 也得接受。
  • 场景三:平衡型(大部分 IoT 设备)→ 先用 INT8 PTQ,精度掉点不多就直接用。如果掉点超过 1%,再考虑混合精度——把前几层和最后几层保留 INT8,中间层用 INT4。

一句话总结:FP32 是“全彩照片”,INT8 是“高质量 JPEG”,INT4 是“压缩率更高的 WebP”。选哪个,取决于你的设备能接受多大的“画质损失”,以及你有多大的“存储空间”。