激活稀疏革命:无需重新训练即可提升模型性能并加速推理!

激活稀疏革命:无需重新训练即可提升模型性能并加速推理!

稀疏技术实现大语言模型推理百倍加速。探索激活稀疏的魔力:无需重新训练,低成本,高效率,显著提升GPU推理速度!

在之前关于“LLM如何通过稀疏性加速推理”的讨论中,我们探讨了第一部分“[大模型如何进行剪枝](Unveiling LLM-Pruner Techniques: Doubling Inference Speed)”。这次,我们继续深入第二部分“如何使用激活稀疏加速推理”,并在接下来的讨论中,我们将研究第三部分“稀疏编译器对LLM推理的影响”。

我们一直在探索是否存在一种方法,可以满足以下要求:不需要重新训练模型,只需要微调(低模型迁移成本),保持模型性能(效果好),得到现代硬件(GPU/CPU)的高度支持,并显著减少GPU计算和I/O以优化延迟(推理速度快)。

实际上,这样的方法是存在的,而激活稀疏就是其中一种满足所有这些要求的方法。

值得注意的是,在神经网络中使用ReLU激活函数能够诱导激活稀疏性,这已在许多先前的工作中被采用。平均而言,所有层中的这种激活稀疏性会导致权重传输(I/O)在GPU和CPU之间显著节省,影响大约95%的投影层权重的行。这种减少直接转化为计算节省,因为这些行的矩阵乘法运算结果将是零。

此外,与非结构化稀疏(例如非结构化权重稀疏)不同,这种稀疏性由于将更广泛和结构化的块(如行或列)置零,因此对硬件更友好。

同样,参考下图,我们简要说明了激活稀疏性在加速推理方面的有效性。

在激活稀疏的情况下,推理时执行稀疏向量-稠密矩阵乘法,而在训练时则调整为稀疏矩阵-稠密矩阵乘法。

  • 减少计算量:这种半结构化稀疏(不同于权重剪枝的非结构化稀疏)允许跳过某些行,从而减少计算。例如,cusparse等库已经支持相应的操作。
  • 减少IO传输:推理时GPU I/O是瓶颈(例如,从GPU缓存到CPU缓存,或从GPU DRAM到GPU缓存)。这种方法允许跳过不必要的行,从而减少I/O。

激活稀疏的可行性

以下内容主要参考论文[5]的数据,以论证将ReLU激活应用于LLM的可行性。

激活稀疏模型与非激活稀疏模型的比较

通过对三个模型(OPT 6.7B、Llama 7B(使用SiLU激活)和Falcon 7B(使用GELU激活))的FFN(前馈神经网络)进行测量和分析,得出以下三个结论:

a. 比较Llama 7B(使用SiLU激活)、Falcon 7B(使用GELU激活)和OPT 6.7B(使用ReLU激活)后发现,ReLU诱导了超过90%的激活稀疏,而SiLU和GELU诱导的激活稀疏不到10%,这表明ReLU可以诱导稀疏激活。

b. 激活稀疏性导致权重传输(I/O)显著节省,影响下游投影层权重大约95%的行。

c. 激活函数的选择对准确性没有显著影响,因为GELU、SiLU或ReLU处于相同的精度水平。然而,ReLU可以节省32%的计算量(FLOPS)。

降低训练成本

许多现代LLM(如Llama和Falcon)是使用非ReLU激活训练的。从头开始训练并不经济;因此,有必要考虑通过微调来实现ReLU激活。模型通过以下两个阶段进行微调:

  • 第一阶段:保留现有的ReLU激活(针对OPT的情况),或者将上投影层和下投影层之间的激活函数替换为ReLU(针对使用GELU和SiLU的Falcon和Llama模型)。
  • 第二阶段:在归一化层之后插入新的ReLU激活。

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

在FFN层中将非ReLU激活替换为ReLU。对于Falcon和Llama模型,这分别意味着替换GELU和SiLU。需要注意的是,由于OPT模型已经使用ReLU激活,因此无需更改。在30B tokens的RefinedWeb上进行微调后,模型在激活上表现出显著的稀疏性。

第二阶段——插入新的ReLU

在上一阶段,我们替换了非ReLU激活以获得更多稀疏性。这使得下投影层的输入变得稀疏,约占总计算成本的30%。然而,除了下投影之外,Transformer解码层中还有其他矩阵-向量乘法,例如FFN层中的上投影和注意力层中的QKV投影。这些矩阵-向量乘法总共消耗约55%的总计算成本。

在现代Transformer层中,注意力和FFN层的输入都来自归一化层,例如LayerNorm或RMSNorm。这些层可以看作是一种特定形式的MLP,它们不应用任何任意的可学习参数,而是学习缩放输入。因此,我们在归一化层之后应用ReLU以获得稀疏激活,从而实现第二阶段的目标。

