searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

深度学习中的数值精度分析

2024-08-29 09:42:16
29
0

1、概述

相比于 CPU,GPU 在架构设计时将更多的晶体管用于数据处理,而不是数据缓存和流量控制,因此可以高度实现并行计算。由于深度学习是基于大量矩阵运算实现的,因此我们往往使用 GPU 训练深度学习网络。GPU 的计算能力和显存大小决定了计算速度和可运行的网络的大小,但除了 GPU 本身的性能外,网络训练/推理的性能还与我们使用的数据类型有关。在大模型时代,低精度和混合精度的使用非常常见。本文列出NVIDIA CUDA支持的数据类型,详细分析每种数据类型的空间占用情况、数据表达能力和精度分辨。

2、基础概念

本节主要介绍数据的存储方式(包括高精度和低精度数据)

2.1 数据存储

浮点数据在计算机内都是以二进制方式存储的,主要由三部分组成:

  • 符号位(Sign, 简称S): 0表示正数,1表示负数;
  • 指数位(Exponent, 简称E): 用于存储科学计数法的指数部分,其大小决定了数据的表达能力(表示范围);
  • 尾数位(Mantissa, 简称M): 用于存储尾数(小数)部分,其大小决定了数据能够表达的分辨率(精度);

2.2 高精度数据

下图展示了NVIDIA GPU中支持的高精度浮点数据类型, 详细给出了了每种数据类型的三部分分别占用的比特位数大小,后续我们根据每种数据类型对应部分的比特位数计算分析其表达能力和数值精度。
1280X1280.PNG

注意:

  • 通常在科学计算领域只有double才算是高精浮点类型,在AI领域fp32也算是高精度表示了;

  • tf32数据只有10bit位表示小数(精度), 在AI领域也是低精度数据,这里为了跟fp32比较,将它画在一起;

2.3 低精度数据

下图展示了NVIDIA GPU中支持的低精度浮点数据类型, 详细给出了了每种数据类型的三部分分别占用的比特位数大小,后续我们根据每种数据类型对应部分的比特位数计算分析其表达能力和数值精度。特别强调是的,FP8格式有不同的表达,如E5M2/E4M3分别表示5bit指数+2bit精度的高表达低精度的类型,以及4bit指数+3bit小数的低表达高精度的类型(在NVIDIA GPU中,目前只有H100+的GPU才支持FP8精度!)。
1280X1280 (1).PNG

3、能力与精度

为了彻底搞懂每一种数据类型的表达能力和精度,我们对2个典型的数据类型进行计算和分析,彻底搞懂特定数据表达能力和精度的计算方式和流程。

3.1 浮点数表示

我们首先回顾一下浮点数的表示方式
企业微信截图_20240828193900.png

其中,
01.png

浮点数可以看做是在2^n和2^(n+1)两个连续2次幂至之间有m个均匀的网络,由于对于不同的数据范围,2^n到2^(n+1)之间的数值的数量不均等,因此浮点数在不同的范围内的精度也不相同。以为bf16例,其在不同数值区间的数值精度如下:
output.png

可以发现,浮点数在原点附近精度最高,可以达到2^(-m)。数值逐渐远离原点的同时,数值精度也逐渐下降。

3.2 float

Float数据又称为全精度数据,在计算机中使用32个二进制位也即2个字节来表示和存储,其由1位符号位、8位指数位和23位尾数位组成,明细如下:
企业微信截图_20240828194043.png

于是,fp32的数据计算方式为:
企业微信截图_20240828194007.png

  • 特殊情况-1 e为00000000
  • 企业微信截图_20240828194014.png
  • 特殊情况-2 e为111111111
    企业微信截图_20240828194111.png

综上所述:
企业微信截图_20240828194023.png

其中的精度表示在原点附近的精度,远离原点精度会降低!

3.3 fp16

Float16数据又称为半精度数据,在计算机中使用16个二进制位也即2个字节来表示和存储,其由1位符号位、5位指数位和10位尾数位组成,明细如下:
企业微信截图_20240828193959.png

于是,fp16的数据计算方式为:
企业微信截图_20240828194049.png

  • 特殊情况-1 e为00000
    企业微信截图_20240828194101.png
  • 特殊情况-2 e为111111
    企业微信截图_20240828194111.png

综上所述:
企业微信截图_20240828194118.png

3.4 fp8

8d09a328-d20b-4261-959a-765abcb70ec5.png
6d4a3ecf-0c07-4f9d-b1cb-6efd07601c2c.png

可以看到,因为FP8格式的设计遵循与IEEE-754约定保持一致的原则,只有在DL应用精度有望获得显著提高时才会偏离。因此,E5M2格式遵循IEEE754对指数和特殊值的约定,可视为IEEE半精度,但尾数位数较少(类似于bfloat16和TF32可视为IEEE单精度,但位数较少)。

这使得E5M2和IEEEFP16格式之间可以直接转换。相比之下,E4M3的动态范围是通过回收用于特殊值的大部分比特模式来扩展,因为在这种情况下,所实现的更大范围要比支持特殊值的多种编码有用得多。如下表所示, 在 NVIDIA H100 Tensor Core GPU上为例,单位是TFLOPS,相较FP16和BF16,FP8的峰值性能能够实现翻倍:

企业微信截图_20240828194144.png

c9ddc9ce-4974-4eda-aaed-927a489b89bc.png

3.5 fp4/nf4

nf4全称为4-bit Fixed Point,指的是 4 位定点数格式。与浮点数不同,定点数使用固定的小数点位置来表示数值。这种格式对于需要固定精度和对计算效率要求较高的场景非常有用

dadf306a-da34-43bc-b98e-3c186c5c5789.png

3.6 总结

数据类型 比特位 符号位 指数位 尾数位 数值范围 数值精度
double 64 1 11 52 -1.79e308~1.79e308 1e-15
float 32 1 8 23 -3.4e38~3.4e38 1e-6
tf32 19 1 8 10 -3.4e38~3.4e38 1e-3
fp16 16 1 5 10 -65504~65504 1e-3
bf16 16 1 8 7 -3.39e38~3.39e38 1e-2
fp8 8 1 5 2 -57344~57344 0.25
fp8 8 1 4 3 -448~448 0.125
fp8 8 1 4 3 -240~240 0.125
int 32 1 31 - -2.15e9~2.15e9 1
int16 16 1 15 - -32768~32767 1
int8 8 1 7 - -128~127 1

需要注意的是FP8有许多种类型,如下:
企业微信截图_20240828194414.png

虽然都是 E5M2 或者 E4M3,不同公司的硬件可能采用不同的格式。比如 NVIDIA GPU 上的 E5M2 符合 IEEE 754 Style,而 E4M3 却不符合 IEEE 754 Style,本文中没有特殊说明都以 ARM-Intel-Nvidia Style 为例。如下图所示,IEEE 754 Style 的 E4M3 的范围为 [-240, 240],而 ARM-Intel-Nvidia Style 的 E4M3 的范围是 [-448, 448]:
企业微信截图_20240828194427.png

4、Pytorch验证

import torch

print(torch.finfo(torch.float64))
#finfo(resolution=1e-15, min=-1.79769e+308, max=1.79769e+308, eps=2.22045e-16, tiny=2.22507e-308, dtype=float64)

print(torch.finfo(torch.float32))
# finfo(resolution=1e-06, min=-3.40282e+38, max=3.40282e+38, eps=1.19209e-07, tiny=1.17549e-38, dtype=float32)

print(torch.finfo(torch.float16))
# finfo(resolution=0.001, min=-65504, max=65504, eps=0.000976562, tiny=6.10352e-05, dtype=float16)

print(torch.finfo(torch.bfloat16))
# finfo(resolution=0.01, min=-3.38953e+38, max=3.38953e+38, eps=0.0078125, tiny=1.17549e-38, dtype=bfloat16)

print(torch.finfo(torch.float8_e5m2))
# finfo(resolution=1, min=-57344, max=57344, eps=0.25, smallest_normal=6.10352e-05, tiny=6.10352e-05, dtype=float8_e5m2)

print(torch.finfo(torch.float8_e5m2fnuz))
#finfo(resolution=1, min=-57344, max=57344, eps=0.125, smallest_normal=3.05176e-05, tiny=3.05176e-05, dtype=float8_e5m2fnuz)

print(torch.finfo(torch.float8_e4m3fnuz))
# finfo(resolution=1, min=-240, max=240, eps=0.125, smallest_normal=0.0078125, tiny=0.0078125, dtype=float8_e4m3fnuz)

print(torch.finfo(torch.float8_e4m3fn))
# finfo(resolution=1, min=-448, max=448, eps=0.125, smallest_normal=0.015625, tiny=0.015625, dtype=float8_e4m3fn)
0条评论
0 / 1000
c****d
4文章数
0粉丝数
c****d
4 文章 | 0 粉丝
原创

深度学习中的数值精度分析

2024-08-29 09:42:16
29
0

1、概述

相比于 CPU,GPU 在架构设计时将更多的晶体管用于数据处理,而不是数据缓存和流量控制,因此可以高度实现并行计算。由于深度学习是基于大量矩阵运算实现的,因此我们往往使用 GPU 训练深度学习网络。GPU 的计算能力和显存大小决定了计算速度和可运行的网络的大小,但除了 GPU 本身的性能外,网络训练/推理的性能还与我们使用的数据类型有关。在大模型时代,低精度和混合精度的使用非常常见。本文列出NVIDIA CUDA支持的数据类型,详细分析每种数据类型的空间占用情况、数据表达能力和精度分辨。

2、基础概念

本节主要介绍数据的存储方式(包括高精度和低精度数据)

2.1 数据存储

浮点数据在计算机内都是以二进制方式存储的,主要由三部分组成:

  • 符号位(Sign, 简称S): 0表示正数,1表示负数;
  • 指数位(Exponent, 简称E): 用于存储科学计数法的指数部分,其大小决定了数据的表达能力(表示范围);
  • 尾数位(Mantissa, 简称M): 用于存储尾数(小数)部分,其大小决定了数据能够表达的分辨率(精度);

2.2 高精度数据

下图展示了NVIDIA GPU中支持的高精度浮点数据类型, 详细给出了了每种数据类型的三部分分别占用的比特位数大小,后续我们根据每种数据类型对应部分的比特位数计算分析其表达能力和数值精度。
1280X1280.PNG

注意:

  • 通常在科学计算领域只有double才算是高精浮点类型,在AI领域fp32也算是高精度表示了;

  • tf32数据只有10bit位表示小数(精度), 在AI领域也是低精度数据,这里为了跟fp32比较,将它画在一起;

2.3 低精度数据

下图展示了NVIDIA GPU中支持的低精度浮点数据类型, 详细给出了了每种数据类型的三部分分别占用的比特位数大小,后续我们根据每种数据类型对应部分的比特位数计算分析其表达能力和数值精度。特别强调是的,FP8格式有不同的表达,如E5M2/E4M3分别表示5bit指数+2bit精度的高表达低精度的类型,以及4bit指数+3bit小数的低表达高精度的类型(在NVIDIA GPU中,目前只有H100+的GPU才支持FP8精度!)。
1280X1280 (1).PNG

3、能力与精度

为了彻底搞懂每一种数据类型的表达能力和精度,我们对2个典型的数据类型进行计算和分析,彻底搞懂特定数据表达能力和精度的计算方式和流程。

3.1 浮点数表示

我们首先回顾一下浮点数的表示方式
企业微信截图_20240828193900.png

其中,
01.png

浮点数可以看做是在2^n和2^(n+1)两个连续2次幂至之间有m个均匀的网络,由于对于不同的数据范围,2^n到2^(n+1)之间的数值的数量不均等,因此浮点数在不同的范围内的精度也不相同。以为bf16例,其在不同数值区间的数值精度如下:
output.png

可以发现,浮点数在原点附近精度最高,可以达到2^(-m)。数值逐渐远离原点的同时,数值精度也逐渐下降。

3.2 float

Float数据又称为全精度数据,在计算机中使用32个二进制位也即2个字节来表示和存储,其由1位符号位、8位指数位和23位尾数位组成,明细如下:
企业微信截图_20240828194043.png

于是,fp32的数据计算方式为:
企业微信截图_20240828194007.png

  • 特殊情况-1 e为00000000
  • 企业微信截图_20240828194014.png
  • 特殊情况-2 e为111111111
    企业微信截图_20240828194111.png

综上所述:
企业微信截图_20240828194023.png

其中的精度表示在原点附近的精度,远离原点精度会降低!

3.3 fp16

Float16数据又称为半精度数据,在计算机中使用16个二进制位也即2个字节来表示和存储,其由1位符号位、5位指数位和10位尾数位组成,明细如下:
企业微信截图_20240828193959.png

于是,fp16的数据计算方式为:
企业微信截图_20240828194049.png

  • 特殊情况-1 e为00000
    企业微信截图_20240828194101.png
  • 特殊情况-2 e为111111
    企业微信截图_20240828194111.png

综上所述:
企业微信截图_20240828194118.png

3.4 fp8

8d09a328-d20b-4261-959a-765abcb70ec5.png
6d4a3ecf-0c07-4f9d-b1cb-6efd07601c2c.png

可以看到,因为FP8格式的设计遵循与IEEE-754约定保持一致的原则,只有在DL应用精度有望获得显著提高时才会偏离。因此,E5M2格式遵循IEEE754对指数和特殊值的约定,可视为IEEE半精度,但尾数位数较少(类似于bfloat16和TF32可视为IEEE单精度,但位数较少)。

这使得E5M2和IEEEFP16格式之间可以直接转换。相比之下,E4M3的动态范围是通过回收用于特殊值的大部分比特模式来扩展,因为在这种情况下,所实现的更大范围要比支持特殊值的多种编码有用得多。如下表所示, 在 NVIDIA H100 Tensor Core GPU上为例,单位是TFLOPS,相较FP16和BF16,FP8的峰值性能能够实现翻倍:

企业微信截图_20240828194144.png

c9ddc9ce-4974-4eda-aaed-927a489b89bc.png

3.5 fp4/nf4

nf4全称为4-bit Fixed Point,指的是 4 位定点数格式。与浮点数不同,定点数使用固定的小数点位置来表示数值。这种格式对于需要固定精度和对计算效率要求较高的场景非常有用

dadf306a-da34-43bc-b98e-3c186c5c5789.png

3.6 总结

数据类型 比特位 符号位 指数位 尾数位 数值范围 数值精度
double 64 1 11 52 -1.79e308~1.79e308 1e-15
float 32 1 8 23 -3.4e38~3.4e38 1e-6
tf32 19 1 8 10 -3.4e38~3.4e38 1e-3
fp16 16 1 5 10 -65504~65504 1e-3
bf16 16 1 8 7 -3.39e38~3.39e38 1e-2
fp8 8 1 5 2 -57344~57344 0.25
fp8 8 1 4 3 -448~448 0.125
fp8 8 1 4 3 -240~240 0.125
int 32 1 31 - -2.15e9~2.15e9 1
int16 16 1 15 - -32768~32767 1
int8 8 1 7 - -128~127 1

需要注意的是FP8有许多种类型,如下:
企业微信截图_20240828194414.png

虽然都是 E5M2 或者 E4M3,不同公司的硬件可能采用不同的格式。比如 NVIDIA GPU 上的 E5M2 符合 IEEE 754 Style,而 E4M3 却不符合 IEEE 754 Style,本文中没有特殊说明都以 ARM-Intel-Nvidia Style 为例。如下图所示,IEEE 754 Style 的 E4M3 的范围为 [-240, 240],而 ARM-Intel-Nvidia Style 的 E4M3 的范围是 [-448, 448]:
企业微信截图_20240828194427.png

4、Pytorch验证

import torch

print(torch.finfo(torch.float64))
#finfo(resolution=1e-15, min=-1.79769e+308, max=1.79769e+308, eps=2.22045e-16, tiny=2.22507e-308, dtype=float64)

print(torch.finfo(torch.float32))
# finfo(resolution=1e-06, min=-3.40282e+38, max=3.40282e+38, eps=1.19209e-07, tiny=1.17549e-38, dtype=float32)

print(torch.finfo(torch.float16))
# finfo(resolution=0.001, min=-65504, max=65504, eps=0.000976562, tiny=6.10352e-05, dtype=float16)

print(torch.finfo(torch.bfloat16))
# finfo(resolution=0.01, min=-3.38953e+38, max=3.38953e+38, eps=0.0078125, tiny=1.17549e-38, dtype=bfloat16)

print(torch.finfo(torch.float8_e5m2))
# finfo(resolution=1, min=-57344, max=57344, eps=0.25, smallest_normal=6.10352e-05, tiny=6.10352e-05, dtype=float8_e5m2)

print(torch.finfo(torch.float8_e5m2fnuz))
#finfo(resolution=1, min=-57344, max=57344, eps=0.125, smallest_normal=3.05176e-05, tiny=3.05176e-05, dtype=float8_e5m2fnuz)

print(torch.finfo(torch.float8_e4m3fnuz))
# finfo(resolution=1, min=-240, max=240, eps=0.125, smallest_normal=0.0078125, tiny=0.0078125, dtype=float8_e4m3fnuz)

print(torch.finfo(torch.float8_e4m3fn))
# finfo(resolution=1, min=-448, max=448, eps=0.125, smallest_normal=0.015625, tiny=0.015625, dtype=float8_e4m3fn)
文章来自个人专栏
AI-大型语言模型
2 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
1
0