8位浮点数¶
论文¶
2022年发表了两篇论文,介绍了以一个字节存储的浮点数,与以四个字节存储的float32相比。浮点精度低得多,但训练精度并未受到太大影响。
来自NVIDIA、Intel和ARM的FP8 Formats for Deep Learning介绍了两种遵循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
中引入了四种新类型,以支持一组有限的操作符,从而实现float 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\)表示二进制数。
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和负NaN。GraphCore引入了另一种类型定义,以更好地利用这四个值。所有名称中包含UZ的类型只有一个零和一个NaN(=负零)。另一个区别在于指数偏差。因此,一个非零、非NaN的float 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}\) |
Cast¶
从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 |
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 |
else |
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 |
else |
RNE |
RNE |
RNE |
RNE |
E8M0¶
E8M0数据类型作为所有OCP Microscaling (MX) Formats的通用比例类型。它有八位用于指数,没有符号位或尾数位。
E8M0 |
|
---|---|
指数偏差 |
127 |
无穷大 |
|
NaN |
\(11111111_2\) |
零 |
|
Max |
\(11111110_2 = 2^{127}\) |
Min |
\(00000000_2 = 2^{-127}\) |
在计算MX格式的比例因子时,可以做出不同的转换选择。因此,ONNX Cast
运算符规范引入了一个额外的“round_mode”属性,该属性接受以下值:
“up”:四舍五入到离零最近的值
“down”:四舍五入到零最近的值
“nearest”:四舍五入到最近的值,平局时向上舍入
研究表明,与其它舍入模式相比,饱和舍入在LLM预训练中能实现更高的精度。