AI 文摘

LLM百倍推理加速之稀疏篇





作者: 吃果冻不吐果冻皮 来源: 吃果冻不吐果冻皮

【点击】加入大模型技术交流群

原文:https://zhuanlan.zhihu.com/p/677948929

众所周知的是,在GPU上对LLM有着三个核心的影响因素:

(1) GPU计算总量

(2) GPU输入/输出 (IO)

(3) GPU的显存大小。

值得注意的是,对于当今的LLM模型而言,因素 (2) 是影响推理阶段的主要瓶颈。

本文通过最新的论文与工程,重点探讨LLM模型通过剪枝或者稀疏等方法,如何在消费级显卡上,进行十倍以上的推理加速。
首先参考[1]对LLM的推理latency指标进行分析,得到以下的三个结论:

  • 在LLM的prompting和token generation两个阶段,因为受模型参数加载的I/O延迟,token generation阶段所耗费花费的时长要长的多。

  • LLM推理中,Attention和MLP两个模块都是瓶颈,其中MLP占了大约三分之二的I/O Latency。

  • All Ruduce(显卡之间通信)占比较低,优化的主要方向还是transformer本身。

详细数据参考下图:

为了提高推理效率,人们探索了包括量化 、推测解码 、蒸馏,稀疏等技术,本文围绕稀疏,重点进行介绍。

稀疏化基础介绍

模型剪枝(Pruning)也叫模型稀疏化,不同于模型量化对每一个权重参数进行压缩,稀疏化方法是尝试直接“删除”部分权重参数。模型剪枝的原理是通过剔除模型中 “不重要” 的权重,使得模型减少参数量和计算量,同时尽量保证模型的精度不受影响。
论文[17]首先介绍了权重剪枝的方法:将权重低于某个阈值的全部被剪枝,之后进行fine-tuned直到准确率达到预期。该论文的作者在LeNet、AlexNet、VGGNet上分别进行了实验验证了剪枝的作用。另一个针对L1和L2正则化的结论表明,不进行fine-tuned的情况下L1正则化更好,进行fine-tuned则L2正则化更好。另外,前面的网络层对剪枝更加敏感,因此迭代式剪枝方式更好 。同时,作者基于实验,提出了彩票理论。彩票理论:对于一个已经训练好的网络,一定存在它的一个子网络可以在不超过原网络训练轮数的情况下达到和原网络相当的准确率。这个子网络就类似于买彩票。
为了恢复模型精度,通常在剪枝之后需要再训练模型。典型的模型剪枝三段式工作 pipeline 流程分成训练、剪枝、微调 三个步骤,剪枝前后网络连接变化如下图所示。


同时根据深度学习模型中可以被稀疏化的对象,深度神经网络中的稀疏性主要包括权重稀疏,激活稀疏和梯度稀疏。
以上是关于稀疏化的简单介绍,我们接下来把重点转移到‘LLM如何通过稀疏进行推理加速’这个关键命题上。

大模型如何做剪枝

LLM的参数规模往往有着数千亿参数的规模,因此常规的重新训练或迭代修剪模型方法是不可行的。因此,迭代剪枝和彩票假设中的方法[2,3]只能应用于较小规模的模型。
剪枝能够有效地应用于视觉和较小规模的语言模型和任务。然而,最优的剪枝方法需要对模型进行大量的再训练,以恢复删除的元素所造成的准确率损失,所以遇到像 GPT 这样规模的模型时,成本也会极为高昂。虽然也存在一些 one-shot 剪枝方法,无需重新训练即可压缩模型,但弊端在于,它们的计算成本太高,无法应用于具有数十亿个参数的模型。
近期在LLM的剪枝技术上,有所突破,本文依次介绍一下。

SparseGPT

SparseGPT[12]是首个 在LLM场景中的one-shot 精确剪枝技术,可以在 100 - 1000 亿参数的模型规模上有效地运作。SparseGPT 的工作原理是将剪枝问题简化为大规模的稀疏回归实例。它基于新的近似稀疏回归求解器,用于解决分层压缩问题,其效率足以在几个小时内使用单个 GPU 在最大的 GPT 模型(175B 参数)上执行。同时,SparseGPT 准确率足够高,不需要任何微调,剪枝后所损耗的准确率也可以忽略不计。例如,当在最大的公开可用的生成语言模型(OPT-175B 和 BLOOM-176B)上执行时,SparseGPT 在 one-shot 测试中剪枝到 50-60% 的稀疏性,无论是以困惑度还是 zero-shot 测试准确率来衡量,损失准确率都极小。
工程代码,参考项目:https://github.com/IST-DASLab/sparsegptparsegpt
图 1 为实验结果,有以下两个关键点需要说明:首先,如图 1(左)所示,SparseGPT 可以在 OPT 家族的 1750 亿参数变量中剪枝到高达 60% 的均匀分层稀疏性,而几乎不会损失精度。相比之下,唯一已知的在此规模下工作的 one-shot 基线 —— 幅度剪枝(Magnitude Pruning)的准确率仅保持到 10% 的稀疏度,并在超过 30% 的稀疏度时完全崩掉。

