论文原文链接
论文github链接
论文结构
1. 引言
-
讨论了当前大语言模型的推理需求与挑战,尤其是在消费级GPU上运行模型的难点:
-
大语言模型的内存需求巨大,远超消费级GPU的容量。
-
数据中心部署的方法通常无法满足本地部署的低延迟需求。
-
-
提出PowerInfer,通过利用神经元激活的稀疏性和局部性,减少GPU内存需求,并提升推理效率。
2. 背景与动机
-
介绍了LLM推理的过程和架构,包括自注意力模块和多层感知机模块(MLP)。
-
阐述了激活稀疏性:
-
在推理过程中,仅有少部分神经元对输出结果有显著贡献(称为“热神经元”),其余神经元(称为“冷神经元”)根据输入动态激活。
-
激活稀疏性可以通过统计学方法预测,为加速推理提供可能。
-
-
回顾现有的模型卸载技术(如CPU-GPU混合部署),指出其面临的局部性错配问题。
3. LLM推理中的局部性洞察
-
提出两大洞察:
-
洞察1:激活的幂律分布:少量热神经元占大多数激活频率,可利用其特性优化推理过程。
-
洞察2:在CPU上的快速计算:小批量推理时,直接在CPU上处理部分神经元比数据从CPU传输到GPU更高效。
-
4. PowerInfer框架
-
架构概览:
-
结合GPU和CPU的推理引擎,热神经元加载到GPU中,而冷神经元在CPU上计算。
-
离线部分分析神经元的激活模式,将其分类为“热”或“冷”。
-
在线部分预测每次推理中将被激活的神经元,仅处理必要的计算任务。
-
-
具体设计:
-
利用自适应预测器优化热神经元的存储。
-
引入稀疏神经元操作符,提高CPU和GPU的计算效率。
-
5. 神经元感知推理引擎
-
详细描述预测器的构建及其对推理计算负载的减少。
-
描述GPU-CPU混合执行模式和稀疏操作符的实现,突出其如何绕过非活跃神经元的冗余计算。
6. 神经元分配策略
-
提出了一种基于整数线性规划(ILP)的优化方法:
-
通过离线分析,最大化GPU上加载的神经元对推理效率的贡献。
-
通过分配策略,平衡GPU和CPU之间的计算负载,并减少CPU-GPU数据传输。
-
7. 实现细节
- PowerInfer在现有的llama.cpp开源框架上进行了扩展,添加了4200行C++和CUDA代码,以及400行Python代码,用于离线分析与策略生成。
8. 评估
-
实验环境:
-
评估使用了两种硬件配置:高端(如RTX 4090)和低端(如RTX 2080Ti)PC。
-
模型包括多个主流LLM(如OPT、LLaMA2、Falcon)和不同激活函数的模型。
-
-
性能表现:
-
PowerInfer在消费级GPU上实现了大幅的推理加速,相比于llama.cpp最多可达到11.69倍的速度提升。
-
对比SpecInfer等基线框架,在不同输入输出长度下也表现出明显优势。
-
性能优势随着输出令牌数增加而进一步扩大。
-
9. 结论
- PowerInfer通过利用神经元激活的局部性和稀疏性,在消费级硬件上实现了高效的大语言模型推理,展现出其在实际应用场景中的潜力。
核心部分讲解(4,5,6部分)
4. PowerInfer框架总览
PowerInfer通过结合GPU和CPU的计算能力,并利用神经元的激活稀疏性,显著提升大语言模型(LLM)的推理性能。
4.1 框架架构
PowerInfer由离线和在线两个阶段组成:
- 离线阶段:
-
任务:分析神经元激活的统计特性,制定神经元分配策略。
-
步骤:
-
使用通用数据集,运行离线推理分析工具,记录各层神经元的激活频率。
-
分类神经元为热神经元(高频激活)和冷神经元(低频激活)。
-
构建神经元分配策略,将热神经元分配到GPU,冷神经元分配到CPU。
-
-
输出:分配策略和预测器参数。
- 在线阶段:
-
任务:根据离线生成的策略,在推理时动态加载激活神经元,并高效执行推理。
-
步骤:
-
GPU加载热神经元,CPU处理冷神经元。
-
使用预测器动态预测当前推理中需要激活的神经元,仅计算激活部分。
-
通过CPU-GPU混合计算完成推理。
-
4.2 执行流程
PowerInfer的推理流程可以分为以下几步:
-
离线阶段生成热/冷神经元分配表。
-
推理过程中,输入数据会被送入在线预测器。
-
预测器动态预测哪些神经元会被激活:
-
GPU计算激活的热神经元。
-
CPU计算激活的冷神经元。
- GPU将CPU的计算结果整合并完成推理输出。
5. 神经元感知推理引擎
PowerInfer的核心是高效的推理引擎,包含自适应稀疏预测器、GPU-CPU混合执行模型、稀疏操作符等关键组件。
5.1 自适应稀疏预测器
任务:
- 通过预测当前推理任务中被激活的神经元,减少冗余计算。
公式与实现:
- 预测器的设计:
-
预测器是一个小型的多层感知机(MLP),由输入层、隐藏层和输出层组成:
-
输入层:输入数据向量。
-
隐藏层:可调节大小,用于平衡预测精度和内存占用。
-
输出层:预测哪些神经元会被激活。
-
- 预测器大小的动态调整:
-
输入稀疏性和偏斜性影响预测器大小:
-
层级稀疏性高时,预测任务更简单,可以使用小型预测器。
-
激活分布高度偏斜时(少量神经元频繁激活),更易用小型预测器。
-
- 公式:隐藏层调整:
-
假设层级稀疏性为S(稀疏率),预测器大小由下式确定: P=f(S,K)其中,P为预测器参数量,K表示层激活分布的偏斜性。
-
通过迭代调整隐藏层神经元数量,确保模型精度损失小于0.1%。
5.2 神经元管理
任务:
- 在GPU和CPU之间合理分配神经元,以实现高效推理。
设计与实现:
- 神经元表:
-
两张表分别存储在GPU和CPU内存中,用于记录每个神经元的位置和状态。
-
表的大小非常小,例如OPT-175B模型仅需9MB内存。
- 神经元映射:
- 在进行矩阵-向量乘法时,每个神经元根据神经元表映射到对应的存储位置,确保计算的正确性。
5.3 GPU-CPU混合执行
流程:
- 全局计算图DAG(有向无环图):
-
推理阶段,构建一个DAG图,节点表示计算操作,边表示数据依赖。
-
DAG图存储在CPU内存中,供GPU和CPU的执行器访问。
- 计算任务分配:
-
GPU负责计算热神经元,CPU负责计算冷神经元。
-
任务分配通过检查依赖关系和内存使用情况实现。
- CPU-GPU同步时间公式:
5.4 神经元感知操作符
-
传统稀疏矩阵计算库(如cuSPARSE)效率不高。
-
PowerInfer设计了基于向量操作的神经元感知操作符:
-
GPU操作符:每个线程块独立计算神经元,避免同步开销。
-
CPU操作符:利用硬件指令集(如AVX2),加速向量计算。
-
- 神经元分配策略
通过优化算法将神经元合理分配到GPU和CPU。
6.1 离线分析
任务:
-
记录每个神经元的激活频率,统计热/冷神经元的比例。
-
公式:神经元影响度量: vi=fi 其中,vi是神经元的影响值,fi是离线分析得到的激活频率。
6.2 神经元分配建模
目标:最大化GPU上加载神经元的总影响值。
- 整数线性规划(ILP):
- 将所有约束转化为线性方程,使用ILP求解器确定神经元分配方案。
6.3 批处理策略
- 为减少ILP求解时间,将每层神经元按影响值分组(每组64个),显著降低计算复杂度。