Abstract
大型语言模型(LLMs)表现出卓越的性能,但计算和内存需求非常高。量化可以减少内存占用并加速推理。然而,现有的方法无法同时保持准确性和硬件效率。我们提出了SmoothQuant,这是一种无需训练、保持准确性且通用的后训练量化(PTQ)解决方案,使LLMs能够实现8位权重和8位激活(W8A8)的量化。基于权重易于量化而激活不易量化的事实,SmoothQuant通过离线迁移量化难度从激活到权重,从而平滑激活中的异常值,并采用数学等效变换。SmoothQuant使得LLMs中的所有矩阵乘法,包括OPT、BLOOM、GLM、MT-NLG、Llama-1/2、Falcon、Mistral和Mixtral模型,都能实现权重和激活的INT8量化。我们展示了在准确性损失可以忽略不计的情况下,LLMs的速度最多提升1.56倍,内存减少2倍。SmoothQuant使得在单个节点内服务530B参数的LLM成为可能。我们的工作提供了一个一站式解决方案,降低了硬件成本,并使LLMs的应用更加普及。
1 Introduction
2 Preliminaries
量化将高精度的值映射到离散的级别上。我们研究了整数均匀量化(Jacob等,2018)(特别是INT8),以便更好地支持硬件和提高效率。量化过程可以表示为:
X ˉ INT8 = ⌊ X FP16 Δ ⌋ , Δ = max ( ∣ X ∣ ) 2 N − 1 − 1 , \bar{X}_{\text{INT8}} = \left\lfloor \frac{X_{\text{FP16}}}{\Delta} \right\rfloor, \quad \Delta = \frac{\max(|X|)}{2^{N-1} - 1}, XˉINT8=⌊ΔXFP16⌋,Δ=2N−1−1max(∣X∣),
其中 ( X ) 是浮点张量, (\bar{X}) 是量化后的对应值, (\Delta) 是量化步长,(\left\lfloor \cdot \right\rfloor) 是四舍五入函数, (N) 是位数(在我们的情况下为8位)。这里我们假设张量在0处是对称的;对于非对称情况(例如在ReLU之后),可以通过添加一个零点(Jacob等,2018)进行类似的讨论。
这种量化方法使用最大绝对值来计算 (\Delta),以保留激活中的异常值,这些异常值对于准确性很重要(Dettmers等,2022)。我们可以通过一些校准样本的激活来离线计算 (\Delta),这被称为静态量化。我们也可以使用激活的运行时统计数据来获取 (\Delta),这被称为动态量化。如图3所示,量化有不同的粒度级别。每个张量的量化使用整个矩阵的单一步长。我们可以通过为每个标记(per-token量化)或权重的每个输出通道(per-channel量化)使用不同的量化步长来启用更精细的量化粒度。每个通道量化的粗粒度版本是对不同的通道组使用不同的量化步长,这被称为组内量化(Shen等,2020;Yao等,2022)。
对于Transformer中的线性层(Vaswani等,2017),
Y = X ⋅ W , Y ∈ R T × C o , X ∈ R T × C i , W ∈ R C i × C o , Y = X \cdot W, \quad Y \in \mathbb{R}^{T \times C_o}, \quad X \in \mathbb{R}^{T \times C_i}, \quad W \in \mathbb{R}^{C_i \times C_o}, Y=X⋅W,Y∈RT×Co,X∈RT×Ci,W∈RCi×Co,
其中 (T) 是标记的数量,(C_i) 是输入通道,(C_o) 是输出通道(见图3,为简化忽略了批次维度),通过将权重量化为INT8,可以将存储减少一半。然而,为了加速推理,我们需要将权重和激活都量化到INT8(即W8A8),以利用整数内核(例如INT8 GEMM),这些内核被广泛的硬件支持(例如,NVIDIA GPU,Intel CPU,Qualcomm DSP等)。
3 ReviewofQuantizationDifficulty
大型语言模型(LLMs)由于激活中的异常值(Dettmers等,2022;Wei等,2022;Bondarenko等,2021)而非常难以量化。我们首先回顾了激活量化的困难,并寻找异常值中的模式。我们在图4(左)中可视化了一个量化误差较大的线性层的输入激活和权重。我们发现了一些激发我们方法的模式:
-
激活比权重更难量化。权重分布相当均匀和平坦,容易量化。以往的工作表明,用INT8甚至INT4量化LLMs的权重不会降低准确性(Dettmers等,2022;Yao等,2022;Zeng等,2022),这与我们的观察一致。
-
异常值使激活量化困难。激活中异常值的规模比大多数激活值大约高出100倍。在每个张量量化的情况下(方程1),大的异常值主导了最大幅度测量,导致非异常通道的有效量化位数/级别(图2)较低:假设通道i的最大幅度是mi,而整个矩阵的最大值是m,则通道i的有效量化级别是28·mi/m。对于非异常通道,有效量化级别会非常小(2-3),导致大量化误差。
-
**异常值固定在特定通道中。**如果一个通道有异常值,它会在所有标记中持久出现(图4,红色)。给定标记的通道之间的方差很大(一些通道的激活值很大,但大多数很小),但给定通道在不同标记间的幅度方差很小(异常通道始终较大)。由于异常值的持久性和每个通道内部的小方差,如果我们能够对激活进行每通道量化(Bondarenko等,2021)(即对每个通道使用不同的量化步长),量化误差将比每个张量量化小得多,而每个标记量化则帮助不大。在表1中,我们验证了模拟的每通道激活量化成功地将准确性与FP16基线接轨,这与Bondarenko等的发现一致。
然而,每通道激活量化不能很好地映射到硬件加速的GEMM内核,这些内核依赖于高吞吐量执行的一系列操作(例如,Tensor Core MMA),不容忍在该序列中插入具有较低吞吐量的指令(例如,转换或CUDA Core FMA)。在这些内核中,缩放只能沿着矩阵乘法的外部维度执行(即激活的标记维度T,权重的输出通道维度Co,见图3),这可以在矩阵乘法完成后应用:
Y = diag ( Δ FP16 X ) ⋅ ( X ˉ INT8 ⋅ W ˉ INT8 ) ⋅ diag ( Δ FP16 W ) Y = \text{diag}(\Delta_{\text{FP16}}^X) \cdot (\bar{X}_{\text{INT8}} \cdot \bar{W}_{\text{INT8}}) \cdot \text{diag}(\Delta_{\text{FP16}}^W) Y=diag(ΔFP16X)⋅(XˉINT8⋅WˉINT8)⋅diag(ΔFP16W)
因此,以往的工作都使用每个标记激活量化来处理线性层(Dettmers等,2022;Yao等,2022),尽管它们无法解决激活量化的难题(仅比每个张量稍好)。
4 SmoothQuant
由于每通道激活量化不可行,我们提出通过每通道平滑因子 (\mathbf{s} \in \mathbb{R}^{C_i})对输入激活进行“平滑”。为了保持线性层的数学等效性,我们相应地反向缩放权重:
Y = ( X ⋅ diag ( s ) − 1 ) ⋅ ( diag ( s ) ⋅ W ) = X ^ W ^ Y = \left( X \cdot \text{diag}(\mathbf{s})^{-1} \right) \cdot \left( \text{diag}(\mathbf{s}) \cdot W \right) = \hat{X} \hat{W} Y=(X⋅diag(s)−1)⋅(diag(s)⋅W)=X^W^
考虑到输入 (X) 通常来自先前的线性操作(例如,线性层、层归一化等),我们可以轻松地将平滑因子融合到先前层的参数中,并且不会产生额外缩放的内核调用开销。对于某些其他情况,当输入来自残差加法时,我们可以在残差分支上添加一个额外的缩放,类似于Wei等(2022)。
将量化的难度从激活迁移到权重。我们旨在选择一个每通道平滑因子 (\mathbf{s}),使得 (\hat{X} = X \cdot \text{diag}(\mathbf{s})^{-1}) 易于量化。为了减少量化误差,我们应该增加所有通道的有效量化位数。当所有通道具有相同的最大幅度时,总的有效量化位数将最大。因此,一个直接的选择是 (\mathbf{s}_j = \max(|X_j|)),(j = 1, 2, \ldots, C_i),其中 (j) 对应于第 (j) 个输入通道。这个选择确保了在除法之后,所有的激活通道将具有相同的最大值,从而易于量化。注意,激活的范围是动态的;它对于不同的输入样本会有所不同。这里,我们使用预训练数据集的校准样本来估计激活通道的规模(Jacob等,2018)。然而,这个公式将所有量化的难度推给了权重。我们发现,在这种情况下,权重的量化误差会很大(异常通道现在迁移到了权重),导致精度大幅下降(见图10)。另一方面,我们也可以通过选择 (\mathbf{s}_j = 1/\max(|W_j|)) 将所有量化难度从权重推给激活。同样,模型性能由于激活量化误差而表现不佳。因此,我们需要在权重和激活之间分配量化难度,使它们都易于量化。
图5显示了当 (\alpha) 为0.5时SmoothQuant的主要思想。平滑因子 (\mathbf{s}) 是在校准样本上获得的,整个转换在离线进行。在运行时,激活在没有缩放的情况下变得平滑。
这里我们引入一个超参数,迁移强度 (\alpha),以控制我们希望从激活迁移到权重的量化难度,使用以下公式:
s j = ( max ( ∣ X j ∣ ) ) α / ( max ( ∣ W j ∣ ) ) 1 − α \mathbf{s}_j = \left( \max(|X_j|) \right)^\alpha / \left( \max(|W_j|) \right)^{1-\alpha} sj=(max(∣Xj∣))α/(max(∣Wj∣))1−α
我们发现,对于大多数模型,例如所有的OPT(Zhang等,2022)和BLOOM(Scao等,2022)模型,(\alpha = 0.5) 是一个很好平衡的点,可以均匀地分配量化难度,特别是当我们使用相同的量化器对权重和激活进行量化时(例如,每张量,静态量化)。该公式确保了相应通道的权重和激活共享相似的最大值,从而共享相同的量化难度。图5展示了当我们取 (\alpha = 0.5) 时的平滑转换。对于某些激活异常值更显著的模型(例如,GLM-130B(Zeng等,2022)有大约30%的异常值,这对激活量化更困难),我们可以选择更大的 (\alpha) 来将更多的量化难度迁移到权重(如0.75)。
应用SmoothQuant到Transformer块。线性层占据了LLM模型大部分的参数和计算。默认情况下,我们对自注意力和前馈层的输入激活进行尺度平滑,并使用W8A8量化所有线性层。我们还量化了注意力计算中的BMM操作符。我们在图6中设计了一个用于Transformer块的量化流程。
我们使用INT8量化计算密集的操作符(如线性层和注意力层中的BMM)的输入和权重,同时保持激活为FP16用于其他轻量级的元素级操作(如ReLU、Softmax和Layer Norm)。这种设计帮助我们在准确性和推理效率之间取得平衡。
5 Experiments
6 RelatedWork
7 Conclusion
我们提出了SmoothQuant,这是一种准确且高效的后训练量化方法,可以实现对参数量高达530亿的大型语言模型(LLMs)进行无损的8位权重和激活量化。SmoothQuant支持对LLMs中所有通用矩阵乘法(GEMMs)的权重和激活进行量化,这比混合精度激活量化基线显著减少了推理延迟和内存使用。我们将SmoothQuant集成到PyTorch和FasterTransformer中,实现了最高1.56倍的推理加速,并将内存占用减半。SmoothQuant通过提供一个一站式解决方案来减少服务成本,从而使LLMs的应用更加普及。