当前位置: 首页 > news >正文

大语言模型(LLM)量化基础知识(一)

请大家关注我的知乎博客:- 派神 - - 知乎

随着大型语言模型 (LLM) 的参数数量的增长,与其支持硬件(加速器内存)增长速度之间的差距越来越大,如下图所示:

上图显示,从 2017 年到 2022 年,语言模型的大小显著增加:

  •  2017 年: Transformer 模型(0.05B 参数)
  • 2018 年: GPT(0.11B 参数)、BERT(0.34B 参数)
  • 2020 年: GPT-2(1.5B 参数)、MegatronLM(8.3B 参数)
  • 2021 年: GPT-3(175B 参数)、T-NLG(17B 参数)
  • 2022 年: MT-NLG(530B 参数)

加速器(一般指GPU)是专门的硬件,用于加速机器学习训练。它们的内存容量对于训练大型模型至关重要。图中显示加速器内存的增长速度远低于模型大小的增长速度:

  • 2017 年: TPUv2(16GB)
  • 2018 年: V100(32GB)
  • 2020 年: TPUv3(32GB)
  • 2021 年: A100(40GB)
  • 2022 年: A100(80GB)
  • 在 2023 年至 2024 年期间,最大且最常用的模型的参数量大约在 700 亿左右。

上图显示了模型大小和加速器内存之间不断增长的差距。“差距”表示模型大小的增长速度远远超过了硬件内存容量的增长速度。这种差距对 LLM 的训练和部署提出了重大挑战。2022 年,模型规模达到了顶峰,但到了 2023 年,人们发现中等规模的模型(~70B 参数)在实际应用中更加实用和高效。然而加速器内存的增长速度没有跟上模型大小的增长速度。 这突出了对更高效的训练技术、模型压缩方法和专用硬件的需求,以克服这一瓶颈。

大型模型的规模和复杂性会限制其访问性和实用性,因此需要找到解决方案,将一个大型、复杂的模型转换为一个更小、更高效的模型,同时保留其核心功能,从而提高可访问性和实用性。 这使得在资源有限的环境中部署和使用模型成为可能。

模型压缩的方法

为了将一个大型、复杂的模型转换为一个更小、更高效的模型,我们需要使用一些模型压缩的方法,下面我们来介绍几种模型压缩的方法: 1.剪枝(Pruning),2.知识蒸馏(Knowledge Distillation),3.量化(Quantization),这里我们会深入讲解 第三种 量化(Quantization)方法,对于剪枝(Pruning)和知识蒸馏(Knowledge Distillation)我们只做简单介绍。

1.剪枝(Pruning)

剪枝(Pruning)的核心思想是移除对模型性能提升不大的连接或神经元,从而减小模型的大小和复杂度:

2.知识蒸馏(Knowledge Distillation)

知识蒸馏(Knowledge Distillation)的核心思想是使用一个已经训练好的大型模型(教师模型)来指导一个较小型模型(学生模型)的训练,从而将大型模型的知识“蒸馏”到小型模型中。 

知识蒸馏指的是使用一个训练好的大型模型(教师模型)来指导小型模型(学生模型)的训练,从而使小型模型获得与大型模型相近的性能,实现模型压缩的目的。 

3. 量化(Quantization)

在讲解量化方法之前,我们先回归一下神经网络:

上图是神经网络的一个隐藏层,展示了线性层 followed by 激活函数的计算过程,其中:

  • w₁, b₁, w₂, b₂, w₃, b₃: 这些是神经网络的权重(Weights,蓝色w) 和偏差(Biases,紫色b)。每个神经元都有一组对应的权重和偏差。
  • x: 橙色箭头和 x 指的是输入向量。
  • a₁, a₂, a₃: 这些是每个神经元的输出,也就是激活值(Activations)。
  • 公式 aᵢ = g(wᵢ ⋅ x + bᵢ): 这展示了线性层 followed by 激活函数的计算过程。其中:
    •     wᵢ ⋅ x 表示权重向量和输入向量的点积。
    •     + bᵢ 表示加上偏差。
    •     g() 表示激活函数。
  • 公式 g(z) = 1 / (1 + e⁻ᶻ): 这定义了激活函数 g(z) 为 sigmoid 函数。sigmoid 函数将线性层的输出映射到 0 到 1 之间,引入非线性。

在神经网络中,我们可以量化权重和激活值,其中:

  • 权重 (w̄):神经网络参数
  • 激活值 (a):在神经网络层中传播的值
  • 例如,在线性层中,a = g(w̄ ⋅ x + b);a 是激活值;w̄ 和 b 是权重。这里用一个线性层的例子进一步解释了激活值、权重和偏差的关系。

