ONNX中的8位浮点数(Float8)详解
引言
在深度学习领域,模型规模的不断扩大对计算资源提出了更高要求。为了优化计算效率,研究人员开始探索使用更低精度的浮点数格式。ONNX作为开放的神经网络交换格式,在1.15.0版本中引入了4种8位浮点数(Float8)类型,为深度学习模型的存储和计算提供了新的选择。
Float8的背景与意义
传统深度学习通常使用32位浮点数(FP32)进行计算,但这会占用大量内存和计算资源。2022年,NVIDIA、Intel和ARM联合发表的论文提出了两种8位浮点格式(E4M3和E5M2),另一篇论文则探讨了不同指数和尾数分配方案。研究表明,虽然8位浮点数的精度较低,但对模型训练准确率的影响有限。
ONNX支持的Float8类型
ONNX目前支持以下4种Float8类型:
1. E4M3FN
- 结构:1位符号位 + 4位指数位 + 3位尾数位
- 特点:支持NaN值,不支持无限值(FN)
- 典型应用:主要用于权重存储
2. E4M3FNUZ
- 结构:1位符号位 + 4位指数位 + 3位尾数位
- 特点:支持NaN值,不支持无限值(FN),无负零(UZ)
- 典型应用:GraphCore硬件专用
3. E5M2
- 结构:1位符号位 + 5位指数位 + 2位尾数位
- 特点:标准IEEE格式
- 典型应用:主要用于梯度计算
4. E5M2FNUZ
- 结构:1位符号位 + 5位指数位 + 2位尾数位
- 特点:支持NaN值,不支持无限值(FN),无负零(UZ)
- 典型应用:GraphCore硬件专用
Float8的数值表示
E4M3FN和E5M2格式
| 特性 | E4M3FN | E5M2 | |------------|---------------------------|--------------------------| | 指数偏置 | 7 | 15 | | 无穷大 | 不支持 | S.11111.00₂ | | NaN | S.1111.111₂ | S.11111.{01,10,11}₂ | | 零值 | S.0000.000₂ | S.00000.00₂ | | 最大值 | S.1111.110₂ | 1.75×2¹⁵=57344 | | 最小值 | S.0000.001₂=2⁻⁹ | S.00000.01₂=2⁻¹⁶ |
数值计算公式:
- 当指数≠0时:
- E4M3FN: $(-1)^S 2^{\sum_{i=3}^6 b_i 2^{i-3} - 7} (1 + \sum_{i=0}^2 b_i 2^{i-3})$
- E5M2: $(-1)^S 2^{\sum_{i=2}^6 b_i 2^{i-2} - 15} (1 + \sum_{i=0}^1 b_i 2^{i-2})$
- 当指数=0时:
- E4M3FN: $(-1)^S 2^{-6} \sum_{i=0}^2 b_i 2^{i-3}$
- E5M2: $(-1)^S 2^{-14} \sum_{i=0}^1 b_i 2^{i-2}$
E4M3FNUZ和E5M2FNUZ格式
| 特性 | E4M3FNUZ | E5M2FNUZ | |------------|--------------------------|--------------------------| | 指数偏置 | 8 | 16 | | 无穷大 | 不支持 | 不支持 | | NaN | 1.0000.000₂ | 1.00000.00₂ | | 零值 | 0.0000.000₂ | 0.00000.00₂ | | 最大值 | S.1111.111₂ | S.11111.11₂ | | 最小值 | S.0000.001₂=2⁻¹⁰ | S.00000.01₂=2⁻¹⁷ |
数值计算公式:
- 当指数≠0时:
- E4M3FNUZ: $(-1)^S 2^{\sum_{i=3}^6 b_i 2^{i-3} - 8} (1 + \sum_{i=0}^2 b_i 2^{i-3})$
- E5M2FNUZ: $(-1)^S 2^{\sum_{i=2}^6 b_i 2^{i-2} - 16} (1 + \sum_{i=0}^1 b_i 2^{i-2})$
- 当指数=0时:
- E4M3FNUZ: $(-1)^S 2^{-7} \sum_{i=0}^2 b_i 2^{i-3}$
- E5M2FNUZ: $(-1)^S 2^{-15} \sum_{i=0}^1 b_i 2^{i-2}$
类型转换规则
向高精度转换(Float8→Float16/BFloat16/Float32)
这种转换相对简单且精确,但可能不保留特定值(如-0或-NaN)的符号。
向低精度转换(Float32→Float8)
转换需要找到最接近的Float8值,通常通过位移和截断实现。转换可分为饱和模式和非饱和模式:
饱和模式转换表: | 输入x | E4M3FN | E4M3FNUZ | E5M2 | E5M2FNUZ | |-------------|---------|---------|---------|---------| | 超出正范围 | FLT_MAX | FLT_MAX | FLT_MAX | FLT_MAX | | 超出负范围 | -FLT_MAX| -FLT_MAX| -FLT_MAX| -FLT_MAX| | 其他 | 就近舍入 | 就近舍入 | 就近舍入 | 就近舍入 |
非饱和模式转换表: | 输入x | E4M3FN | E4M3FNUZ | E5M2 | E5M2FNUZ | |-------------|-------|---------|-----|---------| | 超出正范围 | NaN | NaN | Inf | NaN | | 超出负范围 | NaN | NaN | -Inf| NaN | | 其他 | 就近舍入| 就近舍入 | 就近舍入| 就近舍入|
实际应用建议
-
硬件兼容性:不同硬件厂商对Float8的实现有差异,NVIDIA、Intel和Arm主要支持E4M3FN和E5M2,而GraphCore则使用E4M3FNUZ和E5M2FNUZ。
-
使用场景:
- E4M3系列适合权重存储
- E5M2系列适合梯度计算
-
精度考量:虽然Float8能显著减少内存占用和计算开销,但在某些对精度敏感的场景中仍需谨慎使用。
-
转换策略:根据应用需求选择饱和或非饱和转换模式,前者能保证数值在有效范围内,后者则能更好地检测溢出情况。
通过合理使用Float8类型,开发者可以在模型精度和计算效率之间找到平衡点,为深度学习模型的部署和推理提供更多优化空间。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考