其次,如图 2(右)所示,SparseGPT 还可以在更严格但对硬件友好的 2:4 和 4:8 半结构化稀疏模式中准确地施加稀疏性 。尽管相对于密集基线,这些模式往往会失去额外的准确性,特别是对于较小的模型而言,但计算速度可以直接通过这些稀疏模式得出。此外,由技术引起的稀疏性与通过量化获得的额外压缩可以很好地混合在一起。

LLM-Pruner

LLM-Pruner[13],是一种采用结构剪枝,根据梯度信息选择性地去除非关键耦合结构,最大限度地保留LLM的大部分功能的稀疏化方法 。LLM-Pruner通过LoRA,仅需3小时和50K数据,即可有效恢复剪枝模型的性能。
LLM-Pruner 是第一个专为 LLM 结构化修剪而设计的框架,将 LLMPruner 的优点总结为

(i) 与任务无关的压缩,其中压缩的语言模型保留其作为多任务求解器的能力。

(ii) 减少了对原始训练语料库的需求,压缩只需要 5 万个公开可用的样本,大大减少了获取训练数据的预算。

(iii) 快速压缩,压缩过程在三个小时内完成。

(iv)自动结构修剪框架,其中所有依赖结构都被分组,而不需要任何手动设计。

为了评估 LLM-Pruner 的有效性,对三种大型语言模型进行了广泛的实验:LLaMA-7B、Vicuna-7B 和 ChatGLM-6B。使用九个数据集对压缩模型进行评估,以评估修剪模型的生成质量和零样本分类性能。
工程代码,参考项目:https://https://github.com/horseee/LLM-PrunerPruner
如下表所示,使用2.59M样本,通过LLM-Pruner对LLaMA-7B进行20%的剪枝,最终模型性能并未有太大的下降,但推理速度提升18%作用。

Results of LLM-Pruner with 2.59M samples

Wanda

Wanda[14](按权重和激活进行剪枝)是一种新颖、简单而有效的剪枝方法,旨在诱导预训练的 LLM 的稀疏性。受最近对LLM中出现的大幅值特征的观察的启发,Wanda在每个输出的基础上用最小量值乘以相应的输入激活来修剪权重。值得注意的是,Wanda 不需要重新训练或权重更新,并且修剪后的 LLM 可以按原样使用。 通过 LLaMA 和 LLaMA-2 进行Wanda评估,验证了Wanda有着优于既定的幅度剪枝基线,并且与最近涉及密集权重更新的方法相比具有竞争力。
工程代码,参考项目:https://https://github.com/locuslab/wandada

WikiText perplexity of pruned LLaMA and LLaMA-2 models. Wanda performs competitively against prior best method SparseGPT,** without introducing any weight update.**
参考上图,Wanda与SparseGPT,有着接近的模型剪枝性能。

剪枝方法的缺点

  • 硬件支持:由于现代硬件众所周知的困难,很难通过非结构化稀疏性实现clock-time加速[4]。例如,像SparseGPT 这样的零样本剪枝的最新发展发现了 60% 的非结构化稀疏性,但尚未导致任何明显的clock-time加速效果。

  • 落地挑战:例如In-Context Learning中,通过模型稀疏化去满足对应的需求具有挑战性,例如许多工作已经证明了任务相关剪枝的有效性[6],但为每个任务而维护不同模型与LLM自身的定位相冲突,造成一定的落地障碍。

更好的方法-激活稀疏

激活稀疏