有了神经网络的基础知识后,下面我们来真正进入主题,我们来讨论一下模型压缩中的一种重要技术:量化(Quantization)。 它通过降低模型参数的精度来减小模型的大小和所需的存储空间,如下图所示:

量化的核心思想是以较低的精度存储模型的参数,在上图中:

  • 左侧表格 (FP32): 展示了使用单精度浮点数 (FP32) 存储的模型参数。每个值占用 4 个字节。
  • FP32 to INT8: 表示将参数从 FP32 转换为 8 位整数 (INT8) 的量化过程。
  • 右侧表格 (INT8): 展示了量化后的模型参数,使用 INT8 存储。每个值占用 1 个字节

这里如果以FP32 格式存储,每个值需要 4 字节存储空间,9 个值共需 36 字节。而以INT8 格式存储,每个值只需要 1 字节存储空间,同样的 9 个值只需 9 字节。

这里展示量化如何通过降低数值精度(从 FP32 到 INT8)来显著减少模型的存储空间(从 36 字节到 9 字节)。 虽然精度有所损失,但在很多情况下,这种损失对模型性能的影响是可接受的,并且可以换取更小的模型尺寸和更快的推理速度。

然而量化是会有代价的,那就是它会产生量化误差error,如下图所示:

这里我们将FP32 转换为 INT8 导致了精度损失。 每个误差值是原始 FP32 值和量化后 INT8 值之间的差。例如,第一个值 13.5 被量化成 13,误差为 0.5。最先进的(state-of-the-art)量化方法背后的全部挑战是避免性能下降的前提下尽可能的降低这个误差。

下面我们来介绍一些机器学习中不同的数据表示方式,这里会重点介绍整数和浮点数类型的区别,如下图所示:

这里我们将FP32 转换为 INT8 导致了精度损失。 每个误差值是原始 FP32 值和量化后 INT8 值之间的差。例如,第一个值 13.5 被量化成 13,误差为 0.5。最先进的(state-of-the-art)量化方法背后的全部挑战是避免性能下降的前提下尽可能的降低这个误差。

整数 (Integer, int8):

  • Integer (int8): 表示 8 位整数类型。
  • 绿色方块序列:用 8 个绿色方块直观地表示了 int8 类型,每个方块代表一个比特。其中包含的数字 “1 0 0 0 1 0 0 1” 是一个 int8 数值的二进制表示示例。

浮点数 (Floating Point, FP32, FP16, BF16):

  • 三种常见的浮点数类型:单精度浮点数 (FP32)、半精度浮点数 (FP16) 和 Brain Floating Point (BF16)
  • 彩色条形图:用不同颜色的条形图展示了 32 位浮点数 (FP32) 的组成部分及各自占用的位数:
    • 符号位 (Sign):1 位,用于表示正负。
    • 指数位 (Exponent):8 位,用于表示数值的范围(大小)。
    • 尾数位 (Fraction):23 位,用于表示数值的精度。
    • 总共 32 位。

上面我们介绍了整数 (int8) 和浮点数 (FP32, FP16, BF16)的组成部分。 并重点突出了浮点数的三个组成部分(符号、指数、尾数)及其各自的作用,并以 FP32 为例展示了这些部分是如何构成一个 32 位浮点数的。 这有助于理解不同数据类型在精度和存储空间上的权衡,以及它们在机器学习中的应用。 虽然图片中没有明确指出 FP16 和 BF16 的具体组成,但它们与 FP32 的相似性,只是精度和范围有所不同。

下面我们来介绍一种最简单的量化方法:线性量化 (Linear Quantization)

线性量化的原理是将一个较大范围的浮点数线性映射到一个较小范围的整数。如下图所示:

在上图中:

  • 蓝色线段 (FP32): 代表使用单精度浮点数 (FP32) 表示的数值范围,从 -234.1 到 251.51。
  • 红色线段 (INT8): 代表使用 8 位整数 (INT8) 表示的数值范围,从 -128 到 127。
  • 虚线: 连接 FP32 和 INT8 的值,展示了线性映射的关系。例如,FP32 中的 -234.1 映射到 INT8 中的 -128,FP32 中的 251.51 映射到 INT8 中的 127。

这里我们推荐使用 Hugging Face 的 Quanto 工具将线性量化应用于实际模型。

上图清晰地展示了线性量化的过程:将浮点数范围映射到整数范围。 它还指出了可以使用 Quanto 工具进行实际操作,并提示了量化技术在大语言模型中的重要应用。 通过上图我们可以更容易理解量化是如何工作的,以及为什么它可以用于模型压缩。

