Learning PowerInfer 2.0
00 分钟
2024-6-14
2024-6-21
type
status
date
slug
summary
tags
category
icon
password
URL-TEXT
😀
PowerInfer2.0 提供了在消费级硬件推理的一个强力探索, 使得边缘端LLM推理得到了大幅的增强, 这是一份伟大的工作, 本文针对该论文进行了中文翻译。
 
本文为论文 2406.06282v2 的翻译, 原文在https://arxiv.org/pdf/2406.06282, 官网是: https://powerinfer.ai/v2/。 感谢他们伟大的工作。
 
文中可能有错漏, 请以论文为主

PowerInfer-2:智能手机上的快速大语言模型推理

摘要

本文介绍了PowerInfer-2,一个旨在在智能手机上高速推理大语言模型(LLMs)的框架,特别是对那些模型尺寸超过设备内存容量的情况特别有效。PowerInfer-2的关键理念是利用智能手机中的异构计算、内存和I/O资源,通过将传统的矩阵计算分解为细粒度的神经元簇计算。具体来说,PowerInfer-2具有一个多态神经元引擎,可在LLM推理的各个阶段调整计算策略。此外,它还引入了分段的神经元缓存和细粒度的神经元簇级流水线,有效地最小化并隐藏了I/O操作带来的开销。PowerInfer-2的实现和评估展示了其在两款智能手机上支持多种LLM模型的能力,与最先进的框架相比,推理速度最高提升了29.2倍。值得注意的是,PowerInfer-2是第一个在智能手机上以每秒11.68个tokens生成率运行TurboSparse-Mixtral-47B模型的系统。对于完全适合内存的模型,PowerInfer-2可以在保持推理速度与llama.cpp和MLC-LLM相当的同时,将内存使用量减少约40%。有关更多详细信息,包括演示视频,请访问项目网站:www.powerinfer.ai/v2。

1 引言

大语言模型(LLMs)以其卓越的理解和生成类似人类文本的能力,极大地提升了我们的日常生活并改变了我们的工作环境。目前最先进的LLM,例如GPT-4和Claude-3,通常托管在配备最先进的GPU(如NVIDIA H100)的数据中心中,这些GPU提供了高带宽内存和高达数千teraflops的计算能力。同时,越来越多的趋势表明,将LLM部署在无处不在的智能手机上,将它们转变为智能个人助理,充分利用丰富的个人数据,同时通过避免将私人数据传输到云服务来保持隐私。
然而,尽管智能手机的使用范围广泛,但它们在满足LLM推理的复杂需求方面仍面临挑战,主要是由于其处理能力受限和内存容量有限。
 
为了解决这些问题,研究人员探索了两种有前景的方法来在资源受限的情况下进行LLM推理。考虑到智能手机内存容量有限,一种策略是部署缩小版的LLM。例如,Google的Gemini Nano 3.25B使用不到2GB的内存,这是一种通过降低智能能力来适应内存限制的折衷方案。大模型具有更高智能的现象被称为“规模法则”。
 
另一种方法是降低推理期间LLM权重的计算和存储需求。PowerInfer通过将热激活的神经元分配给GPU,冷神经元分配给CPU,实现了在个人计算机上11倍的推理速度提升。另一种方法,LLM in a Flash,通过使用基于闪存的NVMe存储来缓解内存限制。然而,这些解决方案在智能手机上表现不佳,因为智能手机硬件异构性较强,存储设备带宽较低,且由于只有一个命令队列,不支持并发访问,这使得I/O活动成为移动设备上LLM推理的频繁瓶颈。
 
本文介绍了PowerInfer-2,这是第一个在智能手机上执行高速度LLM推理的框架,能够适应参数多达470亿且超过设备内存容量的模型。PowerInfer-2是PowerInfer项目的后续工作,专为智能手机设计。与其前身一样,PowerInfer-2利用了LLM推理中固有的动态稀疏激活:每次推理迭代仅需要一部分神经元,而不是整个模型权重。此方法在推理过程中显著降低了计算需求,因为PowerInfer-2只需在每次迭代中处理一组选定的神经元。固有的稀疏性还增强了局部性,使PowerInfer-2能够构建一个高效的内存缓存,将最常用的神经元保持在内存中,从而减轻与读取权重相关的I/O开销。
 
与PowerInfer不同,PowerInfer-2在LLM推理中的一个关键挑战在于利用智能手机中高度异构的XPU(如非对称big.LITTLE CPU核心、GPU和NPU)。未能充分利用硬件特性进行推理会导致次优的生成速度。另一个挑战是缓存未命中导致的不可避免的I/O开销。尽管PowerInfer-2利用稀疏激活来减少推理期间所需的权重数量,但仍需要大量的I/O读取操作来检索存储中的权重,这可能会对推理性能产生不利影响。
 
为了解决这些挑战,PowerInfer-2的核心思想是将LLM推理中典型的粗粒度矩阵计算分解为细粒度的神经元簇计算。一个神经元簇由多个神经元组成,其数量由XPU的特性、内存和I/O决定,以充分利用特定硬件组件的能力。具体来说,为了利用智能手机内的异构XPU,PowerInfer-2设计了一个多态神经元引擎,为LLM推理过程的预填充和解码阶段提供不同的计算模式。在预填充阶段,所有用户输入序列的tokens同时处理,PowerInfer-2将所有神经元合并为一个大神经元簇,以最大化NPU在处理大矩阵计算方面的优势。相反,在解码阶段,由于批量大小为1且表现出显著的稀疏性,PowerInfer-2使用小神经元簇来利用CPU核心的灵活性来处理相对较轻的计算任务。
 
