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 实现了 E4M3FN 和 E5M2 是其最新的图形处理器。
GraphCore 仅使用 E4M3FNUZ 和 E5M2FNUZ 实现相同的功能。
E4M3FN 和 E5M2¶
\(S\) 代表符号。\(10_2\) 描述了一个基数为2的数字。
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\)。 浮点值由以下表达式定义:
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。即使尾数相同,指数也不同。
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}\) |
浮点值由以下表达式定义:
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 |