问题引入
LLM(大语言模型)加速是指通过各种技术优化其推理和训练过程,以提高处理速度和计算效率。由于大语言模型通常包含数十亿甚至上千亿个参数,计算开销巨大,因此加速技术的应用至关重要,尤其是在实时应用、低延迟要求或资源受限的环境中。LLM加速技术主要涵盖硬件加速、算法优化、软件框架优化和分布式计算等方面。
需要考虑的几个问题:
-
给LLM加速的方法涉及到很多方面,哪种对加速的提升最大?哪种是当前研究的热门方向?
-
ChatGPT给的答案是:在现有的加速技术中,混合精度计算、模型剪枝和知识蒸馏是最常用且最容易优化的加速手段;还提到了稀疏注意力与并行计算
-
知乎https://zhuanlan.zhihu.com/p/654942557:这篇文章从模型压缩、Attention、解码方法、continuous batching和分布式并行推理几个方面介绍加速方法
-
论文Efficient Large Language Models: A Survey(https://arxiv.org/abs/2312.03863):LLM加速有两大方面:Model-Centric Methods和Data-Centric Methods,这篇论文的解读在:https://zhuanlan.zhihu.com/p/714751580
-
知乎https://zhuanlan.zhihu.com/p/688736901:从量化、模型结构改进和Dynamic batch三方面介绍了LLM加速
-
知乎https://zhuanlan.zhihu.com/p/699776257:从一篇survey出发,介绍了不同加速方式的实现原理和优劣
-
-
LLM加速的实验环境是什么样的,需要模拟嵌入式设备吗?还是需要使用真正的嵌入式设备做实验?有没有推理加速框架?
-
ChatGPT的答案:LLM加速的实验环境不一定一开始就需要真实的嵌入式设备。开发初期可以在高性能计算环境或仿真环境中进行,减少开发时间和资源消耗。
-
加速推理框架vLLM,对该框架的简要介绍:百度安全验证,该框架的github地址:GitHub - vllm-project/vllm: A high-throughput and memory-efficient inference and serving engine for LLMs
-
-
LLM加速效果的评价指标有哪些?哪些最重要?
-
知乎https://zhuanlan.zhihu.com/p/695470224:介绍了影响LLM加速的各种指标
-
其他问题:
-
问:在嵌入式设备上需要进行模型压缩,这是为什么,难道不可以在联网的状态下把对LLM的请求直接发给在大型服务器上运行的LLM吗?
答:主要出于延迟和隐私性的考虑
-
对于许多实时应用,例如语音助手、自动驾驶、VR等,系统需要即时响应用户的输入。
-
并非所有环境都能保证设备始终处于联网状态。
-
某些嵌入式设备处理的内容涉及用户的敏感数据
-
其他成本和资源限制问题
-
前置知识
LLM推理
要想对LLM进行推理加速,前提就是了解LLM推理的整个流程。
-
输入的token化:
当用户输入一段文本时,模型首先会将该文本转化为token,即模型可以理解的最小单位。
模型通常配备了专门的tokenizer(如BPE,Byte Pair Encoding 或 SentencePiece),这些工具将输入文本映射为一系列预定义的token ID。
经过tokenization的输出是一个token ID序列,例如比如
[Hello, world, !]
被转换成token id[15496, 2159, 0]
-
embedding:
将token转换为模型可以理解的数字后,这些token ID会被送入模型的embedding层。每个token ID在embedding层中对应一个高维的向量,向量的维度是模型定义好的。
假设每个token映射为一个300维的向量,那么token序列
[15496, 2159, 0]
会被转换为:[ [0.5, -0.2, ..., 0.1], # 15496的嵌入向量 [-0.3, 0.4, ..., 0.7], # 2159的嵌入向量 [0.1, -0.1, ..., 0.2] # 0(表示"!")的嵌入向量 ]
-
self-attention机制:
模型对每个输入向量生成三组向量:Query(查询)、Key(键)和Value(值)。
Query和Key的内积用于计算不同token之间的相关性(注意力权重)。这些权重表示了模型应该“关注”哪些token,以及应该关注的强度。
将这些注意力权重与Value相乘,然后进行加权求和,得到每个token在当前上下文中的信息聚合结果。
-
多层Transformer堆叠
每一层的计算包括:自注意力机制,每个token与其他token的上下文交互。前馈网络,注意力输出的线性变换和非线性激活。
-
生成机制与KV Cache
在自回归生成中,模型需要多次依赖之前生成的token。这时,KV Cache会在推理的每一步中保存每一层中生成的Key和Value向量,避免重复计算之前生成的部分。比如prompt为’你是谁?‘,你一次生成内容为’我‘,那么就将’你是谁?我‘这5个token对应的KV缓存,因为等到以后生成新的token时还会用到。
-
解码
LLM可以使用不同的解码策略来生成文本。这些策略决定了模型如何选择每一步的输出token:
-
贪婪解码(Greedy Decoding):每一步选择概率最高的token,直接输出。此方法简单但缺乏多样性,容易陷入局部最优。
-
采样解码(Sampling):根据每个token的概率分布进行随机采样,能生成更加多样的结果。
-
束搜索(Beam Search):在每一步保留多个(如k个)候选序列路径,最后选择得分最高的序列。这种方式在质量和多样性之间取得平衡。
-
推理的计算
-
Embedding层计算:
输入的token经过tokenization后,会通过embedding层将token ID映射为高维向量。该过程主要是一个查表操作,即查找每个token对应的嵌入向量,并不涉及复杂的矩阵运算。
-
self attention的计算:
这是LLM推理中最核心的部分,也往往是最耗时的计算。自注意力机制允许模型在推理过程中通过比较不同token之间的相关性,动态调整它们的权重,从而实现对上下文的捕捉。
-
Query、Key、Value计算:将输入序列的每个token嵌入向量分别与Q、K、V权重矩阵相乘,生成Query、Key和Value向量。有L个token,每个token维度是,它和一个维度为的向量相乘,因此这一部分的计算复杂度为 ,其中是模型维度。
-
-
注意力权重的计算:通过计算Query和Key的点积来衡量不同token之间的相关性。具体来说,计算Query和Key的内积,然后对结果进行归一化处理(通常是通过softmax函数)。Query和Key的大小都是,Q和K的转置相乘,这一部分的计算复杂度为 ,这意味着序列长度的平方是这一步最关键的计算瓶颈。
Q和K的转置相乘结果是一个L*L的矩阵,每个元素表示第i个token的Query向量和第j个token的Key向量的点积,这个结果矩阵可以被解释为每个token(第 i 个)对其他所有token(包括它自己,第 j个)的相关性分数
-
加权求和:使用注意力权重对Value进行加权求和,从而聚合不同token之间的信息。大小为的矩阵与大小为的矩阵相乘,这一步的计算复杂度也是 。
-
前馈神经网络
经过self-attention得到的是一个大小的矩阵,先通过线性变换将每个token的维度从升到,这一步复杂度为;再使用激活函数,这一步复杂度为;最后再用线性变换把每个token维度从变回,这一步复杂度是。所以FFN层的复杂度整体来说就是。
-
Layer Normalization和Residual Connections
每一层的输出都会经过Layer Normalization,然后与输入通过残差连接(Residual Connection)相加。这部分的计算主要是线性运算,计算复杂度为
对于生成任务(如文本生成),LLM采用的是自回归解码,即每次推理一个token,并将生成的token作为输入递归地传回模型进行下一步推理,因此每次推理的L是在不断增长的。如果都将整个序列的所有token的KV都重新算一次,那么越往后推理越慢,所以需要将已经计算过的KV矩阵给缓存起来。
分析和指标
LLM推理成本高在于:
-
模型自身复杂性:模型参数规模大,对计算和内存的需求增加
-
Auto-Regressive Decoding(自回归解码):逐token进行,速度太慢
加速主要是从两个层面体现:
-
Latency:延迟,主要从用户的视角来看,从提交一个prompt,至返回response的响应时间,衡量指标为生成单个token的速度,如16 ms/token;若batch_size=1,只给一个用户进行服务,Latency最低。
针对Latency的优化,主要还是底层的OP算子、矩阵优化、并行、更高效的C++推理等,如FasterTransformer、DeepSpeed中就有不少此类优化。针对Latency的优化可以提升Throughput,但没有直接增加batch_size来的更显著。
降低延迟,本质上是提高推理速度,也就是加速计算,尤其是最耗时的attention的计算
-
Throughput:吞吐,主要从系统的角度来看,单位时间内能处理的token数,如16 tokens/s;增加Throughput一般通过增加batch_size,即,将多个用户的请求由串行改为并行
针对Throughput优化,主要是KV Cache存取优化,本质是降低显存开销,从而可以增加batch_size。
提高吞吐,本质上是通过降低内存占用来提高batch size,推理中内存占用包含模型参数和KV cache,模型参数不改变的情况下,关键是降低KV cache的内存占用。