有没有一种能够不用模型重训练并仅仅通过微调(模型迁移代价低),同时不降低模型性能(效果好),同时现代硬件(GPU/CPU)能够非常友好支持(容易扩展),同时大幅降低GPU的compute与I/O从而能够优化latency(推理速度快)的方法?
事实上,真的有,激活稀疏,就是一种能能满足以上所有需求的方法。
值得注意的是,在神经网络中使用ReLU激活函数被认为可以诱导稀疏激活,并且已在各种先前的工作中被采用[7]。平均而言,在所有层中,这种激活稀疏性会导致 GPU 和 CPU 之间的权重传输 (I/O) 大幅节省,影响下投影层权重的95%的行。这种减少直接转化为计算节省,对于这些行,矩阵乘法运算的结果将为零。
此外,与非结构化稀疏性(例如非结构化的权重稀疏)不同,这种类型的稀疏性由于将更广泛和结构化的块(例如行或列)归零而对硬件更加友好[8]。
同样,参考下图,简易说明激活稀疏的加速有效性。

在激活稀疏性的情况下,推理时进行稀疏向量密集矩阵乘法,训练期间调整为稀疏矩阵密集矩阵乘法。

  • 减少计算量:这种半结构化稀疏性(与权重剪枝的非结构化稀疏不同),可以跳过某些rows,降低计算。例如,cusparse等库,已经支持对应操作。

  • 减少 IO 传输:在推理过程中,GPU 的I/O是个瓶颈(例如,从 GPU cache 与 CPU cache或者GPU DRAM 与 GPU cache),通过这种方法可以跳过加载不必要的行,从而降低I/O。

激活稀疏的可行性

以下内容,主要参考[5]的数据,对ReLU激活的在LLM上落地的可行性进行论证。
激活稀疏与非激活稀疏模型的对比
通过对OPT 6.7B、Llama 7B(SiLU激活)、Falcon 7B(GELU激活)三个模型的FFN进行测量分析,从而得到以下三个结论:

a,对比Llama 7B(SiLU激活)、Falcon 7B(GELU激活)不到10%的激活稀疏,OPT 6.7B(ReLU激活)超过90%以上的稀疏,证明了ReLU可以诱导稀疏激活。
b,激活稀疏性会导致权重传输 (I/O) 大幅节省,影响下投影层权重的95%的行。
c,激活函数的选择不会明显影响准确性,因为 GELU、 SiLU或ReLU处于相同水平的精度,但ReLU可以节省了32% 的计算量(FLOPS)。

如何降低训练成本?

许多现代 LLM(例如 Llama 和 Falcon)已经使用非ReLU激活进行了训练,从头开始训练并不具有成本效益 ,因此需要考虑通过微调的方法实现ReLU激活。主要通过以下两个阶段对模型进行微调

  • 在第 1 阶段,我们保留现有的ReLU (在 OPT 的情况下)或将向上投影和向下投影之间的激活函数从 GELU (Falcon) 和SiLU (Llama) 替换为ReLU 。

  • 在第 2 阶段,我们在归一化层之后插入新的ReLU 。

第一阶段——非ReLU激活替换

在 FFN 层中用ReLU替换非ReLU激活。对于 Falcon 和 Llama 模型,这意味着分别替换 GELU 和SiLU 。我们注意到,由于 OPT 模型已经使用ReLU激活,因此我们保持不变。对RefinedWeb的 30B个tokens进行微调后,模型在激活方面具有显著的稀疏性。

第二阶段——插入新的ReLU
在上一阶段,我们替换了非ReLU激活以获得更多稀疏性。这导致下投影层的输入稀疏,大约占总计算量的30% 。然而,除了下投影之外,transformer的docode layers中还存在其他矩阵向量乘法 。例如,在FFN 层的向上投影以及注意层中的QKV 投影。总共,上述矩阵向量乘法消耗了总计算量的55%左右。
在现代 Transformer 层中,注意力层和 FFN 层的输入都来自归一化层,例如LayerNorm 或RMSNorm 。这些层可以被视为 MLP 的一种特定形式,其中它们不是应用任意可学习参数,而是学习缩放输入 。因此,我们应用ReLU来获得归一化层后的稀疏激活,来实现第二阶段。
效果总结
微调成本:阶段1和阶段2分别用30B 和 50B 的tokens完成了微调,相对比Llama的1T tokens的训练成本,大约只有3-5%的成本。
效果:对比Llama和Falcon微调后的推理时延。不能难看出,对应的模型性能并没有下降,但推理性能明显有着30%以上的提升。

总体而言,结果证实,通过微调进行激活稀疏可以降低各个阶段和速率的推理 FLOPS,同时保持各种任务的同等性能。 对应的稀疏激活模型,可以参考项目:https://

