生成式AI时代最火AI芯片峰会下月来袭!9月6-7日,智猩猩发起主办的2024全球AI芯片峰会将在北京盛大举行。峰会设有开幕式、数据中心AI芯片专场、边缘/端侧AI芯片专场、智算集群技术论坛等7大板块。目前,来自AMD、高通、Habana、壁仞科技、摩尔线程、苹芯科技、亿铸科技、凌川科技、云天励飞、中国移动研究院、北极雄芯等40+企业的嘉宾已确认演讲或讨论。扫码报名或购票~
近年来,随着Transformer、MOE架构的提出,使得深度学习模型轻松突破上万亿规模参数,从而导致模型变得越来越大,因此,我们需要一些大模型压缩技术来降低模型部署的成本,并提升模型的推理性能。模型压缩主要分为如下几类:
- 剪枝(Pruning)
- 知识蒸馏(Knowledge Distillation)
- 量化Quantization)
本系列将针对一些常见大模型量化方案(GPTQ、LLM.int8()、SmoothQuant、AWQ等)进行讲述。
-
大模型量化概述
-
量化感知训练:
-
- 大模型量化感知训练技术原理:LLM-QAT
- 大模型量化感知微调技术原理:QLoRA
-
训练后量化:
-
- 大模型量化技术原理:GPTQ、LLM.int8()
- 大模型量化技术原理:SmoothQuant
- 大模型量化技术原理:AWQ、AutoAWQ
- 大模型量化技术原理:SpQR
- 大模型量化技术原理:ZeroQuant系列
- 大模型量化技术原理:FP8
- 大模型量化技术原理:FP6
- 大模型量化技术原理:FP4
-
大模型量化技术原理:总结
本文将讲述FP8量化相关的一些工作。
文章较长,建议先点赞收藏,后续再慢慢观看。另外,我撰写的大模型相关的博客及配套代码均整理放置在Github:llm-action,有需要的朋友自取。
01
FP8 简介
FP8 是 Nvidia、Arm、Intel 联合推出的8位浮点数据格式,用于加速深度学习训练和推理,其发布了论文:FP8 Formats for Deep Learning。目前,在 Nvidia Hopper 和 Ada Lovelace 等 GPU 上提供了支持。
02
补充:浮点表示法
根据 IEEE 754 标准,在计算机中,使用符号位、指数、尾数三部分表示一个浮点数。
- 符号位:表示数值的符号,只占用1bit,0-表示整数,1-表示负数。
- 指数部分:表示数值的指数(阶码数值)部分,决定了数的范围。
- 尾数部分:表示数值的底数部分,决定了数的精度和小数部分的具体值。
image.png
浮点数的表示公式为:
比如,FP32 的表示如下所示
浮点数根据指数位的值分为规格化,非规格化和特殊值(无穷和NAN)。
image.png
对于规格化的值,指数位不全为1或0,其中, , , 也可以表示为:
image.png
对于非规格化的值,指数位全为0;因此 , , , 也可以表示为:
image.png
对于特殊值,当指数位为全为1,同时尾数位全为0时,表示无穷。当指数位为全为1,同时尾数位不全为0时,表示NaN。
image.png
03
FP8 表示形式
通常,在硬件中 FP8 有两种不同的表示形式:E4M3、E5M2,每种表示形式在不同的场景中都有用。根据指数位数表示为 FP8-E[X],有些地方也会对FP8-E2(E2M5)、FP8-E3(E3M4)格式同步进行研究,以理解这些格式的行为。
- E4M3:由1位符号位、4位指数位、3位尾数组成。它可以存储高达 +/-448 和 nan 的值。
- E5M2:由1位符号位、5位指数位、2位尾数组成。它可以存储最多 +/-57344、+/- inf 和 nan 的值。
image.png
E4M3 能表示的精度更高,而 E5M2 能表示的动态范围更大,增加动态范围的代价是存储值的精度较低。
FP8 精度的 E5M2 数据格式的指数部分,与 FP16 的保持一致。这意味着 FP8 精度的 E5M2 数据格式具备与 FP16 相当的动态范围,因此该数据格式常被用在训练的反向传播阶段。而 E4M3 则适合前向传播。
在 H100 的第四代 Tensor Core 中,支持任意的 FP8 格式矩阵的乘法 (E4M3xE4M3, E5M2xE5M2, E4M3xE5M2, E5M2xE4M3),然后会进行累加到 FP32 和 FP16 的数据格式中,同时也支持浮点格式之间的互相转换。
image.png
E5M2 完全遵循上面的 IEEE 754 的浮点数格式,示例如下
image.png
image.png
而 E4M3 不完全遵循 IEEE 754 的数据格式,主要不同在于当指数位全为1时,一样可以用来表示规格化的值(当小数位不为1),当且仅当指数与底数全为1时,其表示NaN,同时,E4M3不能用来表示 Infinites。比如:
- 二进制的 (0 1111 110) 在 FP8 E4M3 格式中表示 2^(15-7) * (1+1/2 + 1/4) = 448
- 二进制的 (1 1111 100) 在 FP8 E4M3 格式中表示 -2^(15-7) * (1+1/2) = -384
- 二进制的 (1 1111 111) 在 FP8 E4M3 格式中表示负无穷大
一些常见的FP8二进制格式如下所示:
image.png
根据表示的方式,可以把浮点数看成 2 的幂 )之间的 个样本的精度;比如,在 E5M2 中,2 和 4 之间会有 4 个样本,4 和 8 之间也会有 4 个样本;在 E4M3 中,2 和 4 之间有 8 个样本。通过这一特性,可以容易得出:
- E5M2量化误差比E4M3更大。
- FP8表示的数值是非均匀的,浮点量化的误差会随着数值变化的增大而增大。
FP8量化误差示意图如下所示:
image.png
FP8与INT8的数值分布示意图如下所示,对FP8来说,越靠近0,分布越稠密,越远离0,分布越稀疏;
image.png
04
INT8 与 FP8 对比
FP8 与 INT8 量化精度
针对不同的数值分布,高通AI研究院的研究人员在FP8 versus INT8 for efficient deep learning inference 中 给出了INT8和FP8量化后的精度对比,纵坐标值越大,精度越好。
- 对于均匀分布,INT8的精度是最好的,FP8-E4和FP8-E5的精度较差。
- 对于正态分布,FP8-E2(具有2个指数位、5个尾数位和1个符号位)的精度是最好的,INT8的精度紧随其后,FP8-E4和FP8-E5的精度较差。
- 而对于具有异常值的t-分布,量化精度普遍较差,其中FP8-E4的精度稍好。
image.png
对于权重与激活量化,Integer or Floating Point? New Outlooks for Low-Bit Quantization on Large Language Models 中统计了LLaMA-65B各层权重的Per Channel量化后的偏差,并对结果进行了排序,结果表明INT8在所有层的权重量化的精度方面要明显好于FP8-E4。
image.png
同时,也统计了 LLaMA-65B各层激活值的 Per Tensor 量化后的偏差,并对结果进行了排序,结果表明FP8-E4在大多数层的激活值量化的精度方面要好于INT8。论文中对该结果进行了解释:激活值是动态的,随着每个输入的不同而变化,因此需要使用校准集来确定量化Scale;校准过程是选择所有Batch的最大值来计算量化Scale,导致非最大值所在的Batch量化后的数值普遍偏小,而FP8-E4对于小值的精度更好。
image.png
因此,INT8和FP8不存在哪一个有绝对优势,可以根据不同的层的实际loss进行选择。相对来说,INT8量化更适合于权重,FP8-E4量化更适合于大多数层的激活值。
FP8 与 INT8 量化性能
以 Nvidia L40(Ada Lovelace) GPU 为例,其硬件参数如下:
image.png
可以发现 FP8 Tensor Core和 INT8 Tensor Core 的计算能力是相同的。该硬件参数在H800、L20和L40S上也是相同的。
同时,Integer or Floating Point? New Outlooks for Low-Bit Quantization on Large Language Models 中针对不同位宽(INT/FP)的运算进行比较,如加法器、乘法器、乘法累加运算单元(multiply-accumulate (MAC) )。对于8位MAC,乘法器为8位,累加器为16位,以防止溢出。
对于在 DNN 中作为矩阵乘法的基本构建块的 MAC 单元,FP 运算通常比 INT 运算需要更多的面积。然而,这种差异随着位宽的减小而缩小。有趣的是,在 8 位时,FP8 和 INT8 MAC 单元的面积要求几乎相同。这一观察结果表明 INT8 和 FP8 表现出相似的硬件成本和推理性能。与H800等GPU的硬件参数一致。
image.png
在深度学习中的累加器的示意图如下所示。权重和激活存储在内存中并移至 MatMul 计算单元。位宽对于传输数据的延迟和能耗都很重要。在计算单元进行矩阵乘法;位宽和格式都对延迟和能耗产生影响。累加器存储中间结果,可以选择其格式/位宽。最后,输出格式也可以选择,其中位宽决定了有多少位被传输并存储回内存中。
image.png
每个步骤(权重、激活、累加器以及写回内存的值的位宽和格式)都需要做出选择。不同的选择导致不同的表现。其效率取决于特定的架构和网络。
FP8 versus INT8 for efficient deep learning inference 中对比了实现不同类型的乘加计算单元所需的硬件。
下面是乘法累加单元中组件的示意图。深蓝色部分代表乘法本身所需的逻辑。灰色区域需要累加,绿色区域对齐/添加乘积到累加器。
左边是带有定点累加器的定点和浮点方案,对于定点累加和浮点输入,需要乘积流水阶段和乘积对齐(移位)。相反,整数输入则不需要。
右边是浮点累加器,浮点累加显著增加了复杂性,但累加器位数却更少。该设计保持累加器的标准化并假设舍入最近偶数。Nvidia 的 Hopper 架构支持 FP16 和 FP32 浮点累加。
image.png
定点累加器对于 INT8 等数字格式来说既精确又高效,而浮点累加器虽然不精确,但对于具有大量指数位的数字格式(例如:FP8-E4)更高效,以允许覆盖更大的动态范围的乘积,而无需大幅增加累加器的大小。由于浮点累加器的不精确性质,求和的顺序很重要并且可能产生不同的结果。此外,总和越大,累加值就越不准确。
下图展示了硬件中实现每种格式和累加器组合所需的 2-input 门的数量,假设面积和功耗与构建设计所需的 2-input 门的数量成正比。从左到右,从 INT8 到 FP8-E5, 每三个一组,第一条代表定点累加器的结果。第二条表示 FP16 累加器的结果,第三条表示 FP32 累加器的结果。可以看到,与定点累加器相比,FP8-E4->16 位需要多 53% 的门,而 FP8-E4->32 位需要多 183% 的门才能在硬件中实现。
image.png
对于 INT8 一直到 FP8-E3,定点精度累加器是最高效的。但对于 FP8-E4,浮点和定点累加器效率几乎持平。而最重要的是,INT8 与 FP8-E4 相比,浮点格式的成本增加了 53%。如果使用 FP32 累加器,情况会明显变得更糟。与 INT8 相比,带有 FP32 累加器的 FP8-E4 格式效率低 183%。
因此,通过针对这两种格式的专用硬件实现,FP8-E4 在计算所需的面积和功耗方面比 INT8 更昂贵。如果模型因计算而成为瓶颈,这也将导致相对性能大幅下降。
FP8 与 INT8 综合对比
- INT8在数值空间是均匀分布的,将浮点数空间的数值按照等分区间映射到一个整数上,很多浮点数数值都会映射到相同的整数数值,从而损失边界特征值。而FP8仍然是浮点数,有更大的动态范围表示和更高的精度表示。
- 混合精度训练时,FP8到FP16/FP32/BF16的转换,更简单直接,而INT8到FP的转化需要需要乘法和加法而导致更大的开销。
- 在CPU上,FP8的速度会比INT8慢很多。
- INT的量化步长是均匀的,总是以一定的步长完成量化,这是一种均匀的量化。而浮点的量化则是非均匀的,随着数值增大,其步长也在逐渐变大。且E5M2的步长变化较E4M3而言更加明显。从另一个角度出发,量化的误差总是与步长正相关的,因此FP8浮点量化相比于INT8而言,对于小数来说会更加精确,但对于大数则更不精确。
05
FP8 量化方案
FP8 量化模拟
来自高通AI研究院的论文 FP8 Quantization: The Power of the Exponent通过对FP8量化格式的深入分析,包括理论基础和实验验证。提出了一种一种在 FP32 硬件中模拟 FP8 量化的新方法,,该方法可加快 FP8 量化模拟速度,同时很容易地在常见的深度学习框架中实现,有助于快速进行PTQ和QAT,并且它暴露了FP8量化器的参数(即尾数/指数位和指数偏置值),允许通过反向传播学习这些参数。
最后得出FP8格式在多种网络模型的 PTQ 中通常优于INT8,5M2E 和 4M3E FP8 格式效果最好,而对于具有更多异常值(例如:Transformer)的神经网络模型,增加指数位数效果最好。同时,还表明在进行量化感知训练时,该格式的许多优点都会消失,因为网络模型学会了在 INT8 量化中也表现良好。
MoFQ 混合格式量化方法
上海交通大学、北京大学和微软亚洲研究院联合发布的论文 Integer or Floating Point? New Outlooks for Low-Bit Quantization on Large Language Models 中对INT和FP量化进行了比较分析,发现不同层的最佳量化格式因张量分布的复杂性和多样性而异,没有一种量化格式在所有情况下都始终优于其他量化格式,从而提出了一种混合格式量化方法(Mixture of Formats Quantization (MoFQ))。该方法逐层(layer-wise)选择最优的量化格式,以最小的精度损失实现 W8A8 量化结果。无论是仅权重还是权重激活量化场景中都取得了良好的效果。
在 8 比特的权重激活量化中,MoFQ 显著优于仅 INT/FP 的方法,实现了接近全精度模型的性能。这表明 MoFQ8 有效地为每一层的分布选择最合适的格式(INT8 或 FP8),最终以最小的精度损失实现 W8A8 量化结果。值得注意的是,与仅 INT/FP 量化相比,MoFQ 不会产生硬件开销,因为位宽保持不变。
image.png
06
FP8 推理流程
训练时为确保梯度计算准确,权重通常维持为高精度(如:BF16 或 FP32),这是由于训练时需更新参数,而在推理时,权重已固定,故可在模型加载或预处理阶段提前将权重转换为 FP8,确保模型加载即为 FP8 格式。
此外,推理阶段应尽量进行操作融合,如将 LayerNorm 与后续数据格式转换操作整合,确保 kernel 输入输出尽可能维持 FP8,从而能够有效提升 GPU 内存吞吐。同样,GeLU (Gaussian Error Linear Unit) 激活函数也要力求融合。
目前少量输出仍会保持为 FP16,原因是 NVIDIA NCCL 仅支持高精度reduce操作,所以现在仍然需采用 FP16 进行 reduce,完成后再转化为 FP8。
推理流程就简化为下图所示。绿线代表 FP8 的输入输出(I/O),红线表示高精度 I/O。图中可见,最前端的 LayerNorm 输出与权重均为 FP8,矩阵输出暂时保持 FP16,与前文描述一致。并且经过测试验证可得,虽然矩阵输出精度对整体性能影响较小,但与输入问题的规模相关;且因其计算密集的特性,对输出形态影响微弱。
在完成 MHA 后,需要将结果转换为 FP8 以进行后续矩阵计算,Reduce 是以 FP16 执行后再转换到 FP8 的。对于 MLP1 和 MLP2,两者逻辑相似,但不同之处在于:MLP1 的输出可保持在 FP8,因为它已经把 GeLU 加 Bias 等操作直接融合到 MLP1 的 kernel。
image.png
07
FP8 在 TensorRT-LLM 中的应用
TensorRT-LLM 是基于 NVIDIA TensorRT 构建,其 FP8 能力也主要是通过 TensorRT 提供。自 TensorRT 9.0 版本起,开始支持 FP8 推理。要在 TensorRT 中启用 FP8 推理,需完成以下几步:
- 设置 FP8 标志:通过调用 config.set_flag (trt.BuilderFlag.FP8) 在 TensorRT 配置中启用 FP8 支持。类似 INT8、BF16、FP16,FP8 也是类似的启用方式。
- 添加 GEMM 缩放因子(scale) :主要针对输入和权重,需在 weight.py (TensorRT-LLM 中的文件)中额外加载这些缩放因子。这是 FP8 推理中不可或缺的步骤。
- 编写 FP8 模型:现阶段需要明确编写需要 FP8 支持的模型。具体做法如下:将原始 FP16 输入量化至 FP8,随后进行反量化;权重同样进行量化与反量化操作。如此编写的模型,TensorRT 会自动将量化与反量化操作尽可能与前一个 kernel 融合,以及将反量化操作与 matmul kernel 融合。最终生成的计算图表现为量化后的 X 与 W 直接进行 FP8 计算,输出也为 FP8 结果。
为了简化 FP8 在 TensorRT-LLM 中的应用,TensorRT-LLM 已对其进行封装,提供了 FP8 linear 函数和 FP8 row linear 函数来实现。直接使用线性层(linear layer),无需重新编写代码,直接调用函数即可。
在 TensorRT-LLM 使用FP8的推理流程如下图所示。首先权重以 FP8 精度存储的,在进行计算前,权重先经历一次反量化。注意,在此之前,权重的量化已在输入前完成了,此处仅需进行反量化操作。这意味着,在进行矩阵内部计算时,实际上是使用反量化后的数据,通常是 FP16 或甚至 FP32 来进行运算的。
矩阵层尽管以 FP8 表示,但累加是采用 FP32 完成,累加后再乘以 scale 的相关参数。最终得到的结果具备较高精度。由于累加器(accumulator)需要采用高精度的数值,因此,要获得最终 FP8 的输出结果,模型还需经过一个量化节点 (quantitation node)。
回顾整个流程,输入经历了量化与反量化操作。其中,量化 kernel 发生在反量化 kernel 之前,而 TensorRT 则会智能地融合这些 kernel,确保计算的高效和准确。
image.png
08
FP8 在 vLLM 中的应用
vLLM 可以在 Nvidia H100 和 AMD MI300x 等 GPU 上使用 FP8 进行权重和激活量化。目前,仅支持 Hopper 和 Ada Lovelace GPU。使用 FP8 进行模型量化可将模型内存需求减少 2 倍,并将吞吐量提高 1.6 倍,同时对准确性的影响最小。
在线动态量化
在 vLLM 中, 使用 BF16/FP16 模型到 FP8 的动态量化,无需任何校准数据。通过在启动推理引擎时指定 --quantization=“fp8” 或者在LLM 构造函数中设置 quantization=“fp8” 来启用该功能。
该量化方法所有的 Linear 模块(最后的 lm_head 除外)的权重都通过 per-tensor 缩放量化为 FP8_E4M3 精度。在每次前向传递期间计算激活的最小值和最大值,以提供动态的 per-tensor 缩放以实现高精度。因此,该方法对延迟的改进有限。目前该方法在量化到 8 比特之前以原始精度加载模型,因此需要足够的内存来加载整个模型。
离线动态量化
接下来使用离线量化方案,离线量化到 FP8,需安装 AutoFP8 库。
该包引入了 AutoFP8ForCausalLM 和 BaseQuantizeConfig 对象来管理模型的压缩方式。
离线动态量化
使用 AutoFP8 将权重提前量化为 FP8(E4M3) 并生成检查点,并让 vLLM 在运行时处理激活的动态缩放(scales)的计算,以获得最大精度。可以使用 activation_scheme=“dynamic” 参数启用此功能。虽然此模式不会为您提供更好的性能,但与在线量化相比,它减少了内存占用。
其输出日志中可以看到模型定义中线性模型被替换为量化线性模块 (FP8DynamicLinear),注意,当前默认情况下会跳过末尾的 lm_head Linear 模块。
最后,直接在 vLLM 中加载量化模型检查点即可使用。
离线静态量化
为了获得最佳的推理性能, 可以使用 AutoFP8 中带有校准数据的静态量化方案,通过启用 activation_scheme=“static” 参数来为权重和激活生成 per-tensor 的静态缩放(scales)。
最后,直接在 vLLM 中加载量化模型检查点即可使用。
KV Cache FP8(E5M2)量化
INT8/INT4 量化方案需要额外的 GPU 内存存储,这降低了预期的 GPU 内存优势。而FP8数据格式保留2~3个尾数位,可以将float/fp16/bflaot16和fp8相互转换。vLLM中的示例如下所示:
KV Cache FP8(E4M3)量化
与 E5M2 相比,E4M3 格式的优点之一是浮点数以更高的精度表示。然而,FP8 E4M3 的数据范围小(可以表示 ±240.0)通常需要在每个量化tensor旁边使用更高精度(通常是 FP32)的缩放因子。目前,仅支持 per-tensor (scalar) 缩放因子。正在开发支持更细粒度的缩放因子(例如:per-channel)。
这些缩放因子可以通过在加载时将可选的量化参数 JSON 传递给 LLM 引擎来指定。如果未指定此 JSON,则缩放因子默认为 1.0。这些缩放因子通常是通过量化工具(例如:AMD quantizer 或 NVIDIA AMMO)运行未量化模型获取。
研究表明,FP8 E4M3 量化通常只会较小程度地降低推理精度。同时,AMD MI300、NVIDIA Hopper 或更高版本支持 fp32、fp16、bf16 等数据精度之间的本机硬件转换。因此,LLM 推理速度大大加快,且精度损失很小。
vLLM中, FP8 E4M3 的 KV Cache 量化 示例如下所示:
关于如何生成 kv_cache_scales.json 参考文档:https://github.com/vllm-project/vllm/blob/main/examples/fp8/README.md
09
FP8在不同推理框架及硬件的性能对比
在 TensorRT-LLM 使用 FP8 性能测试如下表所示。其中,FP16 的 max 值为 75,而 FP8 的 max 值则提升至 85。原因是 FP8 节省了权重部分的内存,但部分 tensor 以及 KV cache 仍保持在 FP16。表格最后一列展示了使用 FP8 KV cache 的情况,此时能够看到其 max 值相比 FP16 的 max 值超出 2 倍。
在性能方面,单纯启用 FP8 会由于 batch size 提升有限,以及 KV cache 的影响,导致性能提升并不显著。然而,一旦将 KV cache 也转换至 FP8,通过减半其内存消耗,模型吞吐量可以相较 FP16 提升约两倍左右,这是一个相当理想的性能提升幅度。
image.png
下面是使用vLLM针对qwen1.5-chat在不同硬件上进行了FP8量化后的实测结果(注:仅供参考具体以实测为准)。
- 数据集:羊驼中文数据集 1k
- 服务器配置:4090/H800/h20
- 框架:vLLM
- 指标:端到端时延、首Token时延、Token间时延
整体来说,FP8静态量化相对于BF16来说,在不同硬件上均有10%~30的性能提升。
10
总结
本文针对FP8进行了基本的介绍,同时从性能和精度方面对比了FP8与INT8,并且介绍了一些目前FP8的量化方案。虽然FP8还不是很成熟,但是目前知名的推理工具都提供了对FP8的支持,文中也介绍了推理框架TensorRT-LLM与vLLM中关于FP8的应用。同时,测试了针对不同硬件FP8相对于BF16的性能对比。
如何学习大模型
现在社会上大模型越来越普及了,已经有很多人都想往这里面扎,但是却找不到适合的方法去学习。
作为一名资深码农,初入大模型时也吃了很多亏,踩了无数坑。现在我想把我的经验和知识分享给你们,帮助你们学习AI大模型,能够解决你们学习中的困难。
我已将重要的AI大模型资料包括市面上AI大模型各大白皮书、AGI大模型系统学习路线、AI大模型视频教程、实战学习,等录播视频免费分享出来,需要的小伙伴可以扫取。
![](https://img-blog.csdnimg.cn/img_convert/78911a42a816eac7b3a1c35d8d7ee1de.png)
一、AGI大模型系统学习路线
很多人学习大模型的时候没有方向,东学一点西学一点,像只无头苍蝇乱撞,我下面分享的这个学习路线希望能够帮助到你们学习AI大模型。
二、AI大模型视频教程
三、AI大模型各大学习书籍
四、AI大模型各大场景实战案例
五、结束语
学习AI大模型是当前科技发展的趋势,它不仅能够为我们提供更多的机会和挑战,还能够让我们更好地理解和应用人工智能技术。通过学习AI大模型,我们可以深入了解深度学习、神经网络等核心概念,并将其应用于自然语言处理、计算机视觉、语音识别等领域。同时,掌握AI大模型还能够为我们的职业发展增添竞争力,成为未来技术领域的领导者。
再者,学习AI大模型也能为我们自己创造更多的价值,提供更多的岗位以及副业创收,让自己的生活更上一层楼。
因此,学习AI大模型是一项有前景且值得投入的时间和精力的重要选择。