神经元簇的粒度进一步使PowerInfer-2能够减轻I/O开销对推理过程的影响。PowerInfer-2引入了一种在神经元粒度上运行的分段缓存。该缓存设计有针对不同LLM权重类型的特定缓存策略,有效地提高了缓存命中率。此外,为了减少I/O操作引起的计算延迟,PowerInfer-2提出了一种细粒度的神经元簇级流水线技术,将I/O操作与神经元簇计算重叠。这种方法显著减少了与I/O延迟相关的等待时间。
 
为了支持各种LLM和配置不同的智能手机,PowerInfer-2在新模型首次在智能手机上进行推理之前执行离线规划。规划器接收用户需求,分析模型和硬件,并生成执行计划。该计划描述了指导在线推理过程的各个组件的配置,包括在不同阶段使用不同XPU的比例、不同缓存区域的大小等。
 
我们通过在PowerInfer的基础上增加12000行代码,扩展了PowerInfer-2,并将其部署在两款智能手机(OnePlus 12和Ace 2)上,这两款手机都配备了异构的高通XPU,并分别拥有24GB和16GB的DRAM内存。PowerInfer-2支持不同模型大小的多种LLM,包括Llama-2(7B、13B)、TurboSparse-Mistral(7B)和TurboSparse-Mixtral(47B)。我们的评估表明,PowerInfer-2比现有最先进的框架LLM in a Flash和llama.cpp平均加速3.94倍(最高4.38倍)和25.4倍(最高29.2倍)。值得注意的是,PowerInfer-2是第一个在移动平台上支持TurboSparse-Mixtral-47B模型的系统,生成速度达到每秒11.68个tokens,比llama.cpp快21.2倍。PowerInfer-2的另一个显著优势是能够在模型推理过程中减少内存使用。例如,对于较小的模型如7B,PowerInfer-2的技术可以在实现与llama.cpp和MLC-LLM相同的推理速度的同时节省近40%的内存使用。

2 背景和动机

2.1 LLM 推理和指标

LLM推理包括两个阶段:预填充阶段和解码阶段。在预填充阶段,用户的提示由LLM在一个迭代中处理,生成第一个token。解码阶段则是LLM以自回归方式逐个生成token。预填充阶段生成的token作为输入用于生成第二个token,第二个token则用于生成第三个,以此类推,直到输出序列完成或达到序列结束(EOS)token。
这两个阶段表现出不同的计算模式,需要优化两个关键指标:预填充阶段的首个token生成时间(TTFT)和解码阶段的token间时间(TBT)。预填充阶段在一个迭代中处理所有提示tokens,计算负担较大;相比之下,解码阶段每次迭代只处理一个token,计算负担较轻。因此,LLM推理系统必须设计特定的计算策略以高效优化这些性能指标。
 

2.2 可预测的稀疏激活

主流LLM,如GPT-4和Llama-2,采用的是仅解码器的Transformer架构。该架构由多个Transformer层组成,每层包含一个注意力块和一个前馈网络(FFN)块。注意力块在序列中建立token之间的关系,而FFN块则解释和处理这些关系。最近的LLM通常采用组查询注意力(Group Query Attention),减少了注意力块中的权重数量,使前馈网络(FFN)块占据了总权重的近80%。FFN块中的激活函数,如ReLU家族函数,会导致大量稀疏激活:大多数神经元(在FFN权重矩阵中表示为行或列)未被激活,因为它们的计算对最终输出影响较小。
幸运的是,在计算每个FFN块之前可以预测FFN中的神经元激活状态,这已被先前的工作所探索。例如,PowerInfer和DejaVu在每个FFN块之前利用小型MLP网络来预测其动态神经元激活状态。通过这些准确的预测器,他们可以显著减少FFN中的神经元计算数量,从而加速推理过程。
 

2.3 智能手机存储分析

智能手机通常缺乏足够的DRAM内存来容纳整个LLM。因此,模型的一部分权重可能存储在外部存储中,如Snapdragon 8gen3中的通用闪存存储(UFS)4.0。在本节中,我们分析了智能手机UFS的性能特征,这些特征指导了PowerInfer-2的I/O设计。
 

2.3.1 读取吞吐量和块大小

首先,我们评估了UFS 4.0的随机和顺序读取吞吐量。一个显著特征是UFS的读取带宽随读取块大小而变化。通常,无论是顺序读取还是随机读取,块越大,读取带宽越大。例如,当块大小设置为512KB时,顺序和随机读取带宽分别达到4 GB/s和3.5 GB/s的最大值。当块大小减小到4KB时,带宽达到最小值,随机读取带宽为450 MB/s。
 

2.3.2 随机读取和数据范围

UFS的随机读取表现出一个有趣的现象,即随机读取范围的大小会影响随机读取的性能。具体来说,较小的随机读取范围会导致较高的带宽。在UFS 4.0中,如图1b所示,如果4KB随机读取范围设置为128MB、256MB和512MB,128MB范围的带宽最高,达到1 GB/s,而512MB范围的带宽最低,低于850 MB/s。值得注意的是,这种现象在其他块大小下并不明显。因此,在128MB范围内,4KB随机读取的带宽超过了8KB和12KB块大小。
notion image