总体而言,结果证实,通过微调进行激活稀疏可以降低各个阶段和速率的推理 FLOPS,同时保持各种任务的同等性能。对应的稀疏激活模型,可以参考项目:https://huggingface.co/SparseLLM。

如何推理加速

DejaVu给出的上下文稀疏性预测,就是非常好的一个方案(参考论文[1])。
如何充分利用结构化稀疏进行加速
上下文稀疏性,假设预训练的模型存在上下文稀疏性,即对Attention和MLP进行稀疏化计算,能起到完整计算的同样效果。以这个为前提,上下文稀疏度平均为*85%*结构化稀疏模型,可以导致每个特定输入的参数减少7 倍,同时保持准确性,从而大大提升推理性能。

如上图所示,根据上下文稀疏性,设计一个异步的稀疏预测器,提前一步预测下一层Attention和MLP的稀疏,不仅能保证推理效率,同时通过大大降低计算量与I/O。
验证上下文稀疏存在
通过 OPT-175B、66B 和30B 模型和各种下游数据集进行测试,例如OpenBookQA 和 Wiki -Text。方法是通过模型的两次前向传递找到每个输入示例的上下文稀疏性。在第一遍中,记录参数的子集,特别是哪些Attention head和 MLP 神经元为输入产生大的输出规范。在第二遍中,每个输入示例仅使用记录的参数子集进行计算。令人惊讶的是,这两个前向传播在所有上下文学习和语言建模任务上产生相似的预测或性能。
观察结果:平均而言,Attention head可以施加高达 80% 的稀疏度,对 MLP 神经元施加高达 95% 的稀疏度,总稀疏度约为 85%,大约能带来7 倍的加速。具体参考数据,如下图所示。

工程效果
加速效果:因为GPU是面向块的设备:加载单个字节的内存与加载同一地址周围的内存块所需的时间相同。NVIDIA GPU 的块大小通常为128字节,因此进行了内存融合和算子合并都优化 ,在batch_size=1的前提下,与FasterTransformer相比,加速达到2倍。

吞吐影响:因为激活是每个token的函数,因此有效稀疏性也是随机分布在token上。因此,稀疏优化的效果会随着批大小的增加呈指数级衰减。参考论文当中的消融实验,可以进行一定的参考:


值得庆幸的是,激活稀疏占比并不随着batch size而线性增长。这表明来自所有输入示例的参数访问是幂律分布而不是均匀分布,存在一定的高吞吐量的优化空间。
项目地址:https://https://github.com/FMInference/DejaVu

DejaVu降低推理门槛

降低推理门槛的方法
对当前部分offloading的方法和DejaVu方法进行整理,如下表所示:

框架 思路 优点 缺点

FlexGen GPU-centric offloading,以 GPU 为中心的卸载利用 CPU 内存来存储超出 GPU 容量的部分模型参数。 会处理位于 GPU 内存中的参数,并根据需要从 CPU 传输更多参数。只要有足够的 CPU 内存和硬盘存储组合可用,此策略就可以推理不同大小的 LLM。 GPU 和 CPU 之间频繁的数据传输,导致性能延迟,超过 99.5% 的处理时间消耗在将 LLM 权重从 CPU 传输到 GPU 上,这显着影响了整体延迟

DejaVu activation sparsity ,使用激活稀疏性加速 LLM 推理,提出用预测器来预测自注意力和 MLP 块中神经元的激活 选择性地仅处理那些预计将被激活的神经元,同时绕过未激活的神经元,极大降低gpu负载 预测器吃内存,较小的预测器降低了预测精度。一种GPU的加速方案,解决不了GPU显存大小的问题。

llama.cpp hybrid offloading ,CPU 首先处理第一层,然后将中间结果发送到 GPU 进行token生成 最大限度地减少数据传输并缓解缓慢的 PCIe 带宽,将推理延迟减少至 600 毫秒左右。无需任何额外依赖,相比 Python 代码对 PyTorch 等库的要求,C/C++ 直接编译出可执行文件,跳过不同硬件的繁杂准备 每次推理迭代都会访问整个模型,导致分层 GPU-CPU 内存结构的局部性较差。GPU 虽然计算能力强大,但受到内存容量的限制。例如,24GB NVIDIA RTX 4090 GPU 上的 30B 参数模型意味着只有 37% 的模型在 GPU 上,将大部分计算任务转移到 CPU。CPU 具有较高的内存,但计算能力较低,最终处理了 98% 的总计算负载。

