谈到FP32,FP16,BF16的区别是什么,可能我们的第一反应是:
- FP32:32 bit表示
- FP16、BF16:16bit表示
所以他们能表示的数值范围、精度不同,如果仅仅是知道这点,那就太表面了。
一个浮点数如何在计算机中存储的
我们以FP32来举例一个浮点数是如果在计算机中存储的,搞清楚这点,我们就基本上搞清楚了FP32。那么FP16和BF16都是大同小异的。
一个浮点数可三个方面来表示:
- 符号位:1 bit。用来表示正负数,负数:1,正数:0.
- 指数位:8bit,类似十进制中科学计数法的指数,决定能表示多大范围的数。实际存储的还要先加上偏置值(bias),偏置=
,k为指数位的位数,在fp32中,bias=127。之所以要加上偏置,是为了更方便的比较浮点数的大小。例如一个浮点数的指数位是2,另一个指数位是-126。
,
,要比较两者真正的大小,计算机硬件还要额外写一套判断符号的复杂逻辑,但是加上偏置之后,就可以直接比较了。
- 尾数位:23bit。体现精度。乍一看怎么不给指数位分多一点,其实8bit的指数位已经足够大了。
一个实际的例子
我们以-6.33为例子:
1.确定符号位(sign):
-6.33为负数,S=1
2.把6.33转成2进制
- 整数部分:
- 小数部分:0.33,采用“乘3取整法”:
这个例子中可以发现,0.33在二进制中是一个无法穷尽的小数,也就是无法精确表示。
组合起来:
3.二进制科学计数法
从科学计数法中提取指数和尾数:
- 真实指数:2。加上偏置之后:
- 尾数:1.10010101000111101011100001,因为二进制科学技术法中第一位一定是1,所以可以省略,那么有效尾数为:10010101000111101011100001,戒断23位:10010101000111101011100
4.内存中的-6.33
到此,已经得到-6.33的关于符号位、指数、尾数的二进制表达了:
- 符号位:1
- 指数位:10000001
- 尾数:10010101000111101011100
这些就是-6.33在计算机中存储的二进制了
复原过程
1.符号位:-1,那么正负号:,为负数
2.指数:,真实指数=129-127=2
3.尾数:10010101000111101011100,在前面补回省略的1,得到:1.10010101000111101011100,转回十进制:
= 1.582499980926513671875
最终复原的值:
FP32能表示的数值范围
从上面复原二进制到10进制的过程:
最终复原的值:
可以发现-1就是决定正负号的,那么跟“范围”无关
最大值
那么一个数的最大值,就是要让尾数和指数越大越好:
- 指数:8bit的指数位,理论上可表示的范围是0~255,但是0(二进制全0)和255(二进制全1)规定用来留作特殊用途了。即1~254,那么最大真实的次方:254-127=127
- 尾数:让二进制二数全为1:
那么最大的值
最小值
同理让指数和尾数最小:
- 指数:1,真实次方:1-127=-126
- 尾数:1.0
那么最小值
到此,应该理解了FP32是个什么东西了
FP32 FP16 BF16区分
仅仅是指数位和尾数位不同而已:
BF16的指数位和FP32是一样的,这是为了让BF16具备和FP32一样的极值范围(实际不太一样,因为尾数位不一样,但是差异很小,可忽略)