2.3.3 读取吞吐量和CPU核心

另一个观察结果是读取带宽受发出读取命令的CPU影响。CPU核心频率越高,读取带宽越大。如表1所示,使用频率为3.3GHz的大核心进行随机读取时,4KB读取的带宽达到1 GB/s。而使用频率为2.2GHz的小核心进行相同随机读取时,带宽只有约760 MB/s。这种关联是因为发出读取命令的CPU核心需要运行UFS驱动程序,因此更高的频率可以更快地处理与UFS相关的I/O操作,包括中断和队列管理。
 

2.3.4 读取吞吐量和核心数量

最后一个观察结果是,与NVMe不同,移动设备中的UFS存储只有一个命令队列,本质上缺乏内部并发能力。因此,使用多个核心发出I/O命令并不会比使用单个核心获得更高的I/O带宽。如表1所示,使用多个核心进行4KB随机读取甚至会因UFS命令队列中的争用导致I/O性能下降高达40%。
总结:当一些模型权重需要存储在移动设备的存储介质上时,一个高效的LLM系统必须充分考虑存储介质的性能特征,以最大化I/O带宽并最小化与I/O操作相关的性能开销。
notion image

3 PowerInfer-2概述

传统的LLM推理通常依赖于作为推理基本单位的矩阵计算,这种方法在智能手机的异构硬件环境中引入了显著的计算和I/O开销。这种粗粒度计算无法有效利用XPU的灵活计算能力。如果矩阵权重的一部分存储在存储设备上,则必须在开始矩阵计算之前将这些权重加载到内存中,导致大量的I/O等待时间。
本文介绍了PowerInfer-2,这是一个专为智能手机设计的高速度LLM推理框架。其设计实现了三个目标:1)低推理延迟:最小化预填充阶段(TTFT)和解码阶段(TBT)期间的推理延迟;2)低内存占用:在推理过程中减少内存使用,即使模型尺寸超过设备内存限制也能实现低延迟推理;3)灵活性:确保设计可以无缝适应计算、内存和存储容量不同的智能手机。
 

3.1 神经元簇与架构

本文提出了一种称为神经元簇的计算抽象,专为异构计算场景下的LLM推理而设计。PowerInfer-2以神经元簇的粒度执行计算和I/O操作,这些神经元簇可以动态地由多个激活的神经元组成,神经元数量由计算单元的计算能力决定。例如,在解码阶段,当由CPU核心执行计算时,分配给每个CPU核心的神经元簇大小比在预填充阶段由NPU执行计算时处理的簇小。通过使用这种抽象,PowerInfer-2可以充分利用不同计算能力的XPU,有效地隐藏I/O开销。
图2展示了PowerInfer-2的整体架构,其结构分为在线(右侧部分)和离线(左侧部分)程序。在线部分以神经元簇粒度提供推理服务,包括四个协作组件:多态神经元引擎(§4.1)、内存神经元缓存(§4.2)、灵活神经元加载(§4.3)和神经元簇级I/O流水线(§4.4)。
多态神经元引擎为预填充和解码阶段提供完全不同的计算模式。对于预填充阶段,神经元簇包含权重矩阵中的所有神经元,主要依赖NPU,因为它在处理大矩阵乘法方面效率更高。对于解码阶段,它会调用预测器来识别在启动计算之前将激活的神经元。然后引擎将这些激活的神经元合并为一个小神经元簇,并利用CPU核心动态计算神经元簇,从而显著减少运行时的计算需求和内存使用。
在推理计算开始之前,计算引擎从神经元缓存中检索神经元权重,该缓存经过优化以利用LLM推理中观察到的神经元级访问局部性。在缓存未命中时,PowerInfer-2发起I/O命令以从存储中获取未缓存的神经元权重。为了减轻I/O延迟,PowerInfer-2引入了一种新型流水线机制,可以同时处理神经元簇和I/O操作。此外,PowerInfer-2通过自适应地捆绑和加载神经元来最小化I/O开销,这取决于模型的量化。
 
notion image
 
为了自动适应不同的模型或智能手机,离线程序在新的模型首次在智能手机上进行推理之前进行一次。此过程涉及接收三种类型的输入:模型权重、用户输入和硬件规格。它输出一个执行计划,描述在线推理中各个组件的配置并指导在线程序。
具体来说,离线规划器输出计算、内存和I/O的配置。对于计算,规划器确定在不同阶段或层中CPU和NPU的使用比例。对于内存配置,为了在内存使用和推理性能之间实现平衡,规划器允许用户在运行PowerInfer-2之前设置所需的推理速度。根据这个速度设置,PowerInfer-2计算所需的最佳缓存大小。对于I/O配置,规划器触发探查器来测量模型的稀疏性以及热、冷神经元的分布。
 

4 基于神经元的运行时推理

4.1 多态神经元引擎

PowerInfer-2引入了一个多态神经元引擎,可以动态地将神经元组合成神经元簇,以利用LLM推理阶段和异构XPU的不同计算特性。

4.1.1 NPU为中心的预填充