4.整数的表示

整数 (Integer)的两种表示方法:无符号整数 (Unsigned Integer)和有符号整数 (Signed Integer),下面我们以 8 位整数为例进行了说明:

无符号整数 (Unsigned Integer):

  • n 位无符号整数范围:这里给出了 n 位无符号整数的取值范围,从 0 到 2 的 n 次方减 1。
  • 范围:以 8 位无符号整数 (torch.uint8) 为例,说明其取值范围是 0 到 255。
  • 绿色方块序列:用 8 个绿色方块直观地表示了 8 位无符号整数,每个方块代表一个字节(byte)。 数值 “1 0 0 0 1 0 0 1” 是一个示例。
  • 计算过程:下方展示了如何将二进制 “1 0 0 0 1 0 0 1” 转换为十进制 137 的过程,每个byte乘以 2 的相应幂次再求和。

有符号整数 (Signed Integer):

  • 表示方法:有符号整数使用补码 (Two's Complement) 表示法。
  • n 位有符号整数的取值范围:这里给出了 n 位有符号整数的取值范围,从 -2 的 (n-1) 次方到 2 的 (n-1) 次方减 1。
  • 8 位有符号整数 (torch.int8) 取整范围:这里以 8 位有符号整数 (torch.int8) 为例,说明其取值范围是 -128 到 127。
  • 红绿方块序列:用一个红色方块和 7 个绿色方块表示 8 位有符号整数,红色方块代表符号位(1 表示负数)。 数值 “1 0 0 0 1 0 0 1” 是一个示例。
  • 计算过程:下方展示了如何将补码表示的二进制 “1 0 0 0 1 0 0 1” 转换为十进制 -119 的过程。最高位(符号位)的权重为负,其余位计算方式与无符号整数相同。

这里我们看到无符号整数只能表示非负数(0和正数),而有符号整数可以表达负数,0和整数,并且有符号数采用的是补码 (Two's Complement) 表示法,在补码中,最高位代表负的 2 的幂次方,其余位则按照标准的二进制转十进制方法计算。

在上图中将二进制 "1 0 0 0 1 0 0 1" 转换为十进制的方法如下:

  1. 识别符号位: 最左边的byte (1) 是符号位。 1 表示这是一个负数。
  2. 剩余字节(byte)位计算: 除了符号位之外的其余byte按照正常的二进制到十进制转换方法计算: 0 * 2⁶ + 0 * 2⁵ + 0 * 2⁴ + 1 * 2³ + 0 * 2² + 0 * 2¹ + 1 * 2⁰ = 0 + 0 + 0 + 8 + 0 + 0 + 1 = 9
  3. 符号位权重: 在 8 位补码中,符号位的权重是 -2⁷ (-128)。
  4. 最终计算: 将符号位的权重和剩余byte计算结果相加: -128 + 9 = -119

因此,二进制 "1 0 0 0 1 0 0 1" 的 8 位补码表示对应的十进制数是 -119。

或许有读者不熟悉补码 (Two's Complement),下面我们就来介绍一下补码:

补码 (Two's Complement) 是一种用于表示有符号整数的二进制编码方式。它之所以被广泛使用,是因为它可以将加法和减法运算统一起来,简化了计算机硬件的设计。

补码的作用:

  • 表示正负数: 补码用最高位(最左边的位)作为符号位,0 表示正数,1 表示负数。
  • 简化运算: 使用补码,加法和减法可以用相同的电路实现,无需额外的减法电路。 这是补码最主要的优势。
  • 唯一表示零: 与原码和反码不同,补码中零只有一个表示形式,避免了歧义。

补码的计算方法:

对于一个 n 位的整数:

  • 正数: 正数的补码与其二进制表示相同。
  • 负数: 负数的补码计算方法如下:
    • 取其绝对值的二进制表示。
    • 将所有byte位取反(0 变 1,1 变 0)。
    • 将结果加 1。

举例说明 (8 位):

  • +5

    • 二进制:00000101
    • 补码:00000101 (与原码相同)

  • -5

    • 绝对值的二进制:00000101
      取反:11111010
      加 1:11111011 (这是 -5 的补码)

补码的运算:

  • 加法: 直接将两个补码相加,忽略最高位的进位。
  • 减法: 将被减数与减数的补码相加,等同于加上减数的相反数。

补码的用途:

  • 计算机硬件: 几乎所有现代计算机都使用补码来表示和运算整数。 这是因为补码简化了 ALU(算术逻辑单元)的设计,可以只用加法器实现加减法运算。
  • 编程语言: 许多编程语言的底层也使用补码来表示整数。
  • 数字信号处理: 在 DSP 中,补码也用于表示和处理数字信号。

补码是一种高效的二进制表示法,它简化了计算机的运算,并且能够清晰地表示正负数和零。 它的广泛应用使得计算机能够更快速、高效地进行整数运算。

下面我们介绍一下在PyTorch 中不同整数数据类型的表示方法,如下图所示:

上门图片中的表格展示了在 PyTorch 中如何使用不同的整数类型。它列出了每种类型的正式名称 (torch.dtype) 和更常用的别名(如果存在),方便开发者在代码中使用。 例如,你可以使用torch.int32或torch.int来表示 32 位有符号整数。 了解这些数据类型及其别名对于编写高效的 PyTorch 代码至关重要,尤其是在处理需要特定整数类型的数据或进行模型量化时。

下面我们来分别介绍一下在PyTorch 中 8 位无符号整数 (torch.uint8) 和有符号整数 (torch.int8) 的表示范围:

在上图中:

  • Unsigned integer: [0, 2ⁿ - 1]: 表明是无符号整数,并给出了 n 位无符号整数的通用取值范围公式,从 0 到 2 的 n 次方减 1。

  • torch.iinfo(torch.uint8): 展示了如何在 PyTorch 中使用 torch.iinfo() 函数获取 torch.uint8 类型的信息。 注意这里标注了 "two 'i's" 并配上了眼睛 👀 表情符号,强调了函数名中有两个 "i",提醒用户不要拼写错误,这是一个很贴心的细节。

  • iinfo(min=0, max=255, dtype=uint8): 这是 torch.iinfo() 函数的输出结果,显示了 torch.uint8 的最小值 (0)、最大值 (255) 和数据类型 (uint8)。

上图展示了 PyTorch 中torch.uint8类型的取值范围,并演示了如何使用torch.iinfo()函数获取数据类型的信息。 强调了 "two 'i's" 的细节,有助于用户避免常见的拼写错误。 这对于理解 PyTorch 中整数类型的表示和使用至关重要,尤其是在图像处理等需要处理像素值(通常在 0 到 255 之间)的情况下。

下面我们来介绍一下在PyTorch 中 8 位有符号整数 (torch.int8) 的表示范围,以及补码表示法:

  • ​​​​​​​[-2ⁿ⁻¹, 2ⁿ⁻¹ - 1]: 这里给出 n 位有符号整数(补码表示)的通用取值范围公式。
  • "torch.int8": 表示这是一个关于 torch.int8 类型的示例。
  • "torch.iinfo(torch.int8)": 展示了如何在 PyTorch 中使用 torch.iinfo() 函数获取 torch.int8 类型的信息。
  • "iinfo(min=-128, max=127, dtype=int8)": torch.iinfo() 函数的输出结果,显示了 torch.int8 的最小值 (-128)、最大值 (127) 和数据类型 (int8)。

这里我们演示了,在PyTorch 中 torch.int8 类型的取值范围,并强调了使用补码表示法。 还演示了如何使用torch.iinfo()函数获取数据类型的信息。 这对于理解 PyTorch 中整数类型的表示和使用至关重要,特别是对于模型量化等需要处理低精度数值的情况。

下面我们来看看如何在 PyTorch 中使用torch.iinfo()函数获取不同有符号整型数据类型的信息,如下图所示:

图中展示了三个使用 torch.iinfo() 函数的例子,分别对应三种不同的整型数据类型:

  • torch.iinfo(torch.int64): 调用 torch.iinfo() 函数,传入 torch.int64 数据类型,这将返回一个 torch.iinfo 对象,其中包含了 torch.int64 类型的各种属性信息,例如最大值、最小值等。

  • torch.iinfo(torch.int32): 调用 torch.iinfo() 函数,传入 torch.int32 数据类型。

  • torch.iinfo(torch.int16): 调用 torch.iinfo() 函数,传入 torch.int16 数据类型。

上图展示了如何使用torch.iinfo()函数获取 PyTorch 中不同整型数据类型的属性信息。 虽然图中没有显示torch.iinfo()函数的输出结果,但它告诉我们如何使用该函数来查询int64、int32和int16的信息,例如它们的取值范围、精度等。 通过这些信息,开发者可以更好地理解和使用 PyTorch 中的整型数据类型。

5.浮点数的表示

下面我们来介绍一下浮点数的三个组成部分及其在不同浮点数格式中的作用,如下图所示:

浮点数的三个组成部分包括:​​​​​​​

  • Sign(符号): 正数或负数(始终为 1 位)。 用于表示数值的正负。
  • Exponent(指数): 影响可表示的数值范围。 指数部分决定了数值的大小范围,类似于科学计数法中的指数。
  • Fraction(尾数): 影响数值的精度。 尾数部分决定了数值的精度,类似于科学计数法中的有效数字。

FP32、BF16、FP16 和 FP8 都是浮点数格式,它们对指数和尾数部分使用了特定数量的位。 这意味着不同格式的浮点数在数值范围和精度上有所不同,这取决于它们分配给指数和尾数的位数。 符号位始终是 1 位。

下面我们来介绍一下 FP32(单精度浮点数)的格式以及它如何表示不同范围的数值。

 

上图中展示了FP32 的三个组成部分以及它们各自占用的位数:

  • ​​​​​​​Sign(符号位): 1 位,红色部分,用于表示正负(0 为正,1 为负)。
  • Exponent(指数位): 8 位,绿色部分,用于表示数值的范围(大小)。
  • Fraction(尾数位): 23 位,蓝色部分,用于表示数值的精度。
  • Total: 总共 32 位,对应“单精度”。

上图数轴和下方的公式解释了 FP32 如何表示不同范围的数值:

  • ​​​​​​​0: 零是一个特殊值,通常表示为所有位都为 0。
  • Subnormal values(非规格化值): 指数位全为 0 (E = 0) 的情况。 这部分数值非常接近于 0,用于表示非常小的数。 其范围大约是 1.4 x 10⁻⁴⁵ 到 1.2 x 10⁻³⁸。 公式为 (-1)ˢ * F * 2⁻¹²⁶,其中:
    • S 是符号位。
    • F 是尾数位表示的小数部分。
  • Normal values(规格化值): 指数位不全为 0 且不全为 1 (E ≠ 0) 的情况。 这是最常用的范围,可以表示大多数的浮点数。 其范围大约是 1.2 x 10⁻³⁸ 到 3.4 x 10³⁸。 公式为 (-1)ˢ * (1 + F) * 2ᴱ⁻¹²⁷,其中:
    • S 是符号位。
    • F 是尾数位表示的小数部分。
    • E 是指数位表示的无符号整数。

数轴上的分段:

数轴上的方括号和数值表示了不同范围的边界:

  • 2⁻¹⁴⁹ : 非规格化值的最小值(接近于 0)。
  • (1 - 2⁻²³)2⁻¹²⁶: 非规格化值的最大值。
  • 2⁻¹²⁶: 规格化值的最小值。
  • (1 + 1 - 2⁻²³)2¹²⁷: 规格化值的最大值(接近于 FP32 能表示的最大值)。​​​​​​​

上图清晰地展示了 FP32 浮点数的格式、不同组成部分的作用,以及如何表示不同范围的数值,包括非常接近于零的非规格化值和更大范围的规格化值。 它还提供了计算 FP32 数值的公式,有助于更深入地理解浮点数的表示方式。

接下来我们再来介绍一下BF16(Brain Floating Point)的格式以及它如何表示不同范围的数值。

上图中展示了BF16 的三个组成部分以及它们各自占用的位数:

  • ​​​​​​​Sign(符号位): 1 位 (红色),表示数值的正负(0 为正,1 为负)。
  • Exponent(指数位): 8 位 (绿色),表示数值的范围(大小)。 与 FP32 相同。
  • Fraction(尾数位): 7 位 (蓝色),表示数值的精度。 比 FP32 的 23 位少。
  • Total: 总共 16 位,因此被称为“半精度”。

数轴和数值范围:

数轴和下方的公式解释了 BF16 如何表示不同范围的数值:

  • ​​​​​​​0: 零是一个特殊值,通常表示为所有位都为 0。
  • Subnormal values(非规格化值): 指数位全为 0 (E = 0)。用于表示非常接近 0 的小数。范围大约是 9.2 x 10⁻⁴¹ 到 1.2 x 10⁻³⁸。 公式:(-1)ˢ * F * 2⁻¹²⁶,其中:
    • S 为符号位。
    • F 为尾数位表示的小数部分 (0 ≤ F < 1)。 注意,BF16 的尾数位只有 7 位,精度比 FP32 低。
  • Normal values(规格化值): 指数位不全为 0 且不全为 1 (E ≠ 0)。这是最常用的范围。范围大约是 1.2 x 10⁻³⁸ 到 3.4 x 10³⁸。 公式:(-1)ˢ * (1 + F) * 2ᴱ⁻¹²⁷,其中:
    • S 为符号位。
    • F 为尾数位表示的小数部分 (0 ≤ F < 1)。
    • E 为指数位表示的无符号整数。

数轴上的分段和边界值:

数轴上的方括号和数值表示了不同范围的边界:

  • ​​​​​​​2⁻¹³³: 非规格化值的最小正值。
  • (1 - 2⁻⁷)2⁻¹²⁶: 非规格化值的最大值,也是最小规格化值。
  • 2⁻¹²⁶: 规格化值的最小正值。
  • (1 + 1 - 2⁻⁷)2¹²⁷: 规格化值的最大值。

与FP32的比较:

  • ​​​​​​​BF16 的指数位宽度与 FP32 相同,因此它们表示的数值范围大致相同。
  • BF16 的尾数位宽度比 FP32 小得多,因此 BF16 的精度比 FP32 低。
  • BF16 在深度学习训练中被广泛使用,因为它在数值范围和精度之间取得了平衡,可以减少内存使用和计算量,同时保持合理的模型精度。

上图清晰地解释了 BF16 浮点数的格式、数值范围、精度以及如何表示不同类型的数值。 通过与 FP32 的比较,可以看出 BF16 牺牲了一定的精度来换取更小的存储空间和更快的计算速度。

接下来,我们来介绍一些FP16(半精度浮点数)的格式、数值范围以及如何表示不同类型的数值(包括非规格化值和规格化值):

上图中列出了 FP16 的三个组成部分及它们占用的位数:

  • ​​​​​​​Sign(符号位): 1 位 (红色),表示数值的正负(0 为正,1 为负)。
  • Exponent(指数位): 5 位 (绿色),表示数值的范围(大小)。
  • Fraction(尾数位): 10 位 (蓝色),表示数值的精度。
  • Total: 总共 16 位。

数轴和数值范围:

数轴和下方的公式解释了 FP16 如何表示不同范围的数值:

  • ​​​​​​​0: 零是一个特殊值,通常表示为所有位都为 0。
  • Subnormal values(非规格化值): 指数位全为 0 (E = 0)。用于表示非常接近 0 的小数。范围大约是 6.0 x 10⁻⁸ 到 6.1 x 10⁻⁵。 公式:(-1)ˢ * F * 2⁻¹⁴,其中:
    • S 为符号位。
    • F 为尾数位表示的小数部分 (0 ≤ F < 1)。
  • Normal values(规格化值): 指数位不全为 0 且不全为 1 (E ≠ 0)。这是最常用的范围。范围大约是 6.1 x 10⁻⁵ 到 6.5 x 10⁴。 公式:(-1)ˢ * (1 + F) * 2ᴱ⁻¹⁵,其中:
    • S 为符号位。
    • F 为尾数位表示的小数部分 (0 ≤ F < 1)。
    • E 为指数位表示的无符号整数。

数轴上的分段和边界值:

数轴上的方括号和数值表示了不同范围的边界:

  • ​​​​​​​2⁻²⁴: 非规格化数的最小正值。
  • (1 - 2⁻¹⁰)2⁻¹⁴: 非规格化数的最大值,也是最小规格化值。
  • 2⁻¹⁴: 规格化数的最小正值。
  • (1 + 1 - 2⁻¹⁰)2¹⁵: 规格化数的最大值。

与FP32的比较:

  • ​​​​​​​FP16 的指数位和尾数位都比 FP32 少,因此 FP16 的数值范围和精度都比 FP32 低。
  • FP16 在深度学习训练中被广泛使用,因为它比 FP32 占用更少的内存和带宽,可以加快训练速度。 但是,使用 FP16 需要注意数值范围和精度 limitations,避免出现下溢或上溢等问题。

总而言之,上图清晰地解释了 FP16 浮点数的格式、不同组成部分的作用,以及如何表示不同范围的数值。 通过与 FP32 的比较,可以看出 FP16 牺牲了数值范围和精度来换取更小的存储空间和更快的计算速度。

三种浮点数数据类型的比较(FP32、FP16 和 BF16)

这里主要比较FP32、FP16 和 BF16的精度和最大值,如下图所示:

上图的表格中有三列:

  • ​​​​​​​Data Type(数据类型): 列出了三种浮点数类型:FP32(单精度)、FP16(半精度)和 BF16(Brain Floating Point)。
  • Precision(精度): 比较了三种数据类型的精度。
  • FP32:精度最高 (best)。
  • FP16:精度次之 (better)。
  • BF16:精度较低,但仍然不错 (good)。
  • maximum(最大值): 比较了三种数据类型可以表示的最大值。
  • FP32:最大值约为 10³⁸。
  • FP16:最大值约为 10⁴。
  • BF16:最大值约为 10³⁸。

上图清晰地展示了 FP32、FP16 和 BF16 之间在精度和数值范围上的差异。FP32 提供最高的精度和最大的数值范围,但需要更多的存储空间。FP16 降低了精度和数值范围,以节省存储空间。BF16 则在数值范围和精度之间取得了平衡,在保持与 FP32 相似数值范围的同时,降低了精度以减少存储空间和计算成本,使其成为深度学习训练中的常用选择。这也说明 BF16 在某些应用场景下的优势。

相关文章:

大语言模型(LLM)量化基础知识(一)

请大家关注我的知乎博客&#xff1a;- 派神 - - 知乎 随着大型语言模型 (LLM) 的参数数量的增长,与其支持硬件&#xff08;加速器内存&#xff09;增长速度之间的差距越来越大&#xff0c;如下图所示&#xff1a; 上图显示&#xff0c;从 2017 年到 2022 年&#xff0c;语言模…...

hadoop面试题

一、单项选择题 1、目前&#xff0c;Hadoop的最高版本是哪个&#xff08; A &#xff09; A、Hadoop3.x B、Hadoop2.x C、Hadoop4.x D、Hadoop1.x 2、大数据的4V特征是指? &#xff08; B &#xff09; A、数据量大(Volume)、类型繁多(Variety)、价值密度低(Va…...

mysql 安装 windows

新版安装 新版本安装 如果出现initializing database无法安装 则用我当前版本传送门 如MySQL 安装时没有developer default 选项 解决方法传送门 如果上述还不行 可以选择full 汉化下载 传送门...

24下软考中级网络工程师考前必背22页

数据中心选址原则 1、地理位置&#xff1a;备选址地点发生自然灾害的概率和频率、环境危害因素以及气候因素 2、电力能源供应&#xff1a;可用性、成本因素 3、通讯基础设施&#xff1a;光纤主干线路及其距数据中心选址的距离、光纤类型、服务运营商的类型及其支持的服务模式…...

Java类和对象(下篇)

今天接着学习类和对象(苦笑)(苦笑)(苦笑) 1. 封装 1.1 封装的概念 面向对象程序三大特性&#xff1a;封装、继承、多态。 而类和对象阶段&#xff0c;主要研究的就是封装特性。 何为封装呢&#xff1f;简单来说就是套壳屏蔽细节。 举例&#xff1a;对于计算机使用者而言&am…...

k8s图形化显示(KRM)

在master节点 kubectl get po -n kube-system 这个命令会列出 kube-system 命名空间中的所有 Pod 的状态和相关信息&#xff0c;比如名称、状态、重启次数等。 systemctl status kubelet #查看kubelet状态 yum install git #下载git命令 git clone https://gitee.com/duk…...

apache poi 实现下拉框联动校验

apache poi 提供了 DataValidation​ 接口 让我们可以轻松实现 Excel 下拉框数据局校验。但是下拉框联动校验是无法直接通过 DataValidation ​实现&#xff0c;所以我们可以通过其他方式间接实现。 ‍ 步骤如下&#xff1a; 创建一个隐藏 sheet private static void create…...

【canal 中间件】canal 实时监听 binlog

文章目录 一、安装 MySQL1.1 启动 mysql 服务器1.2 开启 Binlog 写入功能1.2.1创建 binlog 配置文件1.2.2 修改配置文件权限1.2.3 挂载配置文件1.2.4 检测 binlog 配置是否成功 1.3 创建账户并授权 二、安装 canal2.1 安装 canal-admin(可选)2.1.1 启动 canal-admin 容器2.1.2 …...

JVM垃圾收集算法、对应收集器和选择建议

如果说垃圾收集算法是内存回收的方法论&#xff0c;那么垃圾收集器就是内存回收的具体实现。 到目前为止还没有最好的垃圾收集器出现&#xff0c;也没万能的垃圾收集器。实际使用中&#xff0c;根据具体应用场景选择合适的垃圾收集器。 1、垃圾收集算法 垃圾收集算法可以从高…...

如何在算家云搭建Aatrox-Bert-VITS2(音频生成)

一、模型介绍 ‌ Aatrox - Bert -VITS2 模型是一种基于深度学习的语音合成系统&#xff0c;结合了 BERT 的预训练能力和 VITS2 的微调技术&#xff0c;旨在实现高质量的个性化语音合成。 二、模型搭建流程 1. 创建容器实例 进入算家云的“应用社区”&#xff0c;点击搜索找到…...

ceph灾备之cephfs snapshot mirror和rsync对比

背景 最近要做ceph集群之间的灾备功能&#xff0c;主要讨论文件存储&#xff0c;因为ceph集群容量越来越大&#xff0c;接入的业务也越来越多&#xff0c;一旦出现故障&#xff0c;恢复时间都是小时级(根据经验每年都会出现几次这种事故)&#xff0c;对于核心业务无法接受&…...

【工具分享】Plutocrypt勒索病毒解密工具

前言 Plutocrypt勒索软件首次出现在2021年&#xff0c;作为CryptoJoker勒索软件的变种。该恶意软件通过钓鱼邮件和恶意链接传播&#xff0c;主要针对个人和小型企业用户。Plutocrypt使用了.NET框架开发&#xff0c;并依赖AES-256和RSA-4096的加密算法来加密受害者的文件。与Cr…...

IDEA启动提示Downloading pre-built shared indexes

Download pre-built shared indexes Reduce the indexing time and CPU load with pre-built JDK shared indexes 翻译&#xff1a; 下载预构建的共享索引 使用预构建的JDK共享索引减少索引时间和CPU负载. 使用预构建的JDK共享索引可以显著减少索引构建时间和CPU负载&#xf…...

[HCTF 2018]WarmUp 1--详细解析

打开靶机&#xff0c;进入界面&#xff1a; 信息搜集 当前界面没有任何有用信息。 想到查看页面源代码。右键–查看页面源代码 看到hint&#xff1a;<!--source.php--> 进入/source.php页面&#xff0c;看到页面源代码&#xff1a; <?phphighlight_file(__FILE_…...

软考教材重点内容 信息安全工程师 第1章 网络信息安全概述

第 1 章 网络信息安全概述 1.1.1 网络信息安全相关概念 狭义上的网络信息安全特指网络信息系统的各组成要素符合安全属性的要求&#xff0c;即机密性、完整性、可用性、抗抵赖性、可控性。 广义上的网络信息安全是涉及国家安全、城市安全、经济安全、社会安全、生产安全、人身安…...

TOSHIBA 74VHC00FT COMS汽车、工业企业的选择

74VHC00FT 是一种四路双输入 NAND 门&#xff0c;属于 CMOS 系列数字集成电路。它采用东芝先进的硅栅 C2MOS 技术设计&#xff0c;能够实现类似于双极性肖特基 TTL 逻辑电路的高速运行&#xff0c;同时保持 CMOS 器件的低功耗。这种独特的结合使其非常适合需要高性能和低功耗的…...

【Android】使用productFlavors构建多个变体

项目需求 在一个设备上安装两个一样的程序app 需求解决 我们知道每一个app都有一个包名的&#xff0c;如果一个app在Android设备上安装之后&#xff0c;再安装这个app的话会进行覆盖安装&#xff0c;因为他们两个的包名是一样的&#xff0c;默认是一个app。 但是我们现在需…...

ubuntu 22.04 防火墙 ufw

Ubuntu&#xff08;22.04&#xff09;云主机SSH安全加固 https://blog.csdn.net/qq_44846097/article/details/141098092 ubuntu22.04防火墙策略 https://blog.csdn.net/sunyuhua_keyboard/article/details/139493464 Ubuntu 22.04 防火墙设置和开放端口命令 https://blog.c…...

MySQL压缩版安装详细图解

1.下载 mysql压缩包版本和msi版的安装方法不一样&#xff0c;下面的是压缩包版本的安装详细图解&#xff1a; 总地址下载地址&#xff1a;MySQL :: Download MySQL Community Server MySQL :: Download MySQL Community Server (Archived Versions) 压缩版下载MySQL :: Dow…...

elementui中的新增弹窗在新增数据成功后再新增 发现数据无法清除解决方法

elementui中的新增弹窗在新增数据成功后再新增 发现数据无法清除解决方法 试过网上其他方法&#xff0c;发现表单清空数据还是有问题&#xff0c;索性用下面方法解决: // 给弹框里面添加 v-ifvisible测试无问题&#xff0c;暂时先这样解决&#xff0c;如果有其他方法&#x…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

Vue 模板语句的数据来源

&#x1f9e9; Vue 模板语句的数据来源&#xff1a;全方位解析 Vue 模板&#xff08;<template> 部分&#xff09;中的表达式、指令绑定&#xff08;如 v-bind, v-on&#xff09;和插值&#xff08;{{ }}&#xff09;都在一个特定的作用域内求值。这个作用域由当前 组件…...

数据库正常,但后端收不到数据原因及解决

从代码和日志来看&#xff0c;后端SQL查询确实返回了数据&#xff0c;但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离&#xff0c;并且ai辅助开发的时候&#xff0c;很容易出现前后端变量名不一致情况&#xff0c;还不报错&#xff0c;只是单…...