其中一个优化角度是Sharing-based Attention优化,即修改Attention结构使多个头间共享部分数据。如论文《Fast Transformer Decoding: One Write-Head is All You Need》中提出的MQA(Multi-Query Attention)与论文《GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints》中提出的GQA(Group-Query Attention)。它们被用于在PaLM, StarCoder, LLaMA2等模型中。但由于涉及网络结构本身的改变,这里不作展开。
FlashAttention & FlashAttention2
FlashAttention系列可能是这几年中关于Attention最重要的优化。论文《FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness》与《FlashAttention-2: Faster Attention with Better Parallelism and Work Partitioning》分别提出了FlashAttention(FA)和FlashAttention 2(FA2)。由于出色的性能表现,目前已成为业界的标配。
记Attention的输入为
Q
,
K
,
V
∈
R
N
×
d
\mathbf{Q,K,V} \in \mathbb{R}^{N \times d}
Q,K,V∈RN×d,其计算过程的数学描述为:
S
=
Q
K
T
∈
R
N
×
N
,
P
=
softmax
(
S
)
∈
R
N
×
N
,
O
=
P
V
∈
R
N
×
d
\mathbf{S = QK}^T \in \mathbb{R}^{N \times N}, \quad \mathbf{P} = \text{softmax}(\mathbf{S}) \in \mathbb{R}^{N \times N}, \quad \mathbf{O = PV} \in \mathbb{R}^{N \times d}
S=QKT∈RN×N,P=softmax(S)∈RN×N,O=PV∈RN×d 其中矩阵相乘
Q
K
T
\mathbf{QK}^T
QKT产生shape为[batch, head num, seq len, seq len]的中间张量,
P
\mathbf{P}
P也一样。而最终需要的
O
\mathbf{O}
O是shape为[batch, head num, seq len, hidden size of one head]的张量。由于seq len一般会很长(现在的模型中支持的seq len越来越长,如GPT-3为2K, LLaMA-2为4K到32K,GPT-4有32k,CodeLlama有100k,Gemini 1.5有1M),因此前者的中间张量会非常大。这也意味着如果按照上面的数学定义来计算,中间张量大概率会把内存撑爆。FlashAttention使用tiling解决了该问题,同时减少了HBM与SRAM的读写。谈到tiling,很多文献是针对GEMM或者Conv这样的算子,但要应用于softmax咋一看会有些棘手,因为它本身包含了reduction的语义。对于这个问题,FlashAttention使用论文《Online normalizer calculation for softmax》中的online softmax技术,从而避免了构建巨大的attention matrix,同时也使得softmax可以被并行(原文3.1节)。该算法使内存的复杂度降低到线性,极大降低了它的memory footprint。另外,它还通过kernel fusion,将attention所有操作融合到一个CUDA kernel中,从而减少了kernel launch与访存的开销。
论文《A Case Study in CUDA Kernel Fusion: Implementing FlashAttention-2 on NVIDIA Hopper Architecture using the CUTLASS Library》针对NVIDIA Hopper架构改进了Flash-Attention-2实现。它基于CUTLASS实现,利用了Hopper架构新引入的特性-Tensor Memory Accelerator(TMA)和Warpgroup Matrix-Multiply-Accumulate(WGMMA)指令。通过将TMA copy与WGMMA指令进行overlap,同时选取最优的tile size以平衡寄存器压力与shred memory的使用,相比Ampere架构上的FA 2实现有20-50%的性能提升。
FlashDecoding & FlashDecoding++
文章"Flash-Decoding for long-context inference"和论文《FlashDecoding++: Faster Large Language Model Inference on GPUs》提出了Flash-Decoding(FD)与FlashDecoding++(FD++),也称为FlashAttention-V3和V4。前面的FA是训练与推理通用的,而FD,就像它的名字一样,是针对推理场景中的decoding的。
Attention的性能瓶颈在于对中间张量
Q
K
T
QK^T
QKT的读和写。前面的FA在batch size与query length维度上做并行。训练阶段由于batch大,容易并行。但推理阶段query length一般是1,同时推理时batch一般还比较小。这意味着如果batch数小于SM数量,就打不满GPU,硬件资源会被浪费。这在长序列时尤为严重,因为序列长一般意味着batch较小。因此,FA的优化不太适用于推理。
论文《Blockwise Parallel Transformer for Large Context Models》提出了Blockwise Parallel Transformer(BPT)方法对self-attention与FF模块都用blockwise的方式计算,并将它们融合。这样可以节省构建中间张量所需的内存。对于GPT2模型,能训练的seq长度比标准的attention长32倍,比FlashAttention长4倍。
论文《Generating Long Sequences with Sparse Transformers》基于很多层有sparse attention pattern的观察,提出Factorized Self-Attention,将full self-attention操作分解成多维护更快的操作。每个attention head,会使用pattern选取一些位置的子集。对于图像和音乐等具备周期性的数据,可以使用strided attention pattern;而对于其它如文本数据,可以使用fixed attention pattern。该方法的复杂度为
O
(
n
n
)
O(n \sqrt{n})
O(nn)。实现上,它还使用了sparse attention kernels用于计算attention matrix的子集。
Reformer
论文《Reformer: The Efficient Transformer》采用了以下技术:1) 使用locality-sensitive hashing(LSH)替换dot-product attention。使其复杂度从
O
(
L
)
O(L)
O(L)降到
O
(
L
log
L
)
O(L \log L)
O(LlogL)。LSH是一种在高维空间中寻找nearest neighbor的方法。这里用来在attention中找序列中相关的context。2) 它还使用了reversible residual layer来替代原来的residual,它使得训练中的activation只需存一次而不是N次(N为layer num)。3) 将FF层中的activation切分并以chunk为单位进行处理,从而减少FF层中的memory。
Routing Transformer
论文《Efficient Content-Based Sparse Attention with Routing Transformers》提出学习dynamic sparse attention patterns,避免为与query无关的内容浪费memory与计算。它基于local attention与content-based sparse两方面的思想。Routing Transformer在self-attention上加了基于online k-means的sparse routing module。每一步的query都被route到部分cluster assignment所指定的context元素。它的启发来源于spherical k-means clustering在Maximum Inner Product Search(MIPS)问题上的应用。该方法避免了实例化dense attention matrix,将复杂度从
O
(
n
2
d
)
O(n^2d)
O(n2d)降低到了
O
(
n
1.5
d
)
O(n^{1.5}d)
O(n1.5d)。
HyperAttention
以往的Approximate Attention些方法普遍不支持causal masking。以往工作表明Attention在最坏情况下,需要quadratic time,除非attention matrix的元素有界或者矩阵rank较小。论文《HyperAttention: Long-context Attention in Near-Linear Time》中提出的HyperAttention是一种approximate attention机制,用来解决LLM中长上下文带来的计算挑战。该方法采用Locality Sensitive Hashing(Hamming sorted LSH)与Approximate Matrix Multiplication(AMM)对Attention的计算
A
t
t
n
=
D
−
1
A
V
\mathbf{Attn = D^{-1}AV}
Attn=D−1AV进行近似。它可以达到接近线性复杂度,且支持casual mask。
论文《Efficient Memory Management for Large Language Model Serving with PagedAttention》中提出的PagedAttention使用类似于操作系统中的虚拟内存机制对KV Cache进行管理。KV Cache的size会随着token产生的过程动态变化。一种简单的方式是提前按最大可能长度预分配连续的内存。但是,这会导致三种内存浪费:预留空间,内部碎片化,外部碎片化。其中有效利用的内存可能只有20%左右。另一方面,这种方式难以实现KV Cache的内存共享(Memory sharing)。在一些场景中,我们需要对于一个request生成多个序列,或者在做beam search时,其prompt或者不同beam candidate的序列的KV cache是可以共享的。
对于request间有相同的prefix的情况,将KV Cache缓存下来可以避免重复计算。这就是Prefix caching的基本思想。比如论文《Improving Large Language Model Throughput with Efficient Long-Term Memory Management》基于PagedAttention提出prefix cache,该prefix cache可被swap到CPU与disk。
在prompt工程中,我们会为用户的prompt前加一些system prompt。它包含了任务描述、上下文信息、样例等信息。System prompt在多个request间是相同的,并且可能会很长。如果对于每个request,都去重新计算就会带来巨大的浪费,导致Time to first token (TTFT)非常长。
RadixAttention
"Fast and Expressive LLM Inference with RadixAttention and SGLang"一文指出现有支持KV Cache共享的系统需要手工配置和调整,无法自动化。它提出的RadixAttention是一种运行时的自动高效的跨多LLM generation调用的KV Cache reuse机制。它在当request的处理完成后,不会丢弃其KV Cache,而是将token序列到KV Cache的映射用radix tree管理起来。这样prefix search,insertion和eviction操作会非常高效。另外它还实现了LRU eviction policy和cache-aware scheduling policy来提升cache hit rate。
ChunkAttention
论文《ChunkAttention: Efficient Self-Attention with Prefix-Aware KV Cache and Two-Phase Partition》也是用于多request的prompt有共同prefix的场景(如system prompt与task-specific input组合成最终prompt的情况,或者使用templated requests的情况)。它提出的ChunkAttention是一种新的self-attention module。一方面,它采用Prefix-Aware KV Cache(PAKV),将KV Cache切成小的chunk,将它们以prefix tree的方式组织。具有相同prompt prefix的序列的query张量会被batch到一起。另一方面,它引入two-phase partition(TPP)算法加速在PAKV上的计算。它的优点是可以在运行时自动与动态地检测相同的prefix并优化。
网络模型对于不同的输入,需要的计算是不同的。因此,我们可以用adaptive compute来减少计算量。Adaptive compute主要依赖early-exit策略。Transformer网络是一个多层结构。意味着对于简单的输入,可能只要算前面几层就行。Early exiting可以根据中间层的表征直接输出新token,跳过网络中后面的部分,从而避免计算整个模型。那现在主要的问题就是如何确定exit point,也就是如何判断是否是“难”的。对于这个问题大致有几类方法:1) Heuristic metrics:如entropy, maximum softmax score, 最上两层softmax的差,或者cosine similarity等。但它们的泛化性较差,且threshold需要tuning。2) Learn-to-exit:泛化性好,且不需要threshold tuning。如论文《Confident adaptive language modeling》中就用了这两种方式。3) Hash-function:如论文《A simple hash-based early exiting approach for language understanding and generation》中提出Hash-based Early Exiting(HASHEE)方法用于替代learn-to-exit。这里的hash function用于构建token到exiting layer的映射。基本思想是如果训练中一个样本是容易的,那推理时与它相似的样本也应该是容易的。
论文《SkipDecode: Autoregressive Skip Decoding with Batching and Caching for Efficient LLM Inference》是一种token-level early exit方法,使之能用于batching inferencing和Key-Value Caching。Batching带来的难点是需要等batch中最后的token被处理。KV Cache带来的难点在于如果当前token比其它token退出更晚则需要更新前面token的KV Cache。SkipDecode为batch中的每个sequence position设立单独的exit point,从而克服了这些缺点。它利用了序列结尾更容易预测的特点,序列越到后面所需计算越少(可参见论文Figure 2)。这样做也使前面token的KV Cache不需重新计算。
Genearalizied Aggressive decoding(GAD):来自论文《Lossless Speedup of Autoregressive Translation with Generalized Aggressive Decoding》。它是一种lossless的auto-regressive translation加速方法。它使用NAT同时得到多个token作为draft,然后用AT进行验证,发现分歧就丢弃。
Speculative sampling(SpS):论文《Accelerating Large Language Model Decoding with Speculative Sampling》中提出。它用小型的draft model产生token序列(可用并行的方式,也可用auto-regressive方式),然后用target model给这段序列打分。最后用reject sampling方法,从左到右判断是否接受,从而还原target model的分布。
SpecInfer:论文《SpecInfer: Accelerating Generative Large Language Model Serving with Speculative Inference and Token Tree Verification》中提出。它通过小模型SSM(Small speculative model)进行投机式推理,每次试探推理多步,然后将多个SSM的推理结果汇聚成一个speculated token tree,交由LLM验证,通过高效的树形解码算子实现并行化推理。
Lookahead:论文《Lookahead: An Inference Acceleration Framework for Large Language Model with Lossless Generation Accuracy》提出的lookahead方法采用了multi-branch策略。与single-branch策略每次只考虑一个draft不同,它同时取多个drafts(当context length固定的情况下,decoding length增加在前期对于耗时影响很小),再用并行地对其进行验证,最后确定最长的子序列作为输出。由于drafts通常会有共同的prefix tokens,因此它利用trie tree对其进行组织,提出hierarchical multi-branch draft。
Minions:论文《Minions: Accelerating Large Language Model Inference with Adaptive and Collective Speculative Decoding》中提出的Minions是基于speculative decoding的LLM推理系统。它通过一些手段提高draft model的低acceptance rate,和降低验证时的开销:1) 为了提高acceptance rate,它提出的majority-voted机制使用树结构表达多个不同draft model的输出序列,并结合draft model过往的表现(average acceptance rate)得到majority-approved output。2) Draft model的speculation length影响target model的总推理时间,而最优的speculation length被数据集、batch size等多种因素影响。系统基于验证时的运行时信息,使用启发式搜索算法动态调节该参数。3) 通过intermidiate resulting pool将draft model与target model的执行解耦,使它们组成pipeline,减少idle time,提高吞吐。
LLMCad:论文《LLMCad: Fast and Scalable On-device Large Language Model Inference》 目标是将LLM布署在如手机,IoT等移动设备上。它将一个小型的LLM放在内存中用于构建token tree。另外用一个高精度的LLM用来验证前者产生的token和修正错误。它主要用到的技术有token tree generation and verification(与token sequence不同,token tree中每个token可以有多个后继候选), Self-adaptive fallback strategy(提出使用tree-cumulative confidence指标来确定是否用target model进行验证),和speculative generation pipeline(让小型模型的产生过程与大型模型的验证过程并行)。
论文《Blockwise Parallel Decoding for Deep Autoregressive Models》提出一种blockwise parallel decoding scheme。它采用一些proposal models独立并行地做接下来几个位置的预测,然后通过scoring model选取最长的prefix。为了将scoring和prediciton模型整合在一个模型中,它改造了Transformer,在原decoder output layer后插入多输出的FF层。
LLMA:在一些任务(如retrieval-augmented generation, cache-assisted generation和multi-turn conversions)中,in-context reference与LLM产生的输出序列会有很多重复。基于这个观察,论文《Inference with Reference: Lossless Acceleration of Large Language Models》提出了inference-with-reference decoding机制,它先从reference中选出一段文字,然后将之拷贝到LLM decoder,检查它能否接受。该过程可被并行。
Aggressive Decoding:论文《Lossless Acceleration for Seq2seq Generation with Aggressive Decoding》提出的Aggressive Decoding方法是一种lossless的decoding算法 。它应用于像Grammatical Error Correction这种输入与输出非常相似的任务。它从输入序列拷贝过来作为drafted decoded tokens,然后并行地对其进行verify。对于翻译任务,Generalized Aggressive Decoding会采用额外的NAT decoding模型,然后用auto-regressive的方式并行验证。
Lookahead decoding:论文《Break the Sequential Dependency of LLM Inference Using Lookahead Decoding》中的lookahead deocding是一种不需要draft model的用于加速LLM推理的并行decode算法。它使用Jacobi iteration method并行的提取和验证多个n-grams。LLM可并行地产生多个disjoint n-grams。这些n-grams可以用于所产生序列。它将auto-regressive decoding建模成一个非线性方程组的求解过程,然后求解得到n-grams,通过验证后的为可用于最终的序列。该非线性系统它可以通过Jacobi iteration method来求解。该方法可以并行化,且可保证在m步内完成(m为变量个数)。
Non-autoregressive Transformers
既然auto-regressive的方式对性能不友好,那还有一个思路就是使用Non-autoregressive(NAT)的方式。NAT以迭代的方式迭代的方式将所有的token一起decode出来。NAR(Non-autoregressive)最开始在NMT(Neural machine translation)领域被提出。与auto-regressive方式相比,它可以并行产生token,因此耗时更少,但是代价是准确率更低。其主要原因是"failure of capturing the target side dependency"。它不像auto-regressive方法一样,产生第t个token时有前面t-1个上下文token信息。业界有一种折中的做法是iteration-based NAT模型。即每一次产生的token再给decoder做refinement,迭代数次。相关方法详细可参见论文《A Survey on Non-Autoregressive Generation for Neural Machine Translation and Beyond》。其中讨论了包括data manipulation, modeling method, traning critierion, decoding algorithm和pre-trained model等方面的工作。
另一种常见的是dynamic batching。比如Triton Inference Server可以动态地将客户端的请示在服务端组成一个大的batch。为了控制对于latency的影响,它可以配置latency的约束(最长不超过多长时间做一次batching)。但是,对于input shape会变化的场景(比如语言类模型),需要对input tensor进行padding。而padding会带来资源的浪费与性能的损失。为了避免这个损耗,就需要对输入数据进行"压缩"。比如论文《Prepacking: A Simple Method for Fast Prefilling and Increased Throughput in Large Language Models》提出batch当中prompt长度差很多时,padding的方式浪费资源严重。Prepacking优化prefill计算。它避免了pad token的计算。它使用bin-packing算法,将不同长度的prompt打包进一个序列。然后修改attention mask和positional encoding来对单个序列中的多个prompt进行计算。
这种长度不规则的张量称为ragged tensor。Ragged batching让用户指定输入中的哪些是有效的数据,从而可以避免显式的padding。接下来的问题就是还需要有相应的kernel来高效处理这种ragged tensor。一种是手写,比如Effective Transformer中的Remove padding算法可用于减少padding部分的计算量。该算法后来也被集成到FasterTransformer中。另一种是自动生成,比如论文《The CoRa Tensor Compiler: Compilation for Ragged Tensors with Minimal Padding》中的CoRA是一个张量编译器,用于为CPU与GPU平台自动生成ragged tensor的高效代码。
Response Length Perception and Sequence Scheduling:论文《Response Length Perception and Sequence Scheduling: An LLM-Empowered LLM Inference Pipeline》使用length predictor预测response的长度,然后将response长度差不多的放到一个micro-batch中,从而加速推理过程。对于预测偏离较大的情况,提出FCR(Failure Collection and Recomputation)机制,它将batch中最大预测长度作为新产生token数量的上限。如果超过,就会判定为失败,并在后面重计算。VBS(Variable Batch Size)让短的response的batch有更大的batch size。
S3:论文《S3: Increasing GPU Utilization during Generative Inference for Higher Throughput》中提出的方法全称Scheduling sequences with speculation。它是一个通过预测输出序列长度来优化吞吐,减少内存浪费的框架。文中指出像FasterTransformer会按最大的序列长度预留内存,导致内存的浪费,并限制batch size,降低吞吐。该方法预测输出的序列长度,并基于预测进行调度从而提高硬件利用率与吞吐。它包含三个部分:Predictor用于预测输出序列长度;Scheduler根据预测与HBM使用信息将batch派发到GPU计算文本生成(视作bin packing problem用decreasing first fit算法解决);Supervisor在后台运行,监控GPU利用率,可用HBM并将信息给scheduler。对于预测错误的情况。它会抢占那些实际生成序列超过预测值的case,为其增加内存并计算。
Orca:论文《Orca: A Distributed Serving System for Transformer-Based Generative Models》中提出的Orca首先研究了这个问题,并实现了iteration-level scheduling的机制。它在每次迭代后都会进行调度,选取要处理的request交给engine。当batch中有序列完成token的产生,就会将新的request放进来。另外,对于naive的batching,有三种情况不适用:都是prefill,但input token数量不一样;都是decode,但token index不一样;prefill与decode混合。因此,它提出selective batching,即选择性地对部分操作进行batching:对线性操作,直接处理;对Attention模块先按request切分,单独处理再合起来。
DeepSpeed-FastGen:论文《DeepSpeed-FastGen: High-throughput Text Generation for LLMs via MII and DeepSpeed-Inference》中的DeepSpeed-FastGen基于DeepSpeed-MII与DeepSpeed-Inference提供了高效易用的LLM serving系统。它采用了Dynamic SplitFuse技术,可以将prompt与generation阶段放到一起。比vLLM在吞吐与延迟上都有2倍多的提升。它观察到batch相对于token数量,对于latency影响很小。同时token-throughput是个凹函数。根据这些现象,Dynamic SplitFuse将长prompt切成小的chunk,短prompt进行合成,从而使得每次forward计算的batch size恒定。这样达到更好的响应,高效与低波动的目的。
TetriInfer:论文《Inference without Interference: Disaggregate LLM Inference for Mixed Downstream Workloads》指出现有系统忽略prefill与decode阶段的区别,导致它们相互影响。文中提出的TetriInfer将prompt切分成固定大小的chunk方便accelerator用满计算资源。同时它将prefill与decode分开,独立运行。另外,它使用两层的调度算法,考虑预测的资源使用,避免了decode scheduling hotspot。
DistServe:论文《DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving》指出现有系统为了latency需求,需要调整优先级,或者over-provision计算资源。DistServe将prefill与decoding阶段放到不同的GPU上,以避免它们相互影响,为每个阶段联合优化资源分配与并行策略。它的目标是提升goodput,即满足latency要求下的throughput,而非单一性能指标(TTFT或TPOP)。
Ring Attention: 论文《Ring Attention with Blockwise Transformers for Near-infinite Context》基于BPT(blockwise parallel transformer),将长序列划分成块,然后将块的计算分布到多个host上。这些host设备组成逻辑上的ring,每个device会将它的key-value块拷贝传到下一个device上,同时接收前一个device来的key-value块。只要块的计算时间长于传输时间,数据传输就可以被hide,不会增加额外的开销。
Infinite-LLM:论文《Infinite-LLM: Efficient LLM Service for Long Context with DistAttention and Distributed KVCache》中提出的DistAttention是一种分布式的attention算法。为了克服传统模型并行应用在attention上的资源利用率低的问题,DistAttention将传统的Attention切成更小的称为macro-attention的单元,以及对应的KV Cache(称为rBlock)。每个rBlock包含固定个数token对应的KV Cache以及元信息。每个LLM service instance有一个rBlock manager(称为rManager),负责监管本地的rBlocks。DistKV-LLM是一个基于该算法的分布式LLM推理系统,它可以调度跨数据中心的GPU与CPU内存。另外,它还提出一种称为DGFM的算法可以解决分布式KV Cche环境中的内存碎片的问题。
T3:论文《T3: Transparent Tracking & Triggering for Fine-grained Overlap of Compute & Collectives》中提出的的T3通过配置producer的输出地址空间,以一种“透明”的方式将producer操作与后面的通信操作融合起来。该方法还加了轻量级的track和trigger机制,调度producer的计算与通信。另外,它还将compute-enhanced memory用在通信计算上。
Centauri:论文《Centauri: Enabling Efficient Scheduling for Communication-Computation Overlap in Large Model Training via Communication Partitioning》指出现有系统中对于通信与计算overlap的优化采用fine-grained kernel fusion或有限操作调度的方式在异构训练环境中优化空间有限。因此,Centauri将通信切分,并用层次化的调度机制优化overlap。它将切分空间抽象成三个维度:primitive substitution, topology-aware group partitioning和workload partitioning。
FLUX:论文《FLUX: Fast Software-based Communication Overlap On GPUs Through Kernel Fusion》用于LLM在训练与推理时的计算与通信overlapping。在有TP的情况下,以往的工作切分比较粗粒度,并依赖于精巧的调度,不太适用于GPU。Flux(Fine-grained Communication Overlapping)可用于AllGather - GEMM,GEMM - ReduceScatter这样的pattern。与以往工作相比,它使用细粒度的切分,并将之融合成一个大的kernel。此外,它还结合了tile coordinate swizzling, GPU instruction selection, communicataion order selection等优化技术。实现上,它基于CUTLASS项目,使用auto-tuning选择transfer method及模板参数。
DeepSpeed Inference:论文《DeepSpeed Inference: Enabling Efficient Inference of Transformer Models at Unprecedented Scale》中提出的DeepSpeed Inference是一种支持单卡、多卡和异构的transformer模型推理解决方案。DeepSpeed Inference包含DeepSpeed Transfomer与ZeRO-Inference两个部分。前者为三层架构,包含单GPU transfomer kernel,多GPU dense transformer layer与多GPU sparse transformer layer。它通过Deep-Fusion算子融合和CUDA-Graph来减少访存和kernel launch开销。对于多GPU场景,它使用TP, PP并行方式。后是基于GPU+CPU+NVMe的异构方案,支持多种配置,如dense or sparse(MoE), small or lage batches, billions to trilliions参数级别,单GPU或多GPU。为了减少减少从DRAM或NVMe拿模型权重的开销,它采用了Prefetching与Multi-GPU PCI-e bandwidth utilization技术进行优化。相比GPU-only的方案,它所能支持的模型大25x,并达到50%以上的峰值性能。
FlexGen:论文《FlexGen: High-Throughput Generative Inference of Large Language Models with a Single GPU》中提出的FlexGen是面向高吞吐批处理的LLM推理框架。它整合了GPU,CPU和磁盘的存储和计算资源,并调度I/O操作使之更加高效,从而实现高吞吐。再加上压缩方法(group-wise quantization和sparse attention)与分布式pipeline并行。它将offloading stragey的优化问题建模为graph traversal problem,定义offloading strategy的搜索空间,它考虑computation schedule, tensor placement和computation delegation,然后构建解析的cost model,并通过线性规划方法找到解。
LLM in a flash:论文《LLM in a flash: Efficient Large Language Model Inference with Limited Memory》中提出的方法将模型参数放在flash memory中,然后按需放入DRAM。它引入cost model来为数据传输优化提供指导。利用稀疏性选择性地从flash memory只加载那些输入非零或者预测输出非零的相关参数。减少数据加载和内存使用效率使用了两个技术:windowing和row-column bundling。前者只加载和临时缓存最近token的;后者将up-projection和down-project层的行与列一起存放,有利于提高吞吐。
PowerInfer:论文《PowerInfer: Fast Large Language Model Serving with a Consumer-grade GPU》中提出的PowerInfer是一种GPU-CPU混合推理引擎。网络中一小部分神经元,称为hot neuron几乎会被所有的输入激活。而大部分则为cold neuron,只在特定输入时被激活。Hot neuron会被预加载到GPU,而cold neuron在CPU上计算。这样减少了GPU的内存需求和CPU-GPU的数据传输。PowerInfer还引入adaptive predictor和neuron-aware sparse operator提升计算效率。
Hugging Face Accelerate:支持offload一部分权重。它使用PyTorch中的hooks机制,在forward pass的开始前将CPU或者disk上的权重加载到GPU上,结束后再将之放回原地。
GPTQ:论文《GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers》中的GPTQ方法是一种基于OBQ(Optimal Brain Quantization)方法(使用了二阶信息)的权重的PTQ量化方法。OBQ方法采用layer-wise的方式,对每层权重,独立处理每一行。每次量化一个权重,然后更新其它权重以弥补该权重量化带来的误差。本文为了将之用于LLM,提出了几项改进:Arbitrary Order Insight,Lazy Batch-Update, Cholesky Reformulation。经过改进后,它可用于LLM(如OPT-175B,BLOOM-176B)的近于无损的4-bit量化,使得用单张GPU跑LLM成为可能。缺点是由于硬件不支持混合精度(FP16 x INT4),难以加速。
ZeroQuant:论文《ZeroQuant: Efficient and Affordable Post-Training Quantization for Large-Scale Transformers》提出的ZeroQuant是用于INT8和INT4/INT8混合精度量化的end-to-end的PTQ和推理pipeline,可用于weight与activation。它采用的fine-grained hardware-friendly quantization scheme主要包含group-wise weight quantization与token-wise quantization for activation两项技术。前者将weight矩阵分成若干group,然后对每个group单独量化。同时考虑了GPU上的硬件约束。后者动态地计算每个token的范围,从而减少量化误差。为了减少额外操作带来的开销,它采用kernel fusion将量化算子与前面的算子(如LayerNorm,bias-ad, GeLU)融合。此外,它引入了CUTLASS的INT8 GEMM实现对量化模型进行加速。
ZeroQuant-V2:论文《ZeroQuant-V2: Exploring Post-training Quantization in LLMs from Comprehensive Study to Low Rank Compensation》对round-to-nearest (RTN),GPTQ,ZeroQuant等PTQ方法分别研究了weight-only,activation-only和weight-and-activation下的效果。基于结果,它观察到当前的方法均无法在INT4-weight或W4A8下达到原模型质量,于是提出了Low-Rank compensation (LoRC)方法,使用低轶分解来近似量化误差矩阵的。该方法以少量的model size与计算量增长为代价提升量化后的准确率。
ZeroQuant-FP:论文《ZeroQuant-FP: A Leap Forward in LLMs Post-Training W4A8 Quantization Using Floating-Point Formats》基于H100 GPU引入的FP8和FP4格式,将W4A8的PTQ应用于LLM。
LLM.int8:论文《LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale》中的LLM.int8引入mixed-precision decomposition,它对矩阵相乘中的每个内积用单独的normalization constoant进行量化,对于outlier,它使用FP16精度,而其它的以8-bit相乘。缺点是在加速硬件上较难高效实现。
OdysseyLLM:论文《A Speed Odyssey for Deployable Quantization of LLMs》是考虑硬件加速的W4A8解决方案。它包含Symmetric learnable weight clipping(LWC),iterative Hessian-based compensation,和用于W4A8的kernel实现(FastGEMM)。在混合精度GEMM中,它使用了Kernel fusion(现代GPU只支持同类型的GEMM计算,因此将SINT4toS8与GEMM融合进一个kernel),Removal of INT8 subtraction(现在GPU没有signed 8-bit整数的减法,因此使用对称量化)和Reusing the sign bit(优化int4到int8转换的开销)技术。
RPTQ:论文《RPTQ: Reorder-based Post-training Quantization for Large Language Models》指出LLM量化activation的挑战除了outlier外,还在于不同channel的范围差异很大。因此它将channel重新排列,并按cluster进行量化。不同cluster内使用不同的量化参数。同时为了减少reoreder的开销,它将reorder操作融入layer norm和linear layer。RPTQ对LLM的activation进行3-bit的量化。
SmoothQuant:论文《SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models》提出的SmoothQuant方法是一个training-free, accuracy-preserving的通用PTQ方法。它可用于LLM的W8A8(8位权重,8位activation)量化。主要应用于LLM中的GEMM。基于权重比activation更少outlier,因此也更容易量化的事实,SmoothQuant通过一个数学上的等价变换以离线方式将activation的困难转移到weight上。它让输入activatino除以一个per-channel smoothing factor,同时权重乘以相同的系数,就可以保证结果不变。
AWQ:论文《AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration》中的AWQ(Activation-aware Weight Quantization)方法是一种对硬件友好的,用于LLM中low-bit weight-only量化的方法。它基于权重不是同等重要的观察,即保护很小部分(0.1%-1%)的主要权重可以有效减少量化误差。它通过在calibration set中activation的值来判断是否为主要权重,即对应绝对值较大的activation的权重更重要。 通过分析得出将salient channel的值放大可以减少相对量化误差,因此它设计了一种per-channel scaling方法自动找寻最优的scaling来最小化量化误差。AWQ可使LLM被部署于desktop与mobile GPU。
SparseGPT:论文《SparseGPT: Massive Language Models Can Be Accurately Pruned in One-Shot》是一种Post-training pruning方法。它指出大的模型更易被压缩,GPT系的模型参数至少可被裁减一半,而不需要retraining,且精度损失很少。传统的pruning方法,如AdaPrune,耗时很长(175B Transformers需要数百小时)。SparseGPT可用于GPT系模型,如将OPT-175B和BLOOM-176B在4.5小时内达到60%的unstructured sparsity,且准确率与perplexity损失很小。它基于mask selection + weight reconstruction的范式,并通过Fast approximation reconstruction(优化Hessian矩阵计算)adaptive mask selection(使用iterative blocking)提高了效率。它还可适用于semi-structured pattern(n:m sparsity format),比如结合Ampere NV GPU中的2:4 sparsity。
LLM-Pruner:论文《LLM-Pruner: On the Structural Pruning of Large Language Models》提出的LLM-Pruner是一种structural pruning方法,它基于梯度信息选择性地删除一些不重要的结构。可以做到task-agnostic,并不依赖原始训练数据集。之后用LoRA可以用少量数据快速恢复准确率。
DeJavu:论文《Deja Vu: Contextual Sparsity for Efficient LLMs at Inference Time》中提出的Contextual sparsity定义为attention head与MLP参数的子集。对于给定的输入,它可以获得与dense model相似的输出。DeJa Vu是一个使用low-cost算法对于每layer的指定输入预测contextual sparsity的系统。另外它设计了asynchronous predictor减少相关开销。
Flash-LLM: 论文《Flash-LLM: Enabling Cost-Effective and Highly-Efficient Large Generative Model Inference with Unstructured Sparsity》指出产生式模型推理的性能瓶颈在于skinny matrix multiplication,因为它无法用Tensor Cores。Unstructured pruning往往比structured pruning有更高的准确率,但unstructured sparse MatMul(SpMM)无法利用tensor core,现有的unstructured SpMM实现(如cuSPARSE, Sputnik)除非sparsity达到很高(98%,86%)才能胜过cuBLAS。文中提出的Flash-LLM是一个高效的GPU库用于大型生成模型推理,它支持tensor core上unstructured sparsity。它的核心是采用Load-as-Sparse and Compute-as-Dense方法用于unstructured sparse matrix multiplication(SpMM)。
Sheared LLAMA: 论文《Sheared LLaMA: Accelerating Language Model Pre-training via Structured Pruning》中提出的Sheared LLaMA是一种Structured pruning方法,它主要采用两个技术:1) Targeted structured pruning:它在不同粒度为模型参数学习mask,该mask与模型参数以min-max目标函数被联合优化。该mask决定了对应的子结构是否被裁剪。得到该裁剪后的目标结构后,通过continuing pre-training该裁剪后的网络提升表现。2) Dynamic batch loading:观察到pruning会相对保留那些专用(low-entry)领域的知识。因此将预测loss作为参考,然后在训练过程中根据loss与参考值的差距更新各domain的权重,再根据该权重来采样训练数据。
LoRA:论文《LoRA: Low-Rank Adaptation of Large Language Models》指出大模型动不动就是成百上千GPU训练几周甚至几月。因此对于很多任务会选择fine-tuning,而不是重头训练。于是就诞生了Parameter-Efficient Fine-Tuning (PEFT)方法,研究如何高效的做fine-tuning。这类方法中近两年比较火的就是LoRA(Low-Rank Adaption)。以往研究发现那些巨量参数模型其实都存在在低维度上,因此在为downstream task训练时会在Transfomer模型的每层的dense layer插入可训练的rank decomposition矩阵(即low-rank矩阵)。这样,权重可写成
W
=
W
0
+
B
A
W=W_0 + BA
W=W0+BA。在fine-tuning时,pre-trained model权重不变,只训练那插入的low-rank矩阵。实验分析发现这个增量会为特定的downstream任务放大那些重要的但在pre-training过程中没有被强调的feature。它能使可训练参数减少万倍,GPU memory需求减少3倍。
LORD(Low Rank Decomposition):论文《LORD: Low Rank Decomposition Of Monolingual Code LLMs For One-Shot Compression》中使用Low Rank Decomposition(LoRD)方法来减少模型size。SVD可以用来生成r-rank的近似矩阵
W
=
U
S
V
T
W=USV^T
W=USVT。对于对称矩阵可以用特征值分解
W
=
Q
Λ
Q
T
W=Q \Lambda Q^T
W=QΛQT。但是,SVD没有考虑输入与输出数据的分布,同时计算还非常费时。LORD利用activation是low-ranked的特点,使用Atomic Feature Mimicking(AFM)方法,基于小量calibration数据产生low-rank矩阵。该方法可应用在像CodeGen和StarCoder这样的代码生成模型上。 TensorGPT:论文《TensorGPT: Efficient Compression of the Embedding Layer in LLMs based on the Tensor-Train Decomposition》将LLM模型中Embedding Layer(在GPT-2中占31.02%的参数)压缩成low-rank的张量格式(MPS)。它基于TTD(Tensor-Train Decomposition)方法,其最常见的形式是MPS(Matrix Product State)。它使用TT-SVD(Tensor-Train Singular Value Decomposition)算法将一个大型的N阶张量分解成N个2阶或3阶的张量(称为core tensor)。基于该方法,TensorGPT将embedding矩阵中的每个token embedding生成MPS(Matrix Product State)。该格式可被分布式计算。GPT-2中embedding layer可在准确率不受影响的前提下压缩3.31x倍。
QA-LoRA: 论文《Quantization-Aware Low-Rank Adaptation of Large Language Models》中提出QA-LoRA(quantization-aware low-rank adaption)算法。它关注量化和adaption自由度的不均衡问题,即权重矩阵的每一列只有一对量化参数,但有很多LoRA参数。针对该问题,它使用group-wise operators一方面让每组单独量化从而增加量化的自由度,另一方面,组内共享LoRA参数从而减少adaption自由度。它为LoRA增加了两种能力:在fine-tuning阶段,LLM权重量化成INT4。在fine-tuning后,LLM和附加的权重被整合进量化模型,而没有准确率损失。
MiniLM:论文《MiniLM: Deep Self-Attention Distillation for Task-Agnostic Compression of Pre-Trained Transformers》中提出的MiniLM方法让Student model通过训练模仿teacher model中的self-attention module。它还使用了Teature assistant技术,即先将teature model distill到teacher assistant(它与teacher model的layer num一样,与student model的hidden size一样)中,再将之作为teacher model训练student model。
Distilling step-by-step:论文《Distilling Step-by-Step! Outperforming Larger Language Models with Less Training Data and Smaller Model Sizes》中提出的Distilling step-by-step范式是一种可以用更少训练数据训练task-specific的小模型。它的主要思想是利用LLM的推理能力以更加data-effient的方式训练更小的模型。其过程分两步:首先给LLM未标注的数据,再通过CoT(Chain-of-Thought)让其生成结果以及相应的rationales(以自然语言描述的对最终输出标签的解释)。然后,利用这些rationals连同标签一起作为小模型的输入进行训练。这些rationals能够提供更丰富更细节的信息,因此可以使小模型的训练更高效。
Others
业界还有一些从其它角度进行优化的工作,比如:
FastServe:大多数工作的目标是提高吞吐,但在一些推理场景中latency很重要。论文《Fast Distributed Inference Serving for Large Language Models》中的FastServe挖掘LLM推理中的auto-regressive模式,让其能以output token为粒度抢占。它使用可抢占调度来最小化JCT。
LongLLMLingua:论文《LongLLMLingua: Accelerating and Enhancing LLMs in Long Context Scenarios via Prompt Compression》指出LLM推理的表现决定于输入prompt中关键信息的密度与位置。它提出的LongLLMLingua基于LLMLingua框架,是一种应用于长上下文的prompt compression方法。首先,它使用一些小的语言模型,如GPT2-small或者LLaMA-7B从prompt中识别和删除一些不重要的token。然后,再用LLM对压缩后的prompt进行推理。为了有效地进行prompt压缩,关键信息密度,它使用了question-aware coarse-to-fine压缩方法,document reordering机制,dynamic compression ratio,post-compression subsequence recovery策略等技术。
EcoOptiGen:超参数对于框架性能的重要性不言而喻。但通常系统中的超参很多且相互影响,这给超参数的确定带来了很大的难度。很多时候人们会通过经验或者一些规则来确定它们,代价是会让性能打一些折扣。论文《Cost-Effective Hyperparameter Optimization for Large Language Model Generation Inference》中的EcoOptiGen框架使用超参数优化和cost-based pruning提升token generation的性能。它着眼于优化LLM中的一些超参数,比如number of responses,temperature(控制生成文本的随机性),max token(output中最多生成token数量),stop(使token产生停止的字符串列表)等。考虑到这些参数间的相互影响,文中方法对它们进行联合优化。它使用黑盒优化方法BlendSearch。该方法结合了Bayesian optimization和local search。前者用于产生后者的起始点,后者会在保证收敛速度和开销上界的前提下进行随机方向的搜索。