在预填充阶段,所有提示tokens同时处理。尽管这些tokens各自表现出高度稀疏性并激活不同的神经元,但由于这些激活的聚合,总体稀疏性显著降低。因此,PowerInfer-2在预填充阶段不使用预测器计算激活的神经元,而是直接将所有神经元合并为一个大神经元簇。由于NPU在处理大矩阵乘法方面比CPU核心更擅长,PowerInfer-2在预填充阶段主要利用NPU。
尽管CPU核心不参与矩阵计算,PowerInfer-2仍利用它们在预填充阶段为NPU执行必要的准备工作。首先,由于内存有限,PowerInfer-2依赖一个CPU核心将存储在Flash中的权重加载到内存中。其次,由于当前的NPU不支持直接计算量化权重,PowerInfer-2使用CPU核心在NPU计算前对数据进行去量化。
图3-a展示了在Transformer层粒度上CPU和NPU如何协作执行预填充阶段推理。NPU计算需要使用与CPU共享的有限内存。因此,在NPU计算开始之前,CPU应将所需的矩阵权重预加载到共享内存中。在特定的LLM层内,在NPU进行任何矩阵乘法之前,多个CPU中核读取神经元缓存中的量化矩阵权重并提前将这些权重去量化为fp16,最终将结果存储在CPU和NPU之间的共享内存中。同时,PowerInfer-2使用另一个大核异步地将下一层的所有矩阵权重预加载到神经元缓存中。中核的去量化、NPU的计算和大核的I/O操作同时进行,以减少I/O开销。值得注意的是,由于预填充阶段涉及的是稠密矩阵而非稀疏计算,因此可以利用顺序读取通过I/O加载大块数据到内存中,从而最大化UFS的I/O带宽。

4.1.2 CPU为中心的解码

与预填充阶段不同,解码阶段每次迭代集中处理一个token,表现出显著的稀疏性,因为权重矩阵中只有一小部分神经元(约10%)被激活并参与计算。因此,在从预填充阶段过渡到解码阶段时,多态神经元引擎将权重矩阵计算划分为由预测器识别的激活神经元组成的小神经元簇。当批量大小为1时,CPU核心上的矩阵-向量计算延迟低于NPU。此外,由于稀疏性导致的激活神经元数量减少,在XPU中,CPU核心最适合这些较轻的稀疏计算。因此,PowerInfer-2在解码阶段只使用CPU核心进行神经元簇计算。
具体来说,PowerInfer-2利用CPU核心在解码阶段计算注意力块和FFN块。尽管注意力块不表现出稀疏性,但当输入只是一个向量时,CPU核心仍提供更低的计算延迟。对于FFN块,PowerInfer-2首先将FFN块的输入向量传递给预测器,预测哪些神经元在FFN的权重矩阵中需要被激活并将其合并为一个神经元簇。每个CPU核心负责一个簇并计算该簇内的激活神经元与输入向量的乘积。
图3-b展示了由不同CPU核心执行的解码阶段推理。CPU核心首先从神经元缓存中读取注意力块的权重并与输入向量计算。然后运行预测器确定后续权重矩阵中神经元的激活状态。在第三步中,CPU核心将激活的神经元划分为几个簇,每个核心负责计算簇内的激活神经元与输入向量的乘积,最终在屏障处聚合结果。如果这些神经元在神经元缓存中,CPU核心将与输入向量计算它们。如果发生缓存未命中,即神经元不在神经元缓存中,一个在CPU核心上运行的I/O线程将异步加载神经元到缓存中,最终通知计算线程完成计算。

4.2 内存神经元缓存

有效的缓存设计可以防止昂贵的存储I/O活动,从而优化端到端推理性能。缓存系统的有效性取决于推理过程中是否存在局部性。然而,传统的LLM推理需要遍历所有权重以生成每个token,表现出没有局部性,使任何缓存设计都无效。
LLM in a Flash提出利用稀疏激活选择性加载推理过程中的权重。它还将共同激活的神经元捆绑在一起,从Flash加载,以减少I/O操作。然而,这种方法忽略了神经元激活的偏斜分布,其中一些热点神经元更频繁地激活并高度连接到大多数其他神经元。这为设计有效的缓存策略带来了挑战。首先,这些常用神经元驻留在不同的神经元束中,从Flash中重复加载,浪费了I/O带宽。其次,我们发现移除这些热点神经元会将剩余神经元之间的共同激活概率降低到20%以下,使捆绑机制在减少I/O操作方面无效。
为了解决这个问题,PowerInfer-2引入了一种针对LLM中不同数据类型的分段神经元缓存设计。它将缓存划分为多个区域,每个区域具有特定的预取和逐出策略。注意力块权重较小且激活稀疏较少,在运行时预加载并保留。
相比之下,FFN块容易频繁激活热点神经元,使用基于最近最少使用(LRU)的动态逐出策略管理这些神经元。这种方法确保热点神经元更有可能留在缓存中,而冷神经元则经常被逐出并根据需求从Flash加载。重要的是,逐出过程不涉及写入存储,而只是从内存中丢弃权重。
PowerInfer-2利用经典的双队列方法实现其LRU神经元缓存,以神经元粒度管理LLM权重。系统维护两个双向链表队列,标记为活跃队列和非活跃队列,队列内神经元的顺序由最近访问的时间决定,最近访问的神经元位于队列的头部。
在运行时,所有神经元最初加入非活跃队列。在再次访问时,它们被提升到活跃队列的前面。在后续访问中,已经在活跃队列中的神经元将移动到队列的头部。为了管理缓存容量,当活跃队列占用缓存空间的90%时,活跃队列尾部的神经元将移动到非活跃队列,直到活跃队列的占用率下降到90%以下。如果缓存达到容量,非活跃队列尾部的神经元将被丢弃,以腾出新条目的空间。

