FP16与bfloat16位模式可视化工具

可视化半精度浮点数(FP16、IEEE 754 binary16)和bfloat16的位模式。支持十进制与位模式互相转换,符号位、指数部、尾数部分色显示。适合学习机器学习中的量化与推理加速。

FP16与bfloat16的结构比较

两者合计都是16位,但指数部与尾数部的位数分配不同,导致可表示的数值范围和精度完全不同。

项目 FP16 (IEEE 754 半精度) bfloat16
总位数 16 16
指数部位数 5 8
尾数部位数 10 7
可表示的数值范围 约±6.1×10⁻⁵ 至 ±65504(范围较窄但尾数位多、精度较高) 约±1.2×10⁻³⁸ 至 ±3.4×10³⁸(与float32相同的宽范围,但精度较低)
主要用途 图像处理、图形学、推理时的省内存化(半精度训练) 深度学习训练(TPU、最新GPU)。从float32转换时无需担心指数溢出

bfloat16的指数部位数(8位)和偏移量(127)与float32(单精度)完全相同,因此只需截断float32的尾数部即可转换,这是实现上的一个优势。

使用提示

  • 即使是同一个值0.1,FP16和bfloat16的舍入误差表现也完全不同。切换格式比较尾数部的位模式吧。
  • bfloat16的指数部位数和偏移量与float32相同,因此即使是超过65504的大数值也不易溢出。相反FP16一旦超过65504就会立即变为无穷大。
  • 将"70000"转换为FP16会溢出变为无穷大,而bfloat16则能正常表示(精度有所下降)。
  • 在PyTorch、TensorFlow等机器学习框架中进行模型量化时,bfloat16容易从float32转换,而FP16由于范围较窄有时需要预先缩放。
  • 从位模式逆向转换为十进制时,需输入带`0x`前缀的4位十六进制值,或16位二进制值(`0b`前缀可省略)。

常见问题

两者合计都是16位,但FP16(IEEE 754半精度)是指数部5位、尾数部10位,而bfloat16是指数部8位、尾数部7位。FP16尾数位多精度更高但范围较窄,bfloat16能表示与float32相同的宽范围但精度较低。

深度学习训练中,梯度和参数可能变得非常大或非常小,因此更倾向于使用能保持float32那样宽的表示范围(不易溢出/下溢)同时将内存和计算量减半的bfloat16。FP16范围较窄容易溢出,训练时有时需要额外的损失缩放(loss scaling)。

约65504。若将超过此值的数转换为FP16,会因溢出而变为无穷大(Infinity)。而bfloat16与float32指数部位数相同,可表示约3.4×10³⁸的数值。

指数部全为0而尾数部不为0的位模式。常规(正规化)浮点数尾数有隐含的前导1,而非正规数省略了这一点,从而能表示比通常最小值更接近零的值(但牺牲了有效精度)。

bfloat16的指数部位数(8位)和偏移量(127)与float32完全一致,因此只需保留float32位模式尾数部的高7位(并四舍五入)即可转换,无需重新计算指数或检查范围,实现十分简单。
ツールくん

闲话 ― 为何机器学习需要"降低精度"的数值表示

2018年前后,Google为其TPU(Tensor Processing Unit)设计了一种新的16位浮点格式bfloat16。此前已存在的FP16(IEEE 754半精度)已在图像处理和图形学领域实用化,但由于指数部仅5位,可表示的数值范围较窄,难以应对深度学习训练中梯度时而极小、时而极大的现象(梯度消失、梯度爆炸)。

bfloat16的设计思路很明确:牺牲尾数部的精度,换取与float32(单精度)完全相同的8位指数部宽度,从而能安全处理训练过程中频繁出现的极大极小值。"Brain Floating Point"这个名字来源于Google的机器学习研究部门"Google Brain"。

在传统计算机科学中,降低浮点数精度一直被视为"漏洞的温床"而被避免。但深度学习模型有一种特殊性质:即使存在一定的数值误差,对最终预测精度的影响也微乎其微。利用这种"稍有不精确但整体仍能工作"的特性,将内存占用和计算成本减半的16位表示得以广泛普及,这可以说是有别于传统计算机科学常识的、机器学习领域独有的优化。