likes
comments
collection
share

精度fp32、fp16、bp16的表示范围计算

作者站长头像
站长
· 阅读数 4

可能是最容易懂的浮点数IEEE 754的表示范围计算方法了

题前:

学tensorRT捡起来考研的时候就写错了的浮点数的表示范围计算,我哭了鸭,我总算把这个知识点学会了啊,王道教我的时候就没教会啊TAT

TLDR

  • 指数位均为1表示特殊值

    • 无穷大 如0 11111 0000000000
    • NaN 如0 11111 0000000001
  • 最大正值 如 0 11110 1111111111

    • 符号位 0
    • 指数位除最后一位为0外均为1
    • 尾数均为1
  • 最小正值 如 0 00000 0000000001 【这是非规格数】

    • 符号位 0
    • 指数位均为0
    • 尾数除最后一位为1外均为0

计算规则

  • 正规数
    • 指数部分:二进制-偏置数
    • 尾数部分:1+尾数 (有隐含的前导1)
    • 计算:(−1)符号位×2阶码×(1+尾数)(-1)^{符号位} \times 2^{阶码} \times (1+尾数)(1)符号位×2阶码×(1+尾数)
  • 非正规数 【当指数部分全为0时为非正规数】
    • 固定指数部分:1-偏置数
    • 尾数部分:尾数 (没有隐含的前导1,直接是尾数)
    • 计算:(−1)符号位×21−偏置数×尾数(-1)^{符号位} \times 2^{1-偏置数} \times 尾数(1)符号位×21偏置数×尾数

示例

0 00000001 0000001 (正规数 )

  • 指数部分 1−127=−1261 - 127 = -1261127=126 这是正规数
  • 尾数部分 尾数的十进制值,正规数有隐含的1,0000001(2)=2−70000001_{(2)} = 2^{-7}0000001(2)=27,所以需要1+2−71+2^{-7}1+27
  • 2−126×(1+2−7)=6.11×10−52^{-126} \times (1 + 2^{-7}) = 6.11 \times 10^{-5}2126×(1+27)=6.11×105

0 00000000 0000001 (非正规数)

  • 指数部分 1−127=−1261 - 127 = -1261127=126 对于非规格数实际指数固定为 1−偏置值1−偏置值1偏置值
  • 尾数部分 尾数的十进制值,因为是非规格数,没有隐含的1,0000001(2)=2−70000001_{(2)} = 2^{-7}0000001(2)=27, 所以只有 2−72^{-7}27,不需要+1
  • 2−126×2−7=2−133=9.2×10−412^{-126} \times 2^{-7} = 2^{-133} = 9.2 × 10^{−41}2126×27=2133=9.2×1041

参考文献

www.paddlepaddle.org.cn/documentati… 但要指出的是这里有一个问题

精度fp32、fp16、bp16的表示范围计算

BF16(BFloat16)

表示范围 :[9.2×10−41,3.38953139×1038][9.2 × 10^{−41} , 3.38953139×10^{38}] [9.2×10413.38953139×1038]

  • BF16使用16位表示浮点数,其中1位用于符号位,8位用于指数部分,7位用于尾数部分。
  • BF16提供了较高的计算速度和较小的内存占用,适用于深度学习加速器(如TPU)等场景。
  • BF16的精度介于FP16和FP32之间,适用于一些计算密集型任务。

bf16最大正值

0 11111110 1111111

  • 指数部分 254 - 127 = 127
  • 2127×(1+1−2−7)=2127×1.9921875=3.38953139×10382^{127} \times (1+ 1- 2^{-7}) = 2^{127} \times 1.9921875 = 3.38953139×10^{38}2127×(1+127)=2127×1.9921875=3.38953139×1038

bf16最小正值

0 00000000 0000001

  • 指数部分 1 - 127 = -126 对于非规格数实际指数固定为 1−偏置值
  • 尾数部分 尾数的十进制值,因为是非规格数,没有隐含的1, 所以只有 2^{-7},不需要+1
  • 2−126×2−7=2(−133)=9.2×10−412^{-126} \times 2^{-7} = 2^(-133) = 9.2 × 10^{−41}2126×27=2(133)=9.2×1041

注意