能否能把activation sparsity和offloading的方法结合起来,从而设计一种GPU-CPU 混合推理引擎:热激活神经元被预加载到 GPU 上以实现快速访问,而冷激活神经元则在 CPU 上计算,从而显着减少 GPU 内存需求和 CPU-GPU 数据转移?
答案自然是‘YES’。
PowerInfer[10]这是其中的一个方案,能在单卡 NVIDIA RTX 4090 GPU 上运行 OPT-175B,达到只比顶级A100 GPU服务器低18%的tokens生成速度。当然,除了offloading与activation sparsity之外,Brainstorm[9]、SparTA[15]、Flash-llm[16]等方面的内容也具有参考价值。

概述
PowerInfer 会向 GPU 预加载权重对于频繁激活的神经元,而不太活跃的神经元的权重则保留在 CPU 上。
为了减少推理延迟,推理引擎仅计算在线预测器预测为活动的神经元,跳过大多数不活动的神经元。此外,预加载策略使PowerInfer能够将大量推理任务分配给 GPU,因为已加载到 GPU 上的热激活神经元构成了激活的主要部分。对于不在 GPU 内存中的冷激活神经元, PowerInfer在 CPU 上执行计算,从而无需将权重传输到 GPU 。

The architecture overview and inference workflow of PowerInfer

