参考

浮点和整数的存储

不同数据类型在机器中的存储大小

type size min max
char 1 -128 127
unsigned char 1 0 255
short int 2 -32768 32767
unsigned short int 2 0 63535
int 4 -2147483648 2147483647
unsigned int 4 0 4294967295
long int 8 -2147483648 2147483647
unsigned long int 8 0 4294967295
float 4
double 8

浮点数的表示

IEEE浮点标准用 V=(1)s×M×2EV = (-1)^s \times M \times 2^E 的形式来表述一个浮点数:

  • ss : 符号(sign)s 决定这个浮点数的正(s=0)负(s=1)
  • MM : 有效数(significant)M 是一个二进制小数,它的范围在 [12ϵ][1\sim 2-\epsilon] 或者 [01ϵ][0\sim 1-\epsilon] 之间
  • EE : 指数(exponent)E 是 2 的幂(可能是符数,因为 E 的计算中有个bias),它的作用是对浮点数进行加权

浮点数的位(bits)被划分为三个域,以编码这三个值 s,M,Es, M, E

  • 1 位单独的符号位 ss 直接编码符号 ss
  • k 位的指数域 exp=ek1e1e0exp = e_{k-1}\cdots e_1e_0 编码指数 EE
  • n 位的小数域 frac=fn1f1f0frac = f_{n-1}\cdots f_{1}f_{0} 编码有效数 MM (但是被编码的值也依赖于指数域的值是否为 0)

在单精度浮点数(float)中,s=1,k=8,n=23s=1, k=8, n=23,产生一个 32 位的表示
在双精度浮点数(double)中,s=1,k=11,n=52s=1, k=11, n=52,产生一个 64 位的表示

规格化的值
当 exp 的位模式既不全位 0 (数值0), 也不全为 1 (单精度数值为 2^8 - 1 = 255, 双精度数值为 2^11 - 1 = 2047) 时, 对应的就是规格化的表示, 即 (1)s×M×2E(-1)^s \times M \times 2^E.
在规格化的表示中, 指数域被进行偏置 (biasd), 用来表示有符号的整数. 例如 ek1e1e0e_{k-1} \cdots e_1e_0 表示一个浮点数的指数域, 它对应一个整数值 e=i=0k1ei×2i[0,2k1]e = \sum_{i=0}^{k-1} e_i \times 2^{i} \in [0, 2^{k}-1], 令 bias=2k11bias = 2^{k-1} - 1 (单精度是 127, 双精度是 1023), E=ebiasE = e - bias, 由此产生的指数的取值范围: 单精度 (127+128)(-127 \sim +128), 双精度 (1023+1024)(-1023 \sim +1024). 另外注意在规格化的表示中, 指数的位值不能全 0 (单精度: -127, 双精度: -1023)和全 1 (单精度: +128, 双精度: +1024).
小数域 frac 被解释为小数部分的值, 例如 fn1f1f0f_{n-1} \cdots f_1f_0 可以表示小数 f=i=n10fi×(12)ni[0,112n]f = \sum_{i=n-1}^{0} f_i \times (\frac{1}{2})^{n - i} \in [0, 1-\frac{1}{2^n}]. 而我们将有效数 M 定义为 M=1+f[1,212n]M = 1 + f \in [1, 2 - \frac{1}{2^n}], 我们总能调整指数 E, 使得有效数 M 的范围在 1M<21 \leq M < 2 之中.

不同的float标准

混合精度 | MindSpore

浮点数格式:FP64, FP32, FP16, BFLOAT16, TF32之间的相互区别
bfloat16 floating-point format | wiki

bfloat16 其中的 b 指代 Google Brain

为什么要选择 bf16 进行深度学习的权重类型
bf16 拥有和 fp16 一样的大小 (2bytes), 相比于 fp32 (4bytes) 占用更少的内存, 所以在读取和存储的时候效率更高.
bf16 的指数域为 8 个 bits, 拥有和 fp32 一样的表示范围. 相比于 bp16, fp16 只有 5 bits 的指数域, 它所能表示的范围更小, 在训练过程中参数和结果有可能溢出. 当然, bp16 为了获得更大的表示范围为指数域分配了更多的比特位, 导致它的小数域只有 7 bits, 相比 fp16 的 10 bits 的小数域, bp16 所能表示的精度更低.

Format Bits Sign Exponent Bias Range Fraction
FP32 32 1 8 127 2127+12+12812^{-127+1} \sim 2^{+128-1} 23
FP16 16 1 5 15 215+12+1612^{-15+1} \sim 2^{+16-1} 10
BF16 16 1 8 127 2127+12+12812^{-127+1} \sim 2^{+128-1} 7

floatpointformat

混合精度训练指的是使用FP32作为主权重,而在进行前向和后向传播时使用FP16/BF16来提升训练速度,最后在梯度更新阶段再使用FP16/BF16梯度更新FP32主权重。