8位存储的浮点数

论文

2022年发表了两篇论文,介绍了存储在字节上的浮点数,而不是存储在4字节上的float 32。浮点精度要低得多,但训练准确性不会受到太大影响。

FP8 Formats for Deep Learning 来自NVIDIA、Intel和ARM的介绍了两种遵循 IEEE规范的类型。 第一种是E4M3,1位用于符号,4位用于指数,3位用于尾数。第二种是E5M2,1位用于符号,5位用于指数,2位用于尾数。第一种类型主要用于权重,第二种用于梯度。

第二篇论文 8-bit Numerical Formats For Deep Neural Networks 介绍了 类似的类型。IEEE 标准为 +0(或整数 0)和 -0(或整数 128)赋予相同的值。 他们选择为这两个数字赋予不同的浮点值。论文实验了不同的指数和尾数分配,并展示了 E4M3 和 E5M2 是 最佳选择。

因此,在onnx==1.15.0中引入了四种新类型,以支持一组有限的运算符,从而启用浮点8的计算。

  • E4M3FN: 1位用于符号,4位用于指数,3位用于尾数,只有NaN值,没有无限值(FN),

  • E4M3FNUZ: 1 位用于符号,4 位用于指数,3 位用于尾数,只有 nan 值,没有无限值 (FN),没有负零 (UZ)

  • E5M2: 1位用于符号,5位用于指数,2位用于尾数,

  • E5M2FNUZ: 1 位用于符号,5 位用于指数,2 位用于尾数,只有 nan 值,没有无限值 (FN),没有负零 (UZ)

实现通常依赖于硬件。 NVIDIA、Intel 和 Arm 实现了 E4M3FNE5M2 是其最新的图形处理器。 GraphCore 仅使用 E4M3FNUZE5M2FNUZ 实现相同的功能。

E4M3FN 和 E5M2

\(S\) 代表符号。\(10_2\) 描述了一个基数为2的数字。

Float8 types

E4M3FN

E5M2

指数偏差

7

15

无穷大

\(S.11111.00_2\)

NaN

\(S.1111.111_2\)

\(S.11111.\{01, 10, 11\}_2\)

\(S.0000.000_2\)

\(S.00000.00_2\)

Max

\(S.1111.110_2\)

\(1.75 \times 2^{15}= 57344\)

Min

\(S.0000.001_2 = 2^{-9}\)

\(S.00000.01_2 = 2^{-16}\)

让我们将位表示记为 \(S.b_6 b_5 b_4 b_3 b_2 b_1 b_0\)。 浮点值由以下表达式定义:

Float8 types values

E4M3FN

E5M2

指数 \(\neq\) 0

\((-1)^S 2^{\sum_{i=3}^6 b_i 2^{i-3} - 7} \left( 1 + \sum_{i=0}^2 b_i 2^{i-3} \right)\)

\((-1)^S 2^{\sum_{i=2}^6 b_i 2^{i-2} - 15} \left( 1 + \sum_{i=0}^1 b_i 2^{i-2} \right)\)

指数 \(=\) 0

\((-1)^S 2^{-6} \sum_{i=0}^2 b_i 2^{i-3}\)

\((-1)^S 2^{-14} \sum_{i=0}^1 b_i 2^{i-2}\)

E4M3FNUZ 和 E5M2FNUZ

之前的类型支持正负零、正负NaN。 GraphCore引入了另一种类型定义,以更好地利用这四个值。每个名称中包含UZ的类型只有一个零和一个NaN(=负零)。另一个区别来自指数偏差。因此,由于这种指数偏差的差异,一个非空、非NaN的8位浮点数FLOAT8E4M3FN不能简单地转换为FLOAT8E4M3FNUZ。即使尾数相同,指数也不同。

Float8 types

E4M3FNUZ

E5M2FNUZ

指数偏差

8

16

无穷大

NaN

\(1.0000.000_2\)

\(1.00000.00_2\)

\(0.0000.000_2\)

\(0.00000.00_2\)

Max

\(S.1111.111_2\)

\(S.11111.11_2\)

Min

\(S.0000.001_2 = 2^{-10}\)

\(S.00000.01_2 = 2^{-17}\)

浮点值由以下表达式定义:

Float8 types values

E4M3FNUZ

E5M2FNUZ

指数 \(\neq\) 0

\((-1)^S 2^{\sum_{i=3}^6 b_i 2^{i-3} - 8} \left( 1 + \sum_{i=0}^2 b_i 2^{i-3} \right)\)

\((-1)^S 2^{\sum_{i=2}^6 b_i 2^{i-2} - 16} \left( 1 + \sum_{i=0}^1 b_i 2^{i-2} \right)\)

指数 \(=\) 0

\((-1)^S 2^{-7} \sum_{i=0}^2 b_i 2^{i-3}\)

\((-1)^S 2^{-15} \sum_{i=0}^1 b_i 2^{i-2}\)

类型转换

从float 8转换为 float 16(或E5M10), bfloat16(或E8M7), float32(或E8M23)更容易。 转换是精确的。对于特定值如-0-NaN,转换不一定保留符号。

转换为float 8包括找到最接近原始float 32值的float 8。通常通过移位和截断来完成。

转换可能会带有饱和,每个超出范围的值都会变为可用的最高值。下表总结了所有情况。[x] 表示该值四舍五入到目标尾数宽度。

x

E4M3FN

E4M3FNUZ

E5M2

E5M2FNUZ

0

0

0

0

0

-0

-0

0

-0

0

NaN

NaN

NaN

NaN

NaN

无穷大

FLT_MAX

NaN

FLT_MAX

NaN

-无穷大

-FLT_MAX

NaN

-FLT_MAX

NaN

[x] > FLT_MAX

FLT_MAX

FLT_MAX

FLT_MAX

FLT_MAX

[x] < -FLT_MAX

-FLT_MAX

-FLT_MAX

-FLT_MAX

-FLT_MAX

否则

RNE

RNE

RNE

RNE

转换也可以在没有任何饱和度的情况下定义。

x

E4M3FN

E4M3FNUZ

E5M2

E5M2FNUZ

0

0

0

0

0

-0

-0

0

-0

0

NaN

NaN

NaN

NaN

NaN

-NaN

-NaN

NaN

-NaN

NaN

无穷大

NaN

NaN

无穷大

NaN

-无穷大

-NaN

NaN

-无穷大

NaN

[x] > FLT_MAX

NaN

NaN

无穷大

NaN

[x] < -FLT_MAX

NaN

NaN

-无穷大

NaN

否则

RNE

RNE

RNE

RNE