链载Ai

标题: 万字综述 10 种 LLM 投机采样推理加速方案 [打印本页]

作者: 链载Ai    时间: 8 小时前
标题: 万字综述 10 种 LLM 投机采样推理加速方案
一、背景

我们之前对投机解码(Speculative Decoding)方案做过比较多的介绍,从 Parallel Decoding 到 Google 的 Speculative Decoding,再有 SpecInfer、Medusa、Lookahead Decoding,以及最近阿里的 Lookahead。最近看到也有一篇关于 Speculative Decoding 的综述文章 [2401.07851] Unlocking Efficiency in Large Language Model Inference: A Comprehensive Survey of Speculative Decoding,如下图Figure 3 所示:

这里我们也对投机解码相关工作进行总结,更多的是汇总我们之前接触过的或开源的方案,并对各种方案进行比较。

二、自回归解码(Autoregressive Decoding)

2.1. 概述

当前的主流 LLM 基本都是 Decoder Only 的 Transformer 模型,其推理过程可以分为两个阶段:

2.2 KV Cache

如下图所示,在 LLM 推理中最关键的就是下图中的 Multi-Head Attention,其主要的计算集中在左图中灰色的 Linear(矩阵乘)和 Scaled Dot-Product Attention 中的 MatMul 矩阵乘法:

如上右图中的 Mask 是一个下三角矩阵,也是因为这个下三角矩阵实现了 LLM Decoder 的主要特性,每个 Token 都只能看到当前位置及之前的 Token。

如下图所示,其中的 QKT 可以理解为一个相关性矩阵,如动图所示,4 个 Token 对应 4 个 Step,其中:

在 Decoding 阶段 Token 是逐个生成的,上述的计算过程中每次都会依赖之前的结果,此时最简单的思路就是 Cache 之前计算过的中间结果,在计算当前 Token 时直接从 Cache 中读取而不是重新计算,如下图所示,上面是没有 Cache 的情况,下面是有 Cache 的情况:

如下表所示,在 T4 GPU 上以 GPT2 模型为例验证有无 Cache 对推理时延的影响,其加速效果非常明显,因此也成为 LLM 推理的标配:

GPT2/T4

无 KV Cache

有 KV Cache

加速比

Output Token 1000

52.53s

9.12s

5.76x

当然,KV Cache 也有一定不足,其相当于使用空间换时间,占用的显存会大幅增加,尤其是对于参数规模较大的模型。比如,对于 Vicuna-13B 模型(FP16 推理,其 Transformer layer num=40, embedding size=5120)来说,在 Sequence Length=1024,batch size=8 下,KV 缓存所占显存大小为 2 * 2 * 40 * 5120 * 1024 * 8 = 6.7G。

2.3 访存瓶颈

因为 Decoding 阶段 Token 逐个处理,使用 KV Cache 之后,上面介绍的 Multi-Head Attention 里的矩阵乘矩阵操作全部降级为矩阵乘向量。

除此之外,Transformer 模型中的另一个关键组件 FFN 中主要也包含两个矩阵乘法操作,但是 Token 之间不会交叉融合,也就是任何一个 Token 都可以独立计算,因此在 Decoding 阶段不用 Cache 之前的结果,但同样会出现矩阵乘矩阵操作降级为矩阵乘向量。

矩阵乘向量操作是明显的访存 bound,而以上操作是 LLM 推理中最主要的部分,这也就导致 LLM 推理是访存 bound 类型。

基于 V100 GPU,FP16 精度,LLM 推理 Prefill 阶段和 Decoding 阶段的 Roofline Model 可以近似表示如下(理论上限),其中

2.4 Decoding 阶段优化

如下图 Figure 4 所示,Prefill 阶段在比较小 Batch Size 下可以获得比较大的计算强度,相应的吞吐也很高;而 Decoding 阶段需要比较大的 Batch Size 才能获得相对高的计算强度及吞吐(图片来自 [2308.16369] SARATHI: Efficient LLM Inference by Piggybacking Decodes with Chunked Prefills ):

针对 Decoding 阶段计算强度比较低的情况,有两种优化的思路:

如下图所示为 Batch size 为 1 和 512 时 LLM 中几个主要 OP 的计算耗时,可以看出,将 Batch size 从 1 增加到 512,计算量增加 512 倍,但是其整体时间只增加为原来的 3 倍左右(图片来自 openppl-public · GitHub),如果平均每次验证通过 5 个 Token,那么总的 Decoding Step 数目将降为 1/5,总的 Decoding 时间变为原来的 3/5(忽略其他部分开销),那么即可以实现单一请求的加速:

实际的生成环境中可能要综合考虑上述的两种优化思路,比如如果不同用户间 Continuous Batching 已经达到比较大的 Batch Size,各种矩阵运算接近或超过 Roofline 的交叉点,那么再使用 Speculative Decoding 并不会有什么收益,这一点也是当前提到投机采样最容易被忽略的。

三、并行解码(Parallel Decoding)

3.1 方案概述

