[Paper Reading] LoongServe Efficiently Serving Long-context Large Language Models with Elastic Sequence Parallelism
Paper Source: LoongServe Efficiently Serving Long-context Large Language Models with Elastic Sequence Parallelism
Background
LLM推理过程[^1]
-
模型参数加载到GPU
-
在CPU上对prompt分词(tokenizing),并将token tensor传输到GPU
-
输入token到Transformer,生成第一个token
-
将生成的token附加到输入token序列中,将其作为生成第二个token的新输入。然后,重复此过程,直到生成了停止符(EOS,end-of-sequence)或达到最大序列长度
- 将完成的 tokens 从 GPU 获取到 CPU ,并对它们进行 detokenize(”detokenize“指的是将模型生成的 tokens 序列转换回原始文本或句子的过程。可能包括去除 tokens 之间的空格、添加标点符号、还原缩写等操作,以还原生成文本的自然语言形式。),以获取生成的文本。
Transformer LLM 的推理过程分为两个阶段,将1-3称作预填充阶段(pre-fill phase)
将4称生成阶段(generation phase)、解码阶段(decoding phase)、自回归阶段(auto-regressive phase)、增量阶段(incremental phase)。
KV Cache[^2]
为方便起见,下面将token的上下文表征(contextual representation)称作token
由于Transformer在Decoder使用了Mask技术,在生成新token时,只能使用之前已生成的token信息。而之前的token在每次迭代中都是相同的,所以当前新生成的token在随后的所有迭代也是相同的,因此存在
冗余计算。
举个🌰,假设在解码阶段新一次迭代,使用了 What color is the sky? The sky
作为输入序列生成了is
,在上一次迭代中, sky
是输入序列最后一个token,因此与该token上下文表征是通过使用序列中所有token的表征生成的,
即What
,color
,is
,the
,sky
,?
,The
.sky
的key、value向量,
下一次迭代输入序列将是What color is the sky? The sky is
,
但由于做了Mask,从sky
角度讲,输入序列仍然是What color is the sky? The sky
,
因此,sky
生成的输出向量与上一次迭代完全相同。
同时,唯一尚未计算的是输入序列中最后一个token is
的上下文表征,为此需要得到:
is
的query向量What color is the sky? The sky is
的key向量What color is the sky? The sky is
的value向量
对于key和value向量,除了is
外,都已经在之前迭代中计算过了,因此可以将其缓存下来,也即KV Cache。
那么,为is
计算输出向量将会变得非常简单:
- 计算
is
的query、key、value向量 - 从缓存中获取
What color is the sky? The sky
的key和value向量,并与is
的key和value向量连接 - 使用
is
的query向量和所有key向量计算attention score - 使用attention score和所有value向量计算
is
的输出向量
当我们使用 KV Cache 时,模型输入就不是整个序列,而是最后生成的 token 和 KV Cache
Pre-fill Phase
将输入的prompts得到q、k、v,存入KV Cache(为Decode阶段缓存)。
这一阶段需要将当前输入序列的KV一次性全部计算出来,因此需要大量计算资源。
Decode Phase
由新生成的token得到q、k、v,计算它与之前所有token的attention。
这一阶段需要从KV Cache中读取前面所有token的Key和Value,因此需要占用大量内存资源。
Challenges
- LLM推理所需要的计算资源及GPU显存占用随着不同请求(输入序列)上下文长度的不同而有很大差异
- 即使对于单一请求而言,其在Prefill和Decode两个阶段所需的资源也有很大差异。
Main Idea
文章提出一种新的并行策略 Elastic Sequence Parallelism
,并构建了一个分布式LLM LoongServe
以充分释放ESP的潜力。
LoongServe
由一组实例及一个 global manager
组成。global manager
可以动态将这些实例组织成一个个并行组并动态调整各并行组大小,每组并行处理请求。
Global manager
以 iteration 为粒度动态地调度请求、调整 ESP 组和管理分布式 KV Cache 缓存池。
Elastic Sequence Parallelism(ESP)
Prefill Phase
- 划分输入序列给一个并行组的实例
- 各实例在本地同时计算得到各自分得token的Q、K、V,计算局部attention并把所得KV存储到本机
- 各实例将自己的KV传递给相邻实例,直到各实例的Q与全部KV均进行了attention运算,而后得到本层输出后输入到下一层……
这样做使得模型支持的上下文长度上限由单机提升到多机,同时,由于 KV Cache 块在组内机器上循环传递,为下文 Prefill 阶段的 Scale down 时降低 KV Cache 迁移开销提供机会(做到“zero-cost”)
Decode Phase
在Prefill阶段,并行组的各实例分别存储了部分KV。
- 指定组内一个实例作为master,负责计算新生成token的q和kv,保存kv到本机KV Cache中并计算局部attention
- master将1.中得到的q发送给所有slave,各slave并行计算局部attention并将结果返回给master
- master将结果reduce后做后续的FFN计算……
这种方法只要master有足够的显存存储新生成token的KV就能一直迭代下去。
当master显存不足时,则另外指定组内实例为新的master或对当前并行组做scale up并指定新实例作为master。因此文章中称分布式attention计算方式为 multi-master distributed decoding
。
Scale up & Scale down
组内的计算需求下降时,例如由 prefill 阶段切换到 decode 阶段,可以进行 scale down,降低 DoP(degree of parallelism)。此时,需要将 KV Cache 集中到少数的实例。由于 prefill 阶段的 sequence parallelism 机制,kv 会在组内传递,实例只需要选择性地保存一部分 kv,这部分KV Cache迁移与传递并计算attention重叠,因此说是zero cost。
举个🌰,如下图所示,要将实例 1-3 组成的 并行组scale down为实例 1-2 时,若将 kv1-4 保存在实例 1,kv5-6 保存在实例 2,实例 1 只需要在组间传递 kv 的时候选择保存 kv2,实例 2 只需要选择保存 kv6。
组内的计算或者显存需求上升时,例如随着 decode,可以进行 scale up。此时,需要使新加入的实例可以参与并行计算。由于采用前面提到的 multi-master distributed decoding 机制,只要单个实例有足够的内存来存储新生成的键值张量,就可以通过指定它为 Master 来跨多个实例进行处理。当扩展并行组时,global manager 只需要将新实例添加到 parallel group 中,而不需要迁移现有的KV Cache。
Reference
[^1]: LLM Inference Series: 2. The two-phase process behind LLMs’ responses | by Pierre Lienhart | Medium
[^2]: LLM Inference Series: 3. KV caching explained | by Pierre Lienhart | Medium