4.3 灵活神经元加载

拥有有效存储活跃神经元的神经元缓存后,推理过程仍不可避免地会发生未缓存神经元的I/O操作。为优化I/O读取吞吐量并最小化I/O操作,PowerInfer-2还将相关的神经元捆绑在一起。尽管移除热点神经元后单个FFN权重矩阵内的共同激活变得不频繁,不同矩阵中对应位置的神经元经常一起激活。例如,第i个神经元在Gate、Up和Down矩阵中的共同激活概率高达80%。因此,PowerInfer-2选择基于神经元粒度而非矩阵结构存储神经元
权重,将Gate、Up和Down矩阵中第i个神经元的权重连接成一个条目。
PowerInfer-2进一步引入了针对不同模型的不同I/O加载策略,考虑它们的量化方法和UFS I/O的固有特性。对于未量化的模型,由于每个神经元占用的存储空间较大,PowerInfer-2使用较大粒度的随机读取以提高I/O带宽。例如,Llama-7B-FP16中的每个神经元占用8KB,Gate、Up和Down矩阵中的神经元组合大小达到24KB。PowerInfer-2通过单次随机I/O读取有效地将整个24KB激活束传输到内存中。
对于4位量化的模型,捆绑大小设置为8KB。以Llama-7B模型为例,其中每个神经元量化为4位精度,占用2.5KB(2KB用于量化的int4值,0.5KB用于量化组的FP16尺度),捆绑后的总大小为7.5KB。为了与存储介质的最小读取粒度4KB对齐,PowerInfer-2补充了额外的0.5KB,将总大小四舍五入为8KB。然而,PowerInfer-2并不通过单次I/O操作加载这些8KB捆绑,而是选择4KB粒度。这种选择基于我们在第2.3节中的分析,表明两次4KB随机读取的带宽超过一次8KB读取,从而优化了I/O读取过程。
此外,考虑到这些捆绑内神经元的共同激活概率为80%,仍有近20%的概率这些捆绑神经元未共同激活。为减少这种可能的带宽浪费,对于使用4位量化的模型,PowerInfer-2延迟了第二次4KB读取,直到获得Gate神经元乘积的结果。具体来说,PowerInfer-2使用预测器确定Gate矩阵内神经元的激活情况,基于此信息启动捆绑的第一部分加载。随后,如果激活函数处理后的Gate神经元输出非零,PowerInfer-2继续加载捆绑的第二部分,从而最小化不必要的I/O操作。
 
notion image

4.4 神经元簇级流水线

PowerInfer-2旨在通过重叠计算与I/O活动来隐藏I/O开销。一个简单的方法是矩阵级重叠,在检索矩阵神经元的I/O命令发出时,同时处理内存中的神经元。一旦从存储中加载神经元,它们立即被处理。然而,这种矩阵级重叠方法需要系统等待完成矩阵内所有神经元的计算,包括从存储中提取的神经元,然后才能继续下一个操作。如图4-a所示,假设一个矩阵包含8个神经元簇,其中4个在内存中,其余4个在存储中。一部分I/O操作可以隐藏在缓存神经元计算后面。但由于I/O时间较长,CPU核心仍需等待I/O完成。
为消除I/O操作的等待时间,PowerInfer-2引入了一种神经元簇级流水线机制。这种机制的核心思想是:以神经元簇为粒度,可以在多个矩阵的神经元簇计算中重叠I/O操作。具体来说,PowerInfer-2打破了矩阵计算之间的壁垒,一旦一个神经元簇完成计算,立即开始计算内存中下一个矩阵的神经元簇。这种机制有效减少了等待泡泡,如图4-b所示。
PowerInfer-2将神经元簇的执行过程分为5个顺序阶段:通过预测器确定Gate、Up和Down矩阵的行/列是否激活(Pred)、从存储读取Gate矩阵的权重(GIO)、计算Gate矩阵行与输入向量的乘积(GC)、从存储读取Up和Down矩阵的行/列(UDIO)、分别计算Up和Down矩阵的行/列与输入向量的乘积(UDC)。PowerInfer-2创建多个计算线程和一个I/O线程分别处理这些阶段的计算和I/O操作。具体数量和线程执行的核心由离线规划器确定。
图5展示了神经元簇级流水线的工作流程。在每个FFN块开始时,所有神经元最初处于Pred阶段,并插入计算队列。计算线程处理这些神经元,仅将激活的神经元推进到后续阶段。这些激活神经元随后合并为神经元簇。如果神经元簇的Gate权重在内存中,该神经元簇进入GC阶段并返回计算队列。如果不在内存中,它进入GIO阶段并移动到I/O队列。同时,计算线程继续处理队列中的下一个神经元簇。并行地,I/O线程从I/O队列中取出神经元,根据需要执行I/O任务。UDIO和UDC的执行与GC和GIO类似。
 
notion image

5 执行计划生成

今天的智能手机配备了多种硬件规格,如不同的CPU能力、I/O吞吐量和DRAM大小。用户在这些设备上部署LLM也有不同的目标。有些可能优先考虑生成速度与内存使用的平衡,而另一些则希望最大化硬件利用率以提高速度。此外,模型本身在权重数量、结构和稀疏性水平方面也有所不同。为了管理这种复杂性,PowerInfer-2包含一个离线规划器,专门设计来制定执行计划,以最佳地满足这些不同的需求。

