2. 浮点数表示原理:IEEE 754标准回顾、FP32/FP16/BF16的位宽与动态范围对比、定点数表示与量化误差来源

好,咱们直接进入正题。这一章聊的是浮点数的“底子”。你想想看,我们在端侧芯片上做推理,天天跟FP32、FP16、INT8这些格式打交道。但你真的清楚它们背后是怎么表示一个数的吗?

我个人习惯,在讲任何量化方法之前,一定先把浮点数原理讲透。因为很多坑,其实都埋在这些位宽和指数偏移里。

2.1 IEEE 754标准回顾

IEEE 754,说白了就是定义了“计算机里的小数长什么样”。它把浮点数拆成三部分:符号位、指数位、尾数位。

公式很简单:
Value = (-1)^S × 2^(E - bias) × (1 + M)

这里S是符号,E是指数,M是尾数。bias是偏移量,用来表示负数指数。

举个例子,FP32:

  • 符号位:1 bit
  • 指数位:8 bits,bias = 127
  • 尾数位:23 bits

嗯,这里要注意。尾数部分其实隐含了一个“1.”,也就是我们说的“规格化数”。除非指数全0或全1,那才是非规格化数或特殊值。

核心记忆点:浮点数的精度由尾数位宽决定,动态范围由指数位宽决定。

我在项目中遇到过一个问题:有人把FP32的权重直接截断成FP16,结果模型精度崩了。为什么?因为FP16的动态范围不够,有些大数直接溢出了。这就是没搞懂指数位宽的意义。

2.2 FP32 / FP16 / BF16 的位宽与动态范围对比

咱们直接上表格,一目了然。

格式 总位宽 符号位 指数位 尾数位 bias 最大正数 最小正规格化数
FP32 32 1 8 23 127 ~3.4e38 ~1.18e-38
FP16 16 1 5 10 15 65504 ~6.10e-5
BF16 16 1 8 7 127 ~3.4e38 ~1.18e-38

你看,FP16的指数只有5位,最大只能表示到65504。而BF16虽然也是16位,但它保留了8位指数,所以动态范围和FP32一样大。代价是什么?尾数只有7位,精度差了很多。

我曾经在部署一个语音模型时,试过用FP16推理,结果发现某些层的激活值超过了65504,直接变成Inf。后来换成BF16,问题就解决了。这就是动态范围的重要性。

我的建议:如果你的模型权重分布比较集中,没有极端大值,FP16是省带宽的好选择。如果模型有outlier,BF16更安全。

2.3 定点数表示与量化误差来源

好,聊完浮点,咱们说说定点数。定点数,说白了就是“固定小数点位置的二进制数”。比如Q7.8格式,表示1位符号、7位整数、8位小数。

定点数的好处是:硬件实现简单,计算快,功耗低。端侧芯片特别喜欢用定点数做推理。

但问题来了——量化误差从哪来?

我总结三个主要来源:

  1. 截断误差:浮点数转定点数时,超出位宽的小数部分被直接砍掉。比如0.3用4位小数表示,只能近似成0.3125或0.25,误差就来了。
  2. 溢出误差:数值超出定点数的整数范围。比如Q7.8格式,整数部分最大127,如果权重是128,直接溢出。
  3. 舍入误差:截断时是直接丢弃还是四舍五入?不同的舍入策略,误差不一样。我习惯用“最近偶数舍入”,在统计上偏差最小。

避坑指南:我曾经在一个项目里,因为量化时用了简单的“截断”,导致模型精度掉了2个点。后来改成“随机舍入”,精度就回来了。所以,舍入策略不是小事。

你想想看,端侧芯片的算力有限,内存带宽也有限。我们做混合精度推理,本质上就是在精度和效率之间找平衡。FP32最准但最慢,INT8最快但误差最大。BF16和FP16就是中间态。

下面这张图,是我自己画的,帮你理清本章的知识脉络。

浮点数表示原理 · 知识结构 IEEE 754 标准 符号位 + 指数 + 尾数 规格化 / 非规格化 bias 偏移量 FP32 / FP16 / BF16 位宽对比 动态范围差异 精度 vs 范围权衡 定点数 & 量化误差 Q格式表示 截断 / 溢出 / 舍入 误差来源分析 核心结论 混合精度推理 = 在精度、动态范围、计算效率之间做工程取舍 精度 范围 效率

嗯,这张图把本章的核心逻辑串起来了。从IEEE 754标准出发,对比三种浮点格式,再引出定点数和量化误差。你记住这个结构,后面讲量化方法时,会反复用到这些概念。

最后说一句:搞混合精度推理,别只盯着精度掉没掉。先搞清楚你的数据在什么范围内,再选合适的格式。这是基本功。


公众号:蓝海资料掘金营,微信deep3321