PowerInfer包括离线和在线组件。由于不同 LLM 之间的局部性属性存在差异,离线组件应该分析 LLM 的激活稀疏性,区分热神经元和冷神经元。在线阶段,推理引擎将两种类型的神经元加载到 GPU 和 CPU 中,在运行时以低延迟服务 LLM 请求。在处理用户请求之前,在线引擎根据离线求解器的输出,将两种类型的神经元分配给各自的处理单元。在运行时,引擎创建 GPU 和 CPU 执行器,它们是在 CPU 端运行的线程,以管理并发的 CPU-GPU 计算。(该引擎还预测神经元激活并跳过未激活的神经元。激活的神经元预加载在GPU 内存在那里进行处理,而 CPU 计算其神经元的结果并将其传输到 GPU 进行集成。该引擎在 CPU 和 GPU 上使用稀疏神经元感知运算符,重点关注矩阵内的各个神经元行/列。
项目地址:https://https://github.com/SJTU-IPADS/PowerInfer

owerInfer
单层计算优化

An illustrative example shows how PowerInfer calculates different neurons for one LLM layer

PowerInfer如何协调 GPU 和 CPU 来处理层的神经元?它根据离线数据对神经元进行分类,将热激活的神经元(例如索引 3、5、7)分配给 GPU 内存,将其他神经元分配给 CPU 内存。
收到输入后,预测器会识别当前层中的哪些神经元可能被激活。例如,它预测神经元 3、4 和 5 的激活。值得注意的是,通过离线统计分析识别的热激活神经元可能与运行时激活行为不一致。例如,神经元 7 虽然标记为热激活,但在这种情况下预计将处于非活动状态。
然后,CPU 和 GPU 都会处理预测的活动神经元,忽略不活动的神经元。GPU 计算神经元 3 和 5,而 CPU 处理神经元 4。神经元 4 的计算完成后,其输出将发送到 GPU 进行结果集成。

在线推理(Neuron-aware Inference Engine)

  • 自适应稀疏预测器

PowerInfer中的在线推理引擎通过仅处理那些预测将被激活的神经元来减少计算负载。这种方法也被用在DejaVu 中,它主张训练一组固定大小的 MLP 预测器。在每个 Transformer 层中, DejaVu利用两个独立的预测器来预测自注意力和 MLP 块中神经元的激活。
然而,在资源有限的情况下为本地部署设计有效的预测器具有挑战性,需要平衡预测准确性和模型大小。
PowerInfer为每个 Transformer 层的非固定大小预测器设计了一种迭代训练方法。该过程首先根据层的稀疏度轮廓建立基线模型大小(图9 )。随后,考虑内部激活偏度,迭代调整模型大小以保持准确性。MLP 预测器通常包括输入层、隐藏层和输出层。由于输入层和输出层的尺寸由 Transformer 层的结构决定,因此修改主要针对隐藏层。在迭代调整过程中,隐藏层的尺寸根据观察到的偏度进行修改。对于表现出显着偏度的层,隐藏层大小逐渐减小,直到准确率降至 95% 以下。相反,对于具有最小偏斜度的层,增加维度以提高精度。通过这种方法, PowerInfer有效地将预测器参数限制为 LLM 总参数的 10%。

  • GPU-CPU混合执行

在推理之前, PowerInfer构建一个计算有向无环图 (DAG),其中每个节点代表一个计算 LLM 推理运算符,并将其存储在 CPU 内存中的全局队列中。队列中的每个运算符都标有其必备运算符。在推理过程中,两种类型的执行器(由主机操作系统创建的pthread)管理 CPU 和 GPU 上的计算。它们从全局队列中提取操作符,检查依赖性,并将它们分配给适当的处理单元。GPU 和 CPU 使用它们的神经元感知运算符,GPU 执行器使用cudaLaunchKernel等 API 启动 GPU 运算符,CPU 执行器协调未占用的 CPU 内核进行计算。

实验结论

**性能对比
*各种模型在 FP16 格式的 PC-High 上的加速。 *X 轴表示输出长度。Y 轴表示与 llama.cpp 相比的加速比。每个条上方的数字表示端到端生成速度(tokens/s)。图中第一行配置的输入长度约为 64,第二行配置的输入长度约为 128。

配备 NVIDIA RTX 4090 的 PC-High 上各种模型和输入输出配置的生成速度。平均而言, PowerInfer 生成速度达到 8.32 个tokens/s,最高可达 16.0tokens/s,明显优于 llama.cpp,平均加速为 7.23 倍,而 Falcon-40B 则高达 11.69 倍。随着输出token数量的增加, PowerInfer的性能优势变得更加明显,因为生成阶段在整体推理时间中扮演着更重要的角色。在此阶段,CPU 和 GPU 上都会激活少量神经元,与 llama.cpp 相比,减少了不必要的计算。例如,在 OPT-30B 的情况下,每个生成的token仅激活约 20% 的神经元,其中大部分在 GPU 上处理,这是PowerInfer 的神经元感知推理引擎的优势。
batch_size影响
当批量大小小于 32 时, PowerInfer表现出显着的优势,与 llama.cpp 相比,性能平均提高了 6.08 倍。随着批量大小的增加, PowerInfer提供的加速比会降低。这种减少归因于模型关键激活的稀疏性减少。然而,即使批量大小设置为 32, PowerInfer仍然保持了相当大的加速比,达到了 4.38 倍的加速比。

Batch inference speedup of Falcon-40B on PC-High. The X axis indicates the request batch size, the Y axis represents the end-to-end token generation speed (tokens/s). The number above each bar shows the speedup compared with

负载对比

Neuron load distribution on CPU and GPU during inference. The yellow block refers to llama.cpp, and blue block refers to Power

PowerInfer和 llama.cpp的 CPU 和 GPU 之间的神经元负载分布。神经元负载是指每个处理单元执行的激活神经元计算的比例。值得注意的是,在 PC-High 上, PowerInfer显着增加了 GPU 的神经元负载份额,从平均 20% 增加到 70%。这表明 GPU 处理了 70% 的激活神经元。然而,当模型的内存需求远远超过 GPU 的容量时,例如在一台机器上运行 60GB 的模型11GB 2080Ti GPU,GPU的神经元负载降低至42%。这种下降是由于 GPU 的内存有限,不足以容纳所有热激活的神经元,因此需要 CPU 计算这些神经元的一部分。
在涉及较长输入提示和相对较短输出长度的场景中, PowerInfer仅表现出有限的性能提升。 在这样的在这种情况下,同时处理大量token的提示阶段成为决定推理速度的关键因素。这导致每个token激活一组独特的神经元,从而大大减少激活稀疏性。因此,CPU 成为推理过程中的主要瓶颈,其任务是处理大量冷激活神经元,但受到计算能力的限制。

稀疏编译器

为什么需要编译器

最近的发展表明深度学习计算越来越稀疏,即对具有多个零的张量进行运算。除了稀疏模型权重(通常是静态的且先验已知)之外,还发现更多稀疏模式依赖于输入并且仅在运行时才知道,即动态稀疏性。例如,大型语言模型(例如,GPT 、OPT)表现出各种类型的动态稀疏性。首先,Transformer 模型(和其他类型的模型)在其输入、激活和梯度方面表现出固有的动态稀疏性。激活图中只有极少数元素是非零的(例如,T5-Base 为 3.0%,ViT-B/16 为 6.3%) 。其次,利用动态稀疏性来帮助进一步将 DNN 模型扩展到更大的规模。大多数具有超过一万亿参数的现有模型都采用专家混合(MoE)结构,该结构根据输入稀疏且动态地激活专家。此外,动态稀疏训练在训练过程中动态修剪模型中不太重要的连接,因其卓越的计算效率而受到越来越多的关注。
动态稀疏性(稀疏模式在运行时之前是未知的)对深度学习提出了重大挑战。 由于与预处理相关的大量开销,最先进的稀疏感知深度学习解决方案仅限于预定义的静态稀疏模式。动态稀疏计算的高效执行通常面临用于高效执行的 GPU 友好图块配置与最小化覆盖浪费(张量中的非零值)的稀疏感知图块形状之间的不一致
LLM 稀疏性需要使用稀疏运算符 ,像cuSPARSE或者Sputnik这样的传统库由于其通用设计而不是最佳的,其中包括跟踪每个非零元素并将密集矩阵转换为稀疏格式, 导致要么仅支持稀疏感知内核的静态编译,要么需要将稀疏矩阵动态转换为密集格式,在动态稀疏性的场景下从而导致显着的性能开销。

主流编译器对比

当前主流的稀疏计算编译器主要有cuSPARSE, Sputnik, OpenAI Block Sparse, SparTA 与PIT这几种,参考论文[11],给出以下的加速对比列表数据:
场景:4096 × 4096 × 4096的矩阵乘法
指标:latency(ms)

值得一提的是,PIT 的性能优于最先进的稀疏性优化,分别比 cuSPRARSE、Sputnik、OpenAI Block Sparse、SparTA 实现高达 88.7 倍、5.8 倍、17.5 倍和 5.7 倍的加速。

编译器对LLM推理影响

OPT
实验[11]基于OPT13B 和 30B两个版本模型,在八个 V100-32GB GPU 上使用 Alpaca 数据集和PIT评估。PIT 在 OPT 上应用两种动态稀疏性优化:(1) 消除同一批次中不同长度句子的填充开销;(2)利用 FFN 层中的 ReLU 激活创建的细粒度稀疏性 (高达 99%) 。批量大小设置为 32。PyTorch-S 使用 Triton 作为后端。

End-to-end latency per batch and memory footprints of OPT

PIT 的性能分别优于 PyTorch、PyTorchS 和 DeepSpeed 2.1x ∼ 2.3x、2.5x ∼ 3.0x 和 2.0x ∼ 2.2x。避免动态序列中填充的好处有助于 PIT 相对于基线实现 1.6 倍∼ 1.7 倍的加速。通过进一步利用 FFN 层 ReLU 激活中的动态稀疏性,PIT 将性能进一步提升了 1.3 倍∼ 1.4 倍。与使用块大小为 32x32 的 Triton 块稀疏内核的 PyTorch-S 相比,PIT 使用更小的微块(即 1x32)以及 SRead 和 SWrite 执行高效计算,从而避免计算浪费 。此外,PyTorch-S 还受到稀疏格式转换开销的影响,因此具有最高的延迟。在内存消耗方面,DeepSpeed 的内存使用率最低,因为它将整个编码器层融合到一个算子中,并节省了激活内存。

MOE
实验[11]在SwinMoE 上 PIT 性能测试,SwinMoE 是一个具有编码器和 MoE 结构的大型视觉模型。我们在 float16 精度下测量了 A100 上 PIT 的延迟和内存使用情况。对于视觉转换器,同一批次内的输入图像将被重新缩放到相同的分辨率,以实现一致的序列长度。在我们的实验中,我们比较了不同批量大小和专家数量的 Swin-MoE 的端到端推理延迟和内存占用。MegaBlocks 优于其他基线,因为它同时执行所有专家,有效地利用稀疏内核来避免计算浪费。与 MegaBlocks 相比,PIT 通过在跨内存层次结构的数据移动中支持数据重组,进一步提高了性能。

End-to-end latency and memory footprints of SwinMoE on A100

与 PyTorch、PyTorchS、Tutel、DeepSpeed、MegaBlocks 相比,PIT 分别实现了 1.5x ∼ 6.3x、1.5x ∼ 2.9x、1.1x ∼ 1.8x、1.2x ∼ 1.6x、1.1x ∼ 1.4x 加速。PIT 对 Swin-MoE 的性能提升小于 Switch Transformer,因为 Swin-MoE 的专家数量明显少于 SwitchTransformer。因此,当专家数量从 8 到 32 时,MoE 层仅贡献端到端延迟的 23.6% 到 61.2%。当单独比较 MoE 层的延迟时,PIT 约为 1.2x ∼ 1.7 x 比 Megablocks 快。
整理一下,输出PIT的对比数据列表:

模型 PyTorch PyTorchS DeepSpeed

PIT OPT13B(ReLU激活) 2.1x ∼ 2.3x 2.5x ∼ 3.0x 2.0x ∼ 2.2x

PIT SwinMoE(MOE网络) 1.5x ∼ 6.3x 1.5x ∼ 2.9x 1.2x ∼ 1.6x

硬件

GPU

NVIDIA A100
A100 采用全新的 Ampere 架构。它拥有高达 6912 个 CUDA 核心和 40GB 的高速 HBM2 显存。A100 还支持第二代NVLink技术,实现快速的 GPU 到 GPU 通信,提升大型模型的训练速度。A100 增加了功能强大的新第三代 Tensor Core,同时增加了对 DL 和 HPC 数据类型的全面支持,以及新的稀疏功能,可将吞吐量进一步翻倍。
A100 中的 TF32 Tensor Core 运算提供了一种在 DL 框架和 HPC 中加速 FP32 输入/输出数据的简单路径,其运行速度比 V100 FP32 FMA 运算快 10 倍,或者在稀疏性的情况下快 20 倍。 对于 FP 16/FP 32 混合精度 DL,A100 的性能是 V100 的2.5倍,稀疏性的情况下提高到 5 倍。
在跑 AI 模型时,如果用 PyTorch 框架,相比上一代 V100 芯片,A100 在 BERT 模型的训练上性能提升 6 倍,BERT 推断时性能提升 7 倍。

Intel Max Series GPU
根据论文[18],最近在 NVIDIA V100 GPU 上实现两个稀疏矩阵运算的结果,如中所示并表明我们的性能比 V100 上的参考实现 高出 10 倍。

总结

总结一下稀疏化对LLM推理加速的三个结论:

  • 权重稀疏(50%)、激活稀疏(90%)、MOE稀疏(例如,Mistral 8x7B有着75%的动态稀疏),三者是正交关系(效果可以叠加,但模型性能会受一定影响),结合PIT编译器对稀疏模型的2-3倍的加速效果,对比当前主流的推理框架(TGI/vLLM等),存在理论上5-30倍的加速上限。

  • latency是当前稀疏化的主要方向(稀疏性存在一定有效性,batch_size越大,稀疏效果越差 ),Throughput方向会是一个新的优化方向 ,因为激活稀疏存在一定的幂律分布,工程上具有较大的优化可行性。

*LLM将非ReLU激活转化为ReLU激活的成本较低(3%左右的微调成本,数据质量相对重要),同时DejaVu训练预测器成本更低(训练较快,并且不依赖数据),结合推理速度提升带来的成本下降,是件ROI较高的事情 ,商业上颇为可行。

参考论文

[1]Deja Vu: Contextual Sparsity for Efficient LLMs at Inference Time
[2]Snip: Single-shot network pruning based on connection sensitivity
[3]The lottery ticket hypothesis: Finding sparse, trainable neural networks
[4]The Hardware Lottery
[5]ReLU Strikes Back:Exploiting Activation Sparsity in Large Language Models
[6]Rethinking the Role of Scale for In-Context Learning: An Interpretability-based Case Study at 66 Billion Scale
[7]Inducing and exploiting activation sparsity for fast inference on deep neural networks
[8]Sparse is enough in scaling transformers
[9]Optimizing dynamic neural networks with brainstorm
[10]PowerInfer: Fast Large Language Model Serving with a Consumer-grade GPU
[11]Pit: Optimization of dynamic sparse deep learning models via permutation invariant transformation
[12]SparseGPT: Massive Language Models Can Be Accurately Pruned in One-Shot
[13]LLM-Pruner: On the Structural Pruning of Large Language Models
[14]A Simple and Effective Pruning Approach for Large Language Models
[15]SparTA: Deep-Learning Model Sparsity via Tensor-with-Sparsity-Attribute
[16]Flash-llm: Enabling cost-effective and highlyefficient large generative model inference with unstructured sparsity
[17]Learning both Weights and Connections for Efficient Neural Networks
[18]Performance Optimization of Deep Learning Sparse Matrix Kernels on Intel Max Series GPU
[19]FlightLLM: Efficient Large Language Model Inference with a Complete Mapping Flow on FPGAs

历史文章: 2024年2月大模型文章集锦

更多AI工具,参考Github-AiBard123国内AiBard123

可关注我们的公众号:每天AI新工具