测量结果

微调成本:第一阶段和第二阶段分别使用30B和50B tokens完成微调。与Llama的1T tokens训练成本相比,成本仅为约3-5%。

效果:比较Llama和Falcon微调后的推理延迟,模型性能没有明显下降。然而,推理速度有显著提升,超过30%。

总体而言,结果证实,通过微调实现激活稀疏可以减少各个阶段和速率下的推理FLOPS,同时在各种任务中保持可比的性能。相应的稀疏激活模型可在项目页面找到:https://huggingface.co/SparseLLM

如何加速推理

DejaVu的上下文稀疏预测(如参考文献[1]所述)是一种优秀的方法。

如何充分利用结构化稀疏进行加速

上下文稀疏假设预训练模型表现出上下文稀疏性,即对Attention和MLP进行稀疏化计算与完整计算能达到相同的效果。在此前提下,结构化稀疏模型平均有85%的上下文稀疏性,可以使每个特定输入的参数减少七倍,同时保持准确性,从而显著提升推理性能。

如上图所示,基于上下文稀疏性设计了一个异步稀疏预测器,提前预测下一层Attention和MLP的稀疏性。这种方法不仅保证了推理效率,还大大减少了计算和I/O开销。

上下文稀疏存在性的验证

在OPT-175B、66B和30B模型上使用各种下游数据集(如OpenBookQA和Wiki-Text)进行了测试。该方法涉及对模型进行两次前向传播,以识别每个输入示例的上下文稀疏性。第一次传播记录参数子集,特别是那些为输入生成较大输出范数的Attention头和MLP神经元相关的参数。第二次传播仅使用记录的参数子集计算每个输入示例。令人惊讶的是,在所有的上下文学习和语言建模任务中,两次前向传播产生了相似的预测或性能。

观察结果:平均而言,Attention头可以实现高达80%的稀疏性,而MLP神经元可以实现高达95%的稀疏性,总稀疏性约为85%,这可以实现七倍的加速。具体参考数据请参见下图。

工程影响

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

吞吐量影响:由于激活是每个token的函数,有效稀疏性也随机分布在各个token之间。因此,稀疏优化的效果随批次大小的增加呈指数衰减。论文中的消融实验可供参考。

降低推理门槛

整理当前的部分卸载方法和DejaVu方法,如下表所示:

能否将激活稀疏和卸载方法结合起来,设计一个GPU-CPU混合推理引擎:热激活神经元预加载到GPU上以快速访问,而冷激活神经元在CPU上计算,从而显著减少GPU内存需求和CPU-GPU数据传输?

答案自然是“可以”。

一个这样的解决方案是PowerInfer[10],它可以在单个NVIDIA RTX 4090 GPU上运行OPT-175B,实现仅比顶级A100 GPU服务器低18%的令牌生成速度。除了卸载和激活稀疏之外,其他方面如Brainstorm[9]、SparTA[15]和Flash-llm[16]也具有参考价值。

概述:

PowerInfer将频繁激活的神经元的权重预加载到GPU上,而较少激活的神经元的权重则保留在CPU上。

为了减少推理延迟,推理引擎只计算由在线预测器预测为活跃的神经元,跳过大多数不活跃的神经元。此外,预加载策略使PowerInfer能够将大部分推理任务分配给GPU,因为加载到GPU上的热激活神经元构成了激活的绝大多数。对于不在GPU内存中的冷激活神经元,PowerInfer在CPU上执行计算,从而无需将权重传输到GPU。

PowerInfer的架构概览和推理工作流

PowerInfer包含离线和在线组件。由于不同LLM的局部性属性存在差异,离线组件分析LLM的激活稀疏性,区分热神经元和冷神经元。在在线阶段,推理引擎将两种类型的神经元分别加载到GPU和CPU中,并在运行时以低延迟服务LLM请求。在处理用户请求之前,在线引擎根据离线求解器的输出将两种类型的神经元分配给各自的处理单元。在运行时,引擎创建GPU和CPU执行器(在CPU端运行的线程),用于管理并行的CPU-GPU计算。引擎还预测神经元激活并跳过不活跃的神经元。激活的神经元被预加载到GPU内存中进行处理,而CPU则计算其神经元的输出并将结果传输到GPU进行整合。引擎在CPU和GPU上使用稀疏神经元感知算子,专注于矩阵内单个神经元的行/列。

项目链接:https://github.com/SJTU-IPADS/PowerInfer

单层计算优化

一个示例展示了PowerInfer如何计算LLM一个层中的不同神经元

PowerInfer通过基于离线数据对神经元进行分类来协调GPU和CPU处理层中的神经元,将热神经元(例如索引3、5、7)分配给GPU内存,并将其他神经元分配给CPU内存。