5.1 执行计划

表2中所有标记为Var的符号代表执行计划的输出,描述了运行时推理组件的配置。ccompute表示分配用于计算的CPU核心集合,而cio指定用于I/O操作的CPU核心。变量n表示所选CPU核心的总数,包括计算和I/O核心。内存限制m设置了运行时神经元缓存的大小。最后,规划器输出执行计划的估计生成速度s。

5.2 输入参数

表2还列出了三类输入参数:
  • 硬件:来自硬件探查的参数,如CPU FLOPS、I/O吞吐量和内存带宽。
  • 用户:用户指定的参数,如CPU约束、内存限制和解码速度下限。
  • 模型:通过离线探查器收集的模型参数,如模型大小、稀疏水平和缓存特性等。
为了准确测量硬件和模型特性,规划器利用离线探查器来确定其特定参数。对于硬件,探查器进行一系列微基准测试以评估各个组件的性能,包括CPU功能Fcpu(i)、I/O带宽Bio(i, s)和内存带宽Bmemory。对于模型参数,探查器首先测量神经元大小和数量等静态信息。然后,它通过在包含多达1000万个tokens的广泛数据集(如Wikipedia和RefinedWeb)上运行模型,收集神经元热度、Pactivated和Pmiss(m)的动态数据。此外,探查器在不同内存限制下测量特定模型的Pmiss(m)。
 
notion image

5.3 成本模型

在收集输入参数后,规划器使用成本模型生成执行计划。目标是最大化生成速度s(如公式1所定义),同时遵守用户指定的约束(公式3-5)。解码速度s与解码一个token所需的时间成反比(公式1),由该token的计算时间决定(公式2),因为我们有效地重叠了计算和I/O操作。我们定义了目标函数和约束后,可以使用成熟的SMT求解器来解决构建的模型。在我们的实现中,我们使用Z3求解器来解决成本模型。
notion image
为了计算解码时间,我们首先对计算时间建模。我们观察到与计算相比,内存操作不是显著因素,因此我们在计算时间中不考虑内存时间。计算时间(公式6)主要受注意力块、预测器和FFN块的影响。计算涉及将这些组件的计算负载除以CPU的FLOPS(公式7-8)。所选CPU核心的FLOPS在公式9中指定。
notion image
由于FFN块计算与神经元加载重叠,规划器还必须考虑I/O传输时间。通过将从闪存存储中传输的神经元数量(公式10)除以I/O带宽来计算I/O时间。这取决于激活率和缓存未命中率。
notion image
最后,规划器计算从内存加载神经元的时间,这与注意力块、预测器和运行时激活的神经元的权重大小有关。内存时间通过将一个token的激活神经元的总权重除以内存带宽来确定(公式11)。

6 实现

PowerInfer-2基于PowerInfer [30](一个为稀疏激活的LLM设计的最先进服务框架)开发,并在其基础上增加了12000行C++代码。这些增强包括几个关键领域:多态神经元引擎、神经元缓存、灵活神经元加载和神经元簇级I/O流水线。
由于PowerInfer-2依赖于需要root权限的特权系统API(如锁定内存页面的mlock),我们将其构建在Android [5]平台上。尽管不需要修改系统内核,但一个root过的Android系统仍为我们提供了在开发和调试系统方面的巨大灵活性。此外,PowerInfer-2本质上无需修改内核,使其易于移植到其他操作系统,包括iOS [14]平台。
当前实现的PowerInfer-2支持多种模型大小的LLM,包括Llama-2家族 [27](7B、13B)、TurboSparse-Mistral [31](7B)和TurboSparse-Mixtral [31](47B)。
 
 
notion image

7 评估

在本节中,我们评估了PowerInfer-2在不同模型和智能手机硬件上的性能。

7.1 实验设置

硬件。我们选择了一款高端和一款中端OnePlus [25]智能手机进行评估,详细信息列于表3中。我们选择这些智能手机有两个原因。首先,这些硬件配置代表了高端和中端智能手机。OnePlus 12是一款高端智能手机,配备旗舰硬件,包括顶级的高通SoC,而OnePlus Ace 2代表了上一代智能手机。其次,两款手机都允许root,以便我们绕过供应商指定的应用限制,充分解锁智能手机的计算能力。
模型。我们选择了四种不同架构和模型大小的语言模型,即TurboSparse-Mistral-7B3 [31](简称“Mistral-7B”)、稀疏Llama-7B/13B [29]和TurboSparse-Mixtral-47B4 [31](简称“Mixtral-47B”)。
基线。我们将PowerInfer-2与三个最先进的LLM推理框架进行比较:llama.cpp [13]、LLM in a Flash [4]和MLC-LLM [33]。llama.cpp目前是最快的大模型推理框架,支持部分模型权重的闪存存储(通过mmap),也是许多其他框架的后端,如Ollama [2]。LLM in a Flash(在评估中称为LLMFlash)设计用于PC环境,未开源。因此,我们通过根据原始论文中的描述在llama.cpp中实现稀疏预测、行列捆绑、神经元数据缓存和内存管理来移植它。MLC-LLM利用移动GPU加速大模型推理,但不支持权重卸载。当模型参数超过可用内存时无法运行。因此,我们仅在完全内存内推理的场景中与MLC-LLM进行比较。
对于PowerInfer-2和LLMFlash,我们部署了稀疏化模型,而对于其他基线系统,我们使用原始模型进行速度比较。
工作负载。评估工作负载从实际LLM任务中选择,包括多轮对话、代码生成、数学问题解决和角色扮演,以充分展示PowerInfer-2的效率。值得注意的是,这些选择的工作负载是来自huggingface社区的实际任务代表。我们使用长度为128和512个tokens的提示测试预填充性能。对于解码测试,我们使用最多64个tokens的提示并生成最多1024个tokens。所有测试运行重复10次以平均波动。
关键指标。由于我们关注低延迟设置,我们的主要评估指标集中在端到端生成速度。在我们的评估中,我们采用了预填充速度(tokens/s)和解码速度(tokens/s)作为指标,以更直观地表示系统性能。
notion image
 
