量化基础:定点数与浮点数、均匀量化与非线性量化

量化,说白了就是把连续的数值映射到有限的离散集合上。在芯片里,我们没法像数学公式那样精确表达每一个实数,只能用有限的比特位去近似。这个近似的过程,就是量化。

我刚开始做芯片设计时,总觉得量化就是简单的四舍五入。后来在一个语音处理项目中,因为量化方式选错了,导致整个系统的信噪比差了将近 6dB。嗯,从那以后我再也不敢小看这个环节了。

定点数与浮点数

先聊聊数字在硬件里的两种基本表示方式:定点数和浮点数。

定点数,顾名思义,小数点的位置是固定的。比如我们用 8 位来表示一个数,约定高 4 位是整数部分,低 4 位是小数部分。那这个数的范围就是 0 到 15.9375,精度是 1/16。

定点数的核心特点:

  • 硬件实现简单,只需要整数加法器和乘法器
  • 动态范围有限,容易溢出或精度不足
  • 适合资源受限、计算规律的应用场景

浮点数则灵活得多。它用科学计数法的方式表示数字:一部分存指数,一部分存尾数。IEEE 754 标准里,单精度浮点数用 1 位符号、8 位指数、23 位尾数。

浮点数的好处是动态范围大。同样的 32 位,定点数可能只能表示 -32768 到 32767,浮点数却能表示 ±10³⁸ 的范围。但代价呢?硬件复杂度翻倍,功耗和面积都上去了。

对比项 定点数 浮点数
硬件面积 小(约 1x) 大(约 3-5x)
功耗 低 高
动态范围 有限 大
精度分布 均匀 不均匀(靠近零更密)
适用场景 推理、控制、信号处理 训练、科学计算

我的经验:在部署神经网络推理时,我习惯先用浮点模型跑通精度,再逐步转定点。别一上来就拍脑袋定 Q 格式,先看看数据的实际分布范围。我曾经在一个目标检测项目里,因为没分析激活值的分布,直接选了 Q8.8 格式,结果精度掉了 3 个点,后来改成 Q6.10 才救回来。

均匀量化与非线性量化

量化方式分两大类:均匀量化和非线性量化。区别在于量化步长是否固定。

均匀量化,也叫线性量化。整个数值范围内,每个量化间隔都一样大。比如 0 到 1 的范围,用 8 位量化,步长就是 1/256。

均匀量化的好处是简单、计算快。在硬件里,均匀量化就是一个缩放加取整的操作。但问题也很明显:如果数据分布不均匀,比如大部分值集中在 0 附近,那均匀量化就会浪费很多比特位在那些很少出现的数值上。

// 均匀量化示例:将浮点值映射到 8 位整数
// 范围 [-1.0, 1.0],步长 = 2/256 ≈ 0.0078

float x = 0.345f;
int q = (int)round(x / 0.0078f);  // 量化
float x_hat = q * 0.0078f;        // 反量化

非线性量化则不同。它的步长不是固定的,而是根据数值大小动态调整。常见的非线性量化方式有对数量化、μ-law 量化和 A-law 量化。

为什么需要非线性量化?你想想看,在语音信号里,小信号出现的概率远大于大信号。如果均匀量化,小信号的量化误差相对值就很大,听起来就是噪声。非线性量化在小信号区域用更小的步长,大信号区域用更大的步长,这样整体信噪比就提升了。

避坑指南:我曾经在一个音频编解码器项目里,直接用了均匀量化,结果在静音段听到了明显的底噪。后来换成 μ-law 量化,同样的 8 位,信噪比提升了 12dB。非线性量化不是万能的,但在数据分布极度不均匀的场景下,它确实能省下不少比特。

量化误差分析

量化必然带来误差。这个误差通常用信噪比(SNR)来衡量。对于均匀量化,每增加 1 位,SNR 大约提升 6.02dB。

但要注意,这个公式的前提是输入信号均匀分布。如果信号分布不均匀,实际 SNR 会低于理论值。这就是为什么在神经网络量化中,我们经常需要先统计激活值的分布,再决定量化参数。

量化位数 均匀量化 SNR(理论) 实际场景 SNR(语音)
8 位 49.9 dB 35-40 dB
12 位 74.0 dB 55-65 dB
16 位 98.1 dB 75-85 dB

关键结论:量化误差不是均匀分布的。在信号幅度小的区域,相对误差更大。这就是为什么在低比特量化时,我们需要格外关注小信号的保真度。

量化方式的选择策略

在实际项目中,怎么选量化方式?我一般按这个思路来:

  1. 先看数据分布:收集一批代表性数据,画出直方图。如果数据近似均匀分布,均匀量化就够了。
  2. 再看硬件约束:如果面积和功耗是硬指标,定点数加均匀量化是最稳妥的选择。
  3. 最后看精度要求:如果精度要求高,但比特位有限,非线性量化可能是唯一出路。

举个例子,在神经网络量化中,权重和激活值的分布通常近似拉普拉斯分布或高斯分布。这时候用均匀量化,在均值附近精度够用,但在尾部区域就会浪费比特。所以现在很多芯片都支持非均匀量化,比如用查找表实现的对数量化。

量化方式选择决策流程 输入数据分布分析 数据是否近似均匀分布? 是 均匀量化 + 定点数 否 非线性量化 硬件资源是否紧张? 是 降低位宽 / 用查找表 否 保留精度 / 浮点混合 实际项目中,量化方式的选择需要反复迭代验证,没有一劳永逸的方案

实际项目中的量化技巧

最后分享几个我在项目中积累的小技巧:

  • 先粗后细:先用低精度快速验证算法可行性,再逐步提高精度。别一开始就追求 32 位浮点。
  • 混合精度:不同层、不同张量可以用不同的量化精度。比如第一层用 8 位,后面几层用 4 位。
  • 校准数据集:量化参数(缩放因子、零点)一定要用有代表性的数据来校准。我见过有人随便拿几张图就做量化,结果部署后精度惨不忍睹。
  • 仿真验证:在 RTL 仿真阶段就要加入量化模型,别等到流片回来才发现问题。

我的习惯:每次做量化方案时,我都会先写一个 Python 脚本,把浮点模型和量化模型的输出逐层对比。哪一层误差大了,就针对那一层调整量化参数。这样比整体调参高效得多。

量化不是简单的砍位宽,而是一个系统工程。选对了量化方式,芯片面积能省 30%,功耗能降 40%,精度损失却不到 1%。这就是我们做芯片优化的意义所在。