Parallel Decoding 的第一个工作是 2018 发表在 NIPS 上的 Blockwise Parallel Decoding for Deep Autoregressive Models。作者提出分块并行解码(Blockwise Parallel Decoding)方案,在精度不变的情况下可以获得 2x 加速,在牺牲少量精度的情况下可以获得 7x 加速。

假设输出序列的长度为 m,那么 Autoregressive Decoding 要执行 m 步才能获得最终结果,随着模型的增大,每一步的时延也会增大,整体时延也会放大至少 m 倍,在 Blockwise Parallel Decoding 中,作者期望通过 l 步就可完成整个预测,其中 l 远小于 m。

3.2 实现细节

具体方案如下图所示,分为三步:

  1. Predict 阶段

令 p1=p(p 表示原始模型),然后额外训练一系列的辅助模型 p2,...,pk,其中 pi(yj+i|y<=j,x),也就是说,第 i 个模型是根据之前 1-j 个输出生成第 j + i 个输出。比如,当前已经生成了 I、saw、a、dog、ride 5 个 Token,后续要生产 in、the、bus,那么

  1. Verify 阶段

上一步得到了 K 个新的输出,但是还无法知道这 K 个输出是否全部正确,因此需要进一步验证。分别将前 j-1 个新的 Token 与输入合并,并预测下一个 Token,如果下一个 Token 与第 j 个 Token 相同,则接受这个 Token。例如,上一步得到了 in,the,car,则需使用模型 p1(原始模型)分三组验证(这三组可以并行执行):

  1. Accept 阶段

假设上一步生成了 10 个 Token,在第 5 个 Token 出不一致,那么就可以将前 4 个 Token 和输入合并,然后开始下一次生成。还是用前两步的例子,因为第三组 car 和 bus 不一致,因此只接受 in 和 the,则下一次迭代的输入为 I saw a dog ride in the。

如下图 Figure 3 所示为模型的实现方式,在模型的最后一个 Transformer Decoder 层额外的加几个 head,分别为 p2,...,pk:

并行验证过程如下所示,经过一次前向推理即可验证获得新的 in、the、car 三个 Token:

综上所述,由于 Predict 阶段 p1 和 Verify 阶段都使用的原始模型,因此在理想情况下(每次生成的 K 个 Token 都能接受),总的解码次数从 m 降低到 2m/K。

3.3. 评估结果

作者使用 WMT 2014 的英语-德语翻译数据集。Baseline 模型是在 8 个 P100 GPU 上训练了 1,000,000 steps 的 Transformer 模型。使用 Greddy Decoding,在 newstest2023 development 数据集上 BLEU 得分为 25.56.

作者针对不同的猜测 Token 数,使用原始数据或者 Beam Search 生成的蒸馏数据分别进行训练,每个模型都在相同的硬件额外训练 1,000,000 steps。基于上述模型,作者统计了相应的 BLEU 得分和对应的平均接受 Token 数,如下图所示:

对应上述的机器翻译任务,当 k=8 时,对应的平均接受 Token 数为 4.7,相应的整个任务的加速比达到 3.3 倍。如下图所示:

四、投机解码(Speculative Decoding)

4.1. 方案概述

Google 和 Deepmind 于 2022 年提出投机采样方案 Fast Inference from Transformers via Speculative Decoding,其思路很简单,使用一个高效的小模型来生成多个候选 Token,然后让 LLM 来验证。

4.2 实现细节

假设 Mp 为目标模型,模型推理就是给定前缀输入 x<t,从模型获得对应的分布 p(xt|x<t),要做的就是加速这个推理过程;假设 Mq 为针对相同任务的更高效的近似模型,给定前缀输入 x<t,从模型可以获得对应的分布 q(xt|x<t)。核心思想为:

  1. 使用更高效的模型 Mq 来生成输出 ?∈ℤ+ 个 Token

  2. 使用目标模型 Mp 来并行的评估上一步 Mq 生成的 Token,接受能够满足同一分布的 Token

  3. 从调整后的分布中生成一个额外的 Token(根据第一个出错 Token 之前的 Token 生成),来修复第一个出错的 Token,如果所有 Token 都被接受,则额外新增一个新生成的 Token,以此来保证每次至少生成一个新的 Token。这样,即使在最坏情况下,目标模型相当于完全串行运行,运行次数也不会超过常规模式直接串行运行目标模型的次数;当然,也很可能能够生成更多的 Token,最多可以达到 ?+1,这取决于Mp 和 Mq 的相似度。

如下图 Figure 5 所示,作者提供了一个简单的示例,包含不同的 ?(验证的 Token 数目),其中紫色为执行目标模型 Mp 的 decoder,蓝色为执行近似模型 Mq 的 decoder,黄色和橙色为调用 encoder。

4.3. 评估结果

作者基于 T5X 代码库验证了 T5-XXL 模型的加速效果。相关的设置如下:

  1. 目标模型 Mp:T5-XXL(11B)

  2. 近似模型 Mq:T5-Large(800M),T5-Base(250M),T5-Small(75M)






欢迎光临 链载Ai (https://www.lianzai.com/) Powered by Discuz! X3.5