notion image

7.2 基于卸载的性能

在本节中,我们评估了在内存受限的情况下,PowerInfer-2在不同模型上的解码和预填充性能,并与llama.cpp和LLMFlash进行比较。

7.2.1 解码性能

我们首先比较了PowerInfer-2与最先进的LLM推理框架的解码速度。我们将FFN块权重在DRAM中的放置限制为所有模型的50%,除了OnePlus Ace 2上的TurboSparse-Mixtral-47B,该模型由于可用内存较低,最多只能在DRAM中放置25%的FFN权重。
图6展示了各种模型的生成速度。在高端的OnePlus 12上,PowerInfer-2平均比LLMFlash快3.94倍(最高4.38倍),比llama.cpp快25.4倍(最高29.2倍)。在中端的OnePlus Ace 2上,PowerInfer-2比LLMFlash平均快2.99倍,比llama.cpp平均快13.3倍。
当模型大小超过可用DRAM时,模型权重在闪存存储和内存之间交换,带来了显著的I/O开销。尽管LLMFlash使用神经元缓存存储最近访问的神经元而不是直接使用mmap,这使其平均比llama.cpp快5.35倍,但仍有约10%的激活神经元需要从闪存中以阻塞方式加载,导致计算前的长延迟。相比之下,PowerInfer-2不仅利用高效的神经元流水线重叠I/O操作与计算,还通过灵活的神经元捆绑提高I/O吞吐量,有效消除了这一开销,在不同模型上实现了更好的性能。
如图6所示,PowerInfer-2的加速比随模型变化。这一变化归因于激活参数的实际数量。例如,尽管TurboSparse-Mixtral-47B有470亿参数,但由于使用了专家混合架构和高稀疏性,每个token激活的参数仅约为30亿,与TurboSparse-Mistral-7B相近。这就是为什么这两个模型的性能相似的原因。值得注意的是,TurboSparse-Mixtral-47B实现了每秒9.96个tokens的生成速度,但仍未耗尽所有可用内存。通过扩大神经元缓存,可以进一步提高解码速度,这将在后续部分进行评估。

7.2.2 预填充性能

在本节中,我们评估了PowerInfer-2在提示长度为128和512个tokens时的预填充性能。图7展示了PowerInfer-2与其他基线系统的提示处理速度。对于长度为128个tokens的提示,PowerInfer-2在高端OnePlus 12上平均比LLMFlash快6.95倍,比llama.cpp快9.36倍;在中端OnePlus Ace 2上,分别快7.15倍和6.61倍。对于长度为512个tokens的提示,PowerInfer-2在OnePlus 12上运行Llama-7B时速度提升达到13.3倍。
这种加速得益于PowerInfer-2的NPU为中心的预填充策略。首先,NPU在处理大批量计算时比CPU和GPU更强大。基线系统在预填充阶段使用GPU,而PowerInfer-2充分利用NPU加速计算。其次,PowerInfer-2在预填充阶段充分利用顺序I/O。随着批量大小的增加,单个神经元被激活的概率也增加。例如,在TurboSparse-Mixtral-47B中,当批量大小为128时,单个神经元被激活的概率为99.99%。结合顺序I/O的带宽为4 GB/s,比随机I/O快三倍,PowerInfer-2在预填充阶段使用密集计算,顺序加载整个FFN块到内存中。第三,通过在当前层计算期间预加载下一层的权重,PowerInfer-2可以高效地重叠权重加载与计算。
利用这些技术,预填充阶段计算速度而非顺序读取速度成为PowerInfer-2的瓶颈。如图8所示,在提示长度为128个tokens时,计算时间(包括权重去量化和操作执行)比顺序I/O时间长2.83倍。在提示长度为512个tokens时,由于计算时间增加而顺序I/O时间保持不变,计算与顺序I/O时间差距增至4倍。
notion image

7.2.3 不同内存容量下的性能

在实际使用场景中,智能手机需要同时运行多个应用,导致可用内存不定。为评估PowerInfer-2在这种条件下的适应性,我们评估了其在7GB至19GB不同内存容量下的性能。图9展示了在不同内存配置下TurboSparse-Mixtral-47B的解码速度。
当可用内存限制在7GB时,PowerInfer-2的解码速度为每秒2.13个tokens。设计上,非FFN层权重(1GB)、预测器权重(2.6GB)和FFN权重的量化尺度(2.7GB)常驻内存,并保留300MB内存用于中间张量、KV缓存和PowerInfer-2的其他运行时内存,总共使用6.6GB内存。在整体内存限制为7GB的情况下,存储FFN权重的神经元缓存大小设置为400MB,仅缓存TurboSparse-Mixtral-47B FFN权重的1.8%。如此小的缓存使得token之间几乎无法重复使用缓存神经元。因此,每个token的所有神经元都需要从闪存中提取。然而,由于高效的灵活神经元加载和神经元级流水线,PowerInfer-2仍比LLMFlash快1.84倍。随着神经元缓存大小的增加,PowerInfer-2的解码速度与内存大小线性增长,最高可达18GB内存。当使用所有可用内存(19GB)时,PowerInfer-2实现了每秒11.68个tokens的解码速度,比LLMFlash快3.12倍,比llama.cpp快21.2倍。