接收输入后,预测器识别当前层中哪些神经元可能被激活。例如,它预测神经元3、4和5将被激活。值得注意的是,通过离线统计分析确定为热的神经元可能并不总是与运行时激活行为一致。例如,神经元7虽然被标记为热,但在特定场景下可能处于非激活状态。

随后,CPU和GPU都处理预测出的活跃神经元,而忽略不活跃的神经元。GPU计算神经元3和5,而CPU处理神经元4。一旦神经元4的计算完成,其输出被发送到GPU进行结果整合。

在线推理(神经元感知推理引擎)

  • 自适应稀疏预测器

PowerInfer中的在线推理引擎通过仅处理预测为激活的神经元来减少计算量。DejaVu中也使用了这种方法,倡导训练一组固定大小的MLP预测器。在每个Transformer层中,DejaVu利用两个独立的预测器来预测自注意力和MLP块中神经元的激活。

然而,在资源有限的本地部署环境中设计有效的预测器面临挑战,需要在预测准确性和模型大小之间取得平衡。

PowerInfer为每个Transformer层采用了一种非固定大小预测器的迭代训练方法。该过程首先根据层的稀疏性特征建立基线模型大小。随后,考虑内部激活偏度,迭代调整模型大小以保持准确性。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.0 tokens/s,明显优于llama.cpp,平均加速比为7.23倍,而Falcon-40B最高达到11.69倍。随着输出token数量的增加,PowerInfer的性能优势更加显著,因为生成阶段在整体推理时间中扮演更重要的角色。在此阶段,CPU和GPU上都只有少量神经元被激活,与llama.cpp相比减少了不必要的计算。例如,在OPT-30B的情况下,每个生成的token只有约20%的神经元被激活,且大部分在GPU上处理,这展示了PowerInfer神经元感知推理引擎的优势。

批次大小的影响:

当批次大小小于32时,PowerInfer展现出显著优势,相比llama.cpp平均提升6.08倍。随着批次大小的增加,PowerInfer提供的加速比下降。这种减少归因于模型中联合激活的稀疏性降低。然而,即使批次大小设置为32,PowerInfer仍然保持了相当大的加速比,达到4.38倍。

Falcon-40B在PC-High上的批次推理加速。X轴表示请求批次大小,Y轴表示端到端token生成速度(tokens/s)。每个条柱上方的数字表示与llama.cpp相比的加速比。

负载比较

推理过程中CPU和GPU上的神经元负载分布。黄色块代表llama.cpp,蓝色块代表PowerInfer

比较了PowerInfer和llama.cpp中CPU和GPU之间的神经元负载分布。神经元负载是指每个处理单元执行的激活神经元计算的比例。值得注意的是,在PC-High系统上,PowerInfer显著增加了GPU上神经元负载的份额,从平均20%上升至70%。这表明GPU处理了70%的激活神经元。然而,当模型的内存需求远超GPU容量时,例如在11GB的2080Ti GPU上运行60GB模型,GPU上的神经元负载降至42%。这种下降是由于GPU内存有限,不足以容纳所有热激活神经元,因此部分热神经元需要在CPU上计算。

在涉及较长输入提示和相对较短输出长度的场景中,PowerInfer仅表现出有限的性能提升。在这种情况下,同时处理大量token的阶段成为决定推理速度的关键因素。这导致每个token激活一组独特的神经元,显著降低了激活稀疏性。结果,CPU成为推理过程中的主要瓶颈,需要处理大量冷激活神经元,但计算能力受限。

结论

激活稀疏技术为大语言模型带来了革命性的突破。通过稀疏化神经网络的激活来加速推理过程,同时减轻GPU计算和I/O负载,从而提高了推理速度和性能。这种方法无需重新训练,仅通过微调即可实现激活稀疏,在保持模型性能的同时显著降低成本。激活稀疏技术的应用前景令人兴奋,为深度学习领域带来了更多可能性。我们期待该技术进一步发展和广泛应用。

参考文献

[5]ReLU Strikes Back: Exploiting Activation Sparsity in Large Language Models

[7]Inducing and exploiting activation sparsity for fast inference on deep neural networks

[8]Sparse is enough in scaling transformers

novita.ai 提供Stable Diffusion API以及数百种快速且最便宜的AI图像生成API,支持10,000个模型。🎯 最快生成仅需2秒,按量付费,每张标准图像最低仅需$0.0015,您可以添加自己的模型并避免GPU维护。免费共享开源扩展。

推荐阅读

  1. Quantization Methods for 100X Speedup in Large Language Model Inference
  2. Unveiling LLM-Pruner Techniques: Doubling Inference Speed