浮点数存储在 8 位中

论文

2022 年发表了两篇论文,介绍了将浮点数存储在一个字节中,而不是将 32 位浮点数存储在 4 个字节中。浮点精度要低得多,但训练精度并没有受到太大影响。

用于深度学习的 FP8 格式 来自 NVIDIA、英特尔和 ARM,引入了两种类型,遵循 IEEE 规范。第一个是 E4M3,1 位表示符号,4 位表示指数,3 位表示尾数。第二个是 E5M2,1 位表示符号,5 位表示指数,2 位表示尾数。第一种类型主要用于权重,第二种类型用于梯度。

第二篇论文 深度神经网络的 8 位数值格式 介绍了类似的类型。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、英特尔和 ARM 在其最新的图形处理器中实现了 E4M3FNE5M2。GraphCore 也一样,只是使用的是 E4M3FNUZE5M2FNUZ

E4M3FN 和 E5M2

\(S\) 表示符号。 \(10_2\) 描述一个 2 进制数。

Float8 类型

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\)

最大值

\(S.1111.110_2\)

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

最小值

\(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 类型值

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 和负 NaN。GraphCore 引入了另一种类型定义,以便更好地利用这四个值。每个类型在其名称中包含 UZ 的类型只有一个零和一个 NaN(= 负零)。另一个区别来自指数偏差。因此,一个 8 位浮点数 *FLOAT8E4M3FN*,非空,非 NaN,不能简单地转换为 *FLOAT8E4M3FNUZ*,因为存在指数偏差差异。即使尾数相同,指数也不相同。

Float8 类型

E4M3FNUZ

E5M2FNUZ

指数偏差

8

16

无穷大

NaN

\(1.0000.000_2\)

\(1.00000.00_2\)

\(0.0000.000_2\)

\(0.00000.00_2\)

最大值

\(S.1111.111_2\)

\(S.11111.11_2\)

最小值

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

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

浮点值由以下表达式定义

Float8 类型值

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}\)

转换

从 8 位浮点数转换为 16 位浮点数(或 E5M10)、bfloat16(或 E8M7)、32 位浮点数(或 E8M23)更容易。转换是精确的。转换不一定保留特定值的符号,例如 -0-NaN

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

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

x

E4M3FN

E4M3FNUZ

E5M2

E5M2FNUZ

0

0

0

0

0

-0

-0

0

-0

0

NaN

NaN

NaN

NaN

NaN

Inf

FLT_MAX

NaN

FLT_MAX

NaN

-Inf

-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

Inf

NaN

NaN

Inf

NaN

-Inf

-NaN

NaN

-Inf

NaN

[x] > FLT_MAX

NaN

NaN

Inf

NaN

[x] < -FLT_MAX

NaN

NaN

-Inf

NaN

其他

RNE

RNE

RNE

RNE