架构师_程序员_码农网

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

搜索
查看: 180|回复: 0

双精度(FP64)、单精度(P32、TF32)、半精度(FP16、BF16)

[复制链接]
发表于 2025-3-10 14:22:34 | 显示全部楼层 |阅读模式
大模型的训练和推理,经常涉及到精度的概念,种类很多,而且同等精度级别下,还分不同格式。另外,实际使用场景中,还有多精度和混合精度的概念。

常见精度

浮点数精度:双精度(FP64)、单精度(FP32、TF32)、半精度(FP16、BF16)、8位精度(FP8)、4位精度(FP4、NF4)
量化精度:INT8、INT4 (也有INT3/INT5/INT6的)

一个浮点数由三部分组成:符号位、指数位和尾数位。指数位越大,可表示的数字范围越大。尾数位越大、数字的精度越高。

1.jpg 2.jpg

总结如下表

格式符号位指数位小数位总位数
FP641115264
FP32182332
TF32181019
BF1618716
FP16151016
FP8 E4M31438
FP8 E5M21528
FP41214


FP32:32位浮点数,每个数据占4字节
TF32:19位浮点数,每个数据占2字节
FP16:16位浮点数,每个数据占2字节
BF16:16位浮点数,每个数据占2字节
Int8:8位整数,每个数据占1字节
Int4:4位整数,每个数据占0.5字节

为什么要有这么多精度

因为成本和准确度。都知道精度高肯定更准确,但是也会带来更高的计算和存储成本。较低的精度会降低计算精度,但可以提高计算效率和性能。所以多种不同精度,可以让你在不同情况下选择最适合的一种。
双精度比单精度表达的更精确,但是存储占用多一倍,计算耗时也更高,如果单精度足够,就没必要双精度。

为什么大模型需要量化

1. 降低内存占用
大模型通常使用32位浮点数(FP32)或16位浮点数(FP16)来表示权重和激活值。通过量化,可以将这些高精度的数值转换为更低精度的表示形式(如8位整数,INT8),从而显著减少模型的存储空间。这对于部署在资源有限的设备上(如移动设备、嵌入式系统等)非常重要。

2. 加速推理速度
量化后的模型可以在硬件上更高效地运行。许多现代硬件(如GPU、TPU、NPU等)对低精度计算有专门的优化支持,能够更快地执行量化后的操作。此外,低精度计算通常涉及更少的位运算,减少了计算复杂度,从而加快了推理速度。

3. 降低功耗
量化后的模型不仅减少了计算资源的需求,还降低了功耗。这对于电池供电的设备(如智能手机、物联网设备等)尤为重要,因为低功耗意味着更长的续航时间。

4. 便于边缘设备部署
许多大模型最初是在云端训练和部署的,但随着边缘计算的发展,越来越多的应用场景要求将模型部署到边缘设备上。由于边缘设备的计算能力和存储资源有限,量化可以帮助这些模型在边缘设备上更高效地运行。

5. 减少带宽需求
在分布式推理或模型更新的过程中,量化可以减少模型传输所需的带宽。这对于网络带宽有限的环境(如偏远地区的物联网设备)非常有用。

6. 保持模型性能
虽然量化会引入一定的精度损失,但通过适当的量化方法(如混合精度量化、后训练量化、量化感知训练等),可以在很大程度上保留模型的原始性能。因此,在实际应用中,量化能够在性能和效率之间取得良好的平衡。

内存的参考

类型每10亿参数需要占内存
float324G
fp16/bf162G
int81G
int40.5G


FP64(双精度)

64 位浮点,通常是IEEE 754 定义的双精度二进制浮点格式,具有:

1 位符号
11位指数
52 位小数

3.png

范围: ~2.23e-308 … ~1.80e308,具有完整的 15-17 位小数精度。

用法:

该格式用于精度要求较高的科学计算。
通常不用于深度学习计算。
软件支持:
在大多数 C/C++ 系统上表示double类型。
在TensorFlow(如tf.float64)/ PyTorch(如torch.float64或torch.double)中支持。
硬件支持:
通常在 x86 CPU 中支持。
大多数 GPU,尤其是包括 RTX 系列在内的游戏 GPU,其 FP64 性能受到严重限制(通常是 FP32 性能的 1/32,而不是 1/2)。
最近不受限制的 FP64 支持的 GPU 包括Tesla P100/P40/P4 和 Quadro GP100 中的GP100/102/104 、 Tesla V100/Quadro GV100/Titan V 中的GV100以及最近发布的 A100中的GA100(有趣的是,新的 Ampere 架构有第三代)与支持 FP64 的张量核相比,A100 Tensor Core 现在包含新的符合 IEEE 规范的 FP64 处理,其 FP64 性能是 V100 的 2.5 倍。