0 00000001 0000001

  • 指数部分 1 - 127 = -126 这是正规数
  • 尾数部分 尾数的十进制值,正规数有隐含的1,所以需要1+2^{-7}
  • 2−126×(1+2−7)=6.11×10−52^{-126} \times (1 + 2^{-7}) = 6.11 \times 10^{-5}2126×(1+27)=6.11×105

2. FP16(Half Precision)

表示范围 :[5.96×10−8,65504][5.96 \times 10^{-8}, 65504][5.96×108,65504]

  • FP16也使用16位表示浮点数,其中1位用于符号位,5位用于指数部分,10位用于尾数部分。

  • FP16提供了较高的计算速度和较小的内存占用,适用于GPU等设备上的深度学习计算。

  • FP16的精度较低,可能会导致数值精度损失,但在一些情况下可以提高计算速度和减少内存占用。

  • FP16的最大值是由以下几部分构成:

    • 符号位为 0(表示正数)。
    • 指数位为 11110(最大指数值 - 1,因为 11111 用于表示无穷大和NaN)。
    • 尾数位为 1111111111(尾数位全为1提供了该指数级别下可能的最大尾数)。

计算 FP16 的最大正规数

  • 给定上述结构,FP16的最大正规数计算如下:
  • 指数计算:最大指数位为 11110,代表的指数值为 2+4+8+16 = 30 ,偏移量15 ,30-15 = 15

选择15作为偏移量是为了在5位指数中平衡正负数的表示范围。这样的设计确保了:

  • 能表示的最小指数是 -14(对于非正规数)和 -15(对于正规数)。
  • 能表示的最大指数是 +15。
  • 特殊编码(全0和全1的指数)被用来表示0、非正规数、无穷大和NaN。
  • 尾数计算:尾数位 1111111111 表示的额外值为 1−2^{−10} =0.9990234375。

最大正规数为 1.9990234375× 2 ^15 =65504。

fp16的最小正值是

  • 指数部分 1 - 15 = -14
  • 0 00000 0000000001 = 2−14×2−10=2−24=(0.000000059604645)10=5.96×10−82^{-14} \times 2^{-10} = 2^{-24} = (0.000000059604645)_{10} = 5.96 \times 10^{-8}214×210=224=(0.000000059604645)10=5.96×108

bf16 vs fp16

总的来说,

BF16提供了更好的精度和表示范围,适用于一些需要较高精度的任务,

而FP16提供了更快的计算速度和更小的内存占用,适用于一些对精度要求不那么严格的任务。

正规数vs非规格数

在讨论FP16或BF16等浮点数格式的最大值、最小值以及表示范围时,我们通常指的是正规数(normalized numbers)。这是因为正规数能够使用其所有的位精确地表示数值,并利用隐含的前导一优化存储空间。非正规数通常用于填补零与最小正规数之间的间隙,允许接近零的值能够被表示,尽管这些数的精度较低。

  • 关于正规数和非正规数
    • 最大值:通常指最大的正规数,这是浮点格式可以表示的最大的非无穷大数值。
    • 最小值:在不同上下文中,这可能指最小的正规数或最小的正非正规数。最小的正规数是除零外,可以表示的最小的正数,并且具有完整的精度。而最小的正非正规数是可以表示的最接近零的正数,但精度较低。
  • 正规数(Normalized Numbers)正规数是浮点数格式中的一种数,其中包括:
    • 非零的指数。
    • 一个隐含的前导一(即尾数部分在数学上总是以1开始)。

对于正规数,其二进制表示的指数部分从最小的正值开始(全0保留为表示非正规数和零),使得尾数能够用其全部位精确地表示数字,而指数则提供了数值的大小级。例如,在FP16中,最小正规指数是 -14(编码为 00001),对应于二进制表示中的实际指数 1−15=−14。

  • 非正规数(Subnormal Numbers)非正规数用于表示非常接近于零的数值,这些数值太小,不能以正规数的形式表示。在非正规数的表示中:
    • 指数部分为全0,这是一个特殊编码,表示这些数的实际指数比正规数的最小指数还要小一级(在FP16中为 −14−1=−15)。
    • 没有隐含的前导一,尾数直接从0开始,这减少了数值的精度,但增加了接近零的表示范围。

非正规数的引入主要是为了解决“下溢”问题,即当数值过小,无法表示为正规数时,如果没有非正规数,这些值就会直接四舍五入为零。使用非正规数可以让我们表示和处理这些极小的值,虽然这样做牺牲了一些精度。