7.2.4 解码速度分布

为评估PowerInfer-2在不同实际LLM任务中的鲁棒性,我们研究了PowerInfer-2在任务级和token级的解码速度分布。
对于特定任务的解码速度,我们测量了四个代表性实际任务的平均解码速度:角色扮演、多轮对话、数学问题解决和代码生成。图10显示了PowerInfer-2在不同任务中的解码速度至少为每秒11.4个tokens,展示了PowerInfer-2在处理多样任务方面的鲁棒性。解码速度略有不同,原因在于执行不同任务时模型的激活稀疏性有所不同。
为了检查每个token解码速度的分布,我们测量了TurboSparse-Mixtral-47B和TurboSparse-Mistral-7B上1024个tokens的平均、50th百分位(P50)、90th百分位(P90)和99th百分位(P99)解码速度。我们将两个模型的FFN权重放置限制在DRAM中的50%。表4显示了解码速度分布。对于TurboSparse-Mixtral-47B,10%的tokens生成速度比平均解码速度慢16.5%,而99th百分位的解码延迟比平均延迟慢40.9%。这种性能差异是由于相邻tokens的激活相似性变化引起的。具有相似激活的tokens可以共享神经元缓存中已有的常用神经元,减少从闪存中提取神经元的需求。以TurboSparse-Mixtral-47B为例,我们观察到平均每个token的神经元缓存未命中率为3.5%,而P99未命中率为18.9%,是平均的5.4倍。高未命中率导致更多神经元在神经元缓存和闪存之间交换,从而延长了解码时间。
notion image

7.3 内存中的性能

如果模型大小完全适合设备的内存,PowerInfer-2可以在保持高解码速度的同时节省内存使用。本节评估在可用内存充足情况下TurboSparse-Mistral-7B的解码性能。我们将PowerInfer-2与llama.cpp和MLC-LLM(分别代表智能手机上的CPU和GPU解码)进行比较,结果如图11所示。
当不使用卸载且所有模型权重驻留在内存中时,PowerInfer-2平均比llama.cpp和MLC-LLM快1.64倍和2.06倍。这主要归功于模型的激活稀疏性,减少了约70%的FFN计算。TurboSparse-Mistral-7B需要至少4GB内存来存储其所有模型参数。通过卸载一半的FFN权重,PowerInfer-2可以节省约1.5GB内存,实现在不卸载任何权重的情况下保持与llama.cpp和MLC-LLM相当的性能。相比之下,卸载如此多的FFN权重使llama.cpp的解码性能下降了20.8倍,并且使MLC-LLM无法运行。证明了PowerInfer-2能够在减少已适合内存的模型内存消耗的同时保持用户体验。

8 相关工作

资源高效的LLM

在资源受限设备上部署LLM变得越来越受欢迎。代表性框架是MLC-LLM,它支持在移动设备上本地部署许多大语言模型并利用GPU加速。然而,它仅限于内存内计算场景,当模型太大而无法适应内存时无法运行。还有其他方法,如网络剪枝、知识蒸馏和量化来减少模型的内存占用。这些方法与PowerInfer-2是正交的,可以与PowerInfer-2结合使用以进一步提高在移动设备上部署LLM的效率。

推测性解码

推测性解码也可以用于增强推理速度。这种技术使用较小的模型(例如,1B参数)快速生成多个候选tokens,然后使用较大的模型(例如,13B参数)批量验证它们。只有被较大模型接受的tokens才会显示给用户。通过一次验证多个tokens,SpecInfer可以减少解码步骤的数量。然而,在卸载场景中,大量的I/O加载成为推测性解码的瓶颈,尤其是对于需要为一个批次加载所有专家的MoE模型,失去了专家稀疏激活的好处。

9 结论

本文介绍了PowerInfer-2,一个支持在智能手机上进行高速LLM推理的框架,特别是对于超过设备内存容量的模型。PowerInfer-2的关键理念是利用智能手机中的异构资源,将矩阵计算适应为更易管理的神经元簇计算。对两款智能手机的评估表明,PowerInfer-2比现有最先进的系统实现了高达29.2倍的速度提升,并且是第一个能够高效在智能手机上运行超大型语言模型如TurboSparse-Mixtral-47B的推理框架。

🤗 总结归纳

PowerInfer-2是一个支持在智能手机上进行高速大型语言模型(LLM)推理的框架,特别适用于超过设备内存容量的模型。它利用智能手机中的异构资源,将矩阵计算适应为更易管理的神经元簇计算。评估表明,PowerInfer-2比现有最先进的系统实现了高达29.2倍的速度提升,并且是第一个能够高效在智能手机上运行超大型语言模型如TurboSparse-Mixtral-47B的推理框架。

📎 参考文章

 
上一篇
5G-a & 5G Redcap 知多少
下一篇
Mac Dell P2415Q 输出4k只有30hz的解决办法