FP32(全精度)

这种格式长期以来一直是深度学习的主力。另一种 IEEE 754 格式,单精度浮点具有:

1 位符号
8位指数
23 位小数
理想情况下训练和推理都应该在 FP32 中完成,但 FP32 比 FP16/BF16 慢两倍,因此实践中常常使用混合精度方法,其中,使用 FP32 权重作为精确的 “主权重 (master weight)”,而使用 FP16/BF16 权重进行前向和后向传播计算以提高训练速度,最后在梯度更新阶段再使用 FP16/BF16 梯度更新 FP32 主权重。

在训练期间,主权重始终为 FP32。而在实践中,在推理时,半精度权重通常能提供与 FP32 相似的精度 —— 因为只有在模型梯度更新时才需要精确的 FP32 权重。这意味着在推理时我们可以使用半精度权重,这样我们仅需一半 GPU 显存就能获得相同的结果。

4.png

范围: ~1.18e-38 … ~3.40e38,精度为 6-9 位有效小数。

用法:

长期以来神经网络计算的标准类型。神经网络中的权重、激活和其他值长期以来默认以 FP32 表示。
对于许多科学计算(尤其是迭代计算)来说,精度不够,导致误差累积。
软件支持:
在大多数 C/C++ 系统上表示float类型。
在TensorFlow(如tf.float32)/ PyTorch(如torch.float32或torch.float)中受支持。
硬件支持:
通常在 x86 CPU 中受支持。
通常受 NVIDIA/AMD GPU 支持。

FP16(半精度)

同样,IEEE 754 标准格式,半精度浮点格式具有:

1 位符号
5位指数
10 位小数
FP16 数字的数值范围远低于 FP32。因此 FP16 存在上溢 (当用于表示非常大的数时) 和下溢 (当用于表示非常小的数时) 的风险。例如,当你执行 10k * 10k 时,最终结果应为 100M,FP16 无法表示该数,因为 FP16 能表示的最大数是 64k。因此你最终会得到 NaN (Not a Number,不是数字),在神经网络的计算中,因为计算是按层和 batch 顺序进行的,因此一旦出现 NaN,之前的所有计算就全毁了。一般情况下,我们可以通过缩放损失 (loss scaling) 来缓解这个问题,但该方法并非总能奏效。

5.png

范围: ~5.96e−8 (6.10e−5) … 65504,精度为 4 位有效十进制数字。

用法:

深度学习有使用 FP16 而不是 FP32 的趋势, 因为较低精度的计算对于神经网络来说似乎并不重要。额外的精度没有任何作用,同时速度较慢,需要更多内存并降低通信速度。
可用于训练,通常使用混合精度训练(TensorFlow / PyTorch)。
可用于训练后量化以加快推理速度 ( TensorFlow Lite )。用于训练后量化的其他格式包括整数INT8(8 位整数)、INT4(4 位)甚至INT1(二进制值)。
软件支持:
目前不在 C/C++ 标准中(但有一个short float提案)。某些C/C++ 系统支持__fp16类型。否则,可以与特殊库一起使用。
在TensorFlow(如tf.float16)/ PyTorch(如torch.float16或torch.half)中受支持。
硬件支持:
x86 CPU 不支持(作为一种独特的类型)。
在旧游戏 GPU 上的支持很差(FP32 的 1/64 性能,请参阅有关 GPU 的帖子了解更多详细信息)。目前在现代 GPU(例如 NVIDIA RTX 系列)上得到了良好的支持。

BFLOAT16(半精度)

另一种最初由 Google 开发的 16 位格式称为“ Brain Floating Point Format ”,简称“bfloat16”。这个名字来源于Google Brain。

最初的 IEEE FP16 设计时并未考虑深度学习应用,其动态范围太窄。 BFLOAT16 解决了这个问题,提供与 FP32 相同的动态范围。

因此,BFLOAT16 有:

1 位符号
8位指数
7 位小数

6.png

bfloat16 格式是截断的 IEEE 754 FP32,允许与 IEEE 754 FP32 之间进行快速转换。在转换为 bfloat16 格式时,指数位被保留,而尾数字段可以通过截断来减少。

7.jpg

范围: ~1.18e-38 … ~3.40e38,具有 3 位有效小数位。
用法:

现在似乎正在取代 FP16。与 FP16(通常需要通过损失缩放等技术进行特殊处理)不同,BF16 在训练和运行深度神经网络时几乎可以直接替代 FP32。
软件支持:
不在 C/C++ 标准中。可以与特殊的库一起使用。
在TensorFlow(如tf.bfloat16)/ PyTorch(如torch.bfloat16)中受支持。

TF32

TensorFloat-32或 TF32 是NVIDIA A100 GPU中的新数学模式。

TF32 使用与半精度 (FP16) 数学相同的 10 位尾数,事实证明,它具有足够的余量来满足 AI 工作负载的精度要求。并且TF32采用与FP32相同的8位指数,因此可以支持相同的数值范围。

从技术上讲,它是一种 19 位格式。可以将其视为扩展精度 BFLOAT16,例如“BFLOAT19” 或者像降低精度 FP32。

所以,TF32 有:

1 位符号
8位指数
10 位小数
TF32的优点是格式与FP32相同。使用 TF32 计算内积时,输入操作数的尾数从 23 位舍入到 10 位。舍入操作数精确相乘,并在普通 FP32 中累加。

TF32 Tensor Core 在 FP32 输入上运行并以 FP32 生成结果,无需更改代码。非矩阵运算继续使用FP32。这提供了在深度学习框架和 HPC 中加速 FP32 输入/输出数据的简单途径。

范围: ~1.18e-38 … ~3.40e38,精度为 4 位有效小数位。
用法:

TF32 的一大优点是仅在最深层(即 CUDA 编译器内部)需要编译器支持。其余代码只是看到 FP32 的精度较低,但动态范围相同。使用TF32主要是对库进行调用以显示它是否正常运行。 TF32 的存在可以快速插入,无需太多工作即可利用 Tensor Core 的速度。
FP16 和 BFLOAT16 等格式需要更多的调整,因为它们涉及不同的bit布局。但使用这些格式可以减少内存带宽,从而允许更快的执行速度。
作为比较,A100 的峰值性能为:

没有张量核心的 FP32:19.5 TFLOPS
TF32 张量核心:156 TFLOPS(因此,使用 TF32 代替 FP32 可以轻松提高速度)。
FP16/BF16 张量核:312 TFLOPS(因此,合理的切换到 FP16/BF16 可以带来更多速度提升,但成本更高)。
软件支持:
不在 C/C++ 标准中。
CUDA 11支持。
硬件支持:
GPU: NVIDIA A100是第一个支持的型号

FP8

由H100 GPU引入,实现更大的矩阵乘法和卷积量,但精度更低。

H100 支持的 FP8 数据类型实际上是 2 种不同的数据类型,可用于神经网络训练的不同部分:

E4M3 - 由 1 个符号位、4 个指数位和 3 位小数组成。它可以存储高达 +/-448 和nan.
E5M2 - 由 1 位符号位、5 位指数位和 2 位小数组成。它可以存储高达 +/-57344、+/-inf和的值nan。增加动态范围的代价是存储值的精度较低。

8.jpg

浮点数据类型的结构。显示的所有值(在 FP16、BF16、FP8 E4M3 和 FP8 E5M2 中)都是值 0.3952 的最接近表示。

在训练神经网络期间,可以使用这两种类型。通常,前向激活和权重需要更高的精度,因此最好在前向传递期间使用 E4M3 数据类型。然而,在后向传播中,流经网络的梯度通常不太容易受到精度损失的影响,但需要更高的动态范围。因此,最好使用 E5M2 数据格式存储它们。 H100 TensorCore 支持这些类型的任意组合作为输入,使我们能够使用其首选精度来存储每个张量。

参考:

https://zhuanlan.zhihu.com/p/696370474
https://zhuanlan.zhihu.com/p/712752948




上一篇:【网络】主路由和子路由下的设备互通
下一篇:【AI】(十)LLM 大模型推理 GPU 内存 VRAM 估算
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:help@itsvse.com

QQ|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2025-3-21 22:43

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表