LLM大模型系列(十):深度解析 Prefill-Decode 分离式部署架构
〔更多精彩AI内容,尽在 「魔方AI空间」 ,引领AIGC科技时代〕
本文作者:猫先生
在上一篇文章中,我们介绍了NVIDIA 发布的Dynamo框架及其PD分离式部署技术,旨在优化大语言模型(LLM)推理过程中的资源利用和推理效率。
《大模型系列:NVIDIA Dynamo框架详解——PD分离式部署技术解析》
Dynamo的PD分离式部署技术通过优化资源分配和推理流程,显著提升了LLM推理的效率和资源利用率,有望成为未来AI推理服务的重要架构。
那么,本文将深度解析 Prefill-Decode 分离式部署架构的原理!!
我们开始吧!!
一、什么是Prefill-Decode分离架构
预填充-解码阶段分离(Prefill-Decoding Disaggregation, PDD)是一种用于处理长上下文大型语言模型(LLMs)的方法,旨在通过将推理过程分为两个主要阶段——预填充(Prefill)和解码(Decoding),这两个阶段被拆分到不同的 GPU 实例上独立运行。如下图所示,DistServe论文中的架构图。
预填充阶段(Prefill Phase)
-
目标:预填充阶段的主要目标是处理输入序列的所有输入token,以构建键值缓存(KV Cache)。这个缓存用于存储中间计算结果,以便在后续的解码阶段重用。
-
特点:预填充阶段通常是计算密集型的,因为它需要处理整个输入序列,并生成初始的输出标记。由于注意力机制的计算复杂度与输入序列长度的平方成正比,因此长序列的处理需要更多的计算资源。
解码阶段(Decoding Phase)
-
目标:解码阶段的任务是基于预填充阶段构建的键值缓存,逐个生成输出token。由于每个新生成的token只需要计算与之相关的键值缓存,因此解码阶段的计算负载相对较轻。
-
特点:解码阶段通常需要较少的计算资源,但仍然需要频繁访问键值缓存。为了减少干扰,PDD将解码阶段与预填充阶段分离到不同的GPU组。
二、为什么LLM推理分成两个阶段:Prefill 和 Decode?
要想回答这个“为什么”,我们需要首先搞懂 prefill 阶段的内部机制,attention 的计算细节、KV Cache 是如何初始化的、为什么 prefill 计算量这么大。
在传统集成式推理流水线中,LLM的Prefill和Decode阶段往往被置于同一GPU上运行,导致资源需求不匹配,资源利用率不高。例如,当用户请求的Prefill长度和Decode长度非常不匹配时,同一GPU需要同时处理高算力需求和高内存带宽需求的任务,难以发挥最佳性能。
一句话简单理解:LLM生成文本的过程本质上是给定上下文,逐词预测下一个词。但在实现上,这个过程被明确地分成两个阶段:
阶段 | 资源需求特性 | 计算模式 | 显存占用模式 | 目的 |
---|---|---|---|---|
Prefill | 计算密集型 | 高并行度,矩阵乘法为主 | 低,固定规模 | 模型读取并“理解”你输入的所有上下文 |
Decode | 内存密集型 | 顺序生成,访存为主 | 随上下文增长指数级上升 | 模型基于已有信息逐步生成回复 |
Prefill 是用户输入完 prompt 到生成首个 token 的过程,Decode 则为生成首个 token 到推理停止的过程。
那么,这样我们就很好理解,
为什么不能一个阶段,而必须拆分成两个阶段进行:
-
输入 prompt 是完整的、一次性提供的,适合并行计算。
-
输出 token 是未知的,只能一个一个推理,必须串行。
在Prefill阶段,大模型一次性对prompt中所有token进行计算QKV,由于不同token的计算是独立的,因此该过程可以并行。在Attention部分,计算得到的QKV进一步计算出Output矩阵,再经过后续的FFN层和解码得到首字母token。
在Decode阶段,计算原理和 Prefill 完全相同,但计算方式却不能一样。原因有两个:
第一:随着序列长度的增加,Attention 计算复杂度平方级增长,直接计算代价很大,导致长序列的推理时间极慢,甚至不可行。
第二:对Decode阶段的计算过程简单分析发现,该过程可以复用 Prefill 阶段的KV结果,也可以复用Decode阶段已经产生的KV结果。
综上,可以把已产生的KV存起来,不必重新计算,这就是KV Cache。对于Q矩阵,每次需要计算的只是Q的最后一行q,计算关于qKV的attention,而不是关于QKV的attention,这样复杂度降低了一个量级,实现以存换算。
三、Prefill 内部运行机制
Prefill 阶段是语言模型推理中的第一个步骤,它负责处理你输入的所有上下文内容(prompt),为后续生成打下基础。
比如你问模型一句话:
“请解释一下 Transformer 的原理。”
这句话会被 tokenizer 编码为一串 token,比如 ["请", "解释", "一下", "Trans", "##former", "的", "原理", "。"]
。
然后这些 token 会进入 Transformer 模型进行前向传播。想要更详细了解Transformer的运行原理,可以参考这篇文章《新手必看 | 44张图带您极简学习Transformer | 分步数学示例(建议收藏)》
重点来了 👇
Prefill 中模型内部到底发生了什么?
Step 1:Embedding 输入
-
每个 token 会映射成一个向量(embedding),形状为
[batch_size, seq_len, hidden_dim]
Step 2:Self-Attention 的全量计算
-
输入是完整的上下文,因此模型会执行一次完整的 masked self-attention。对于位置 i 的 token,会计算它和前面所有位置的注意力(包括自己):
Step 3:生成 KV Cache
-
每层 Transformer 都会把每个 token 的 K 和 V 存下来,形成 KV Cache:
KV Cache = [K₁, K₂, ..., Kₙ], [V₁, V₂, ..., Vₙ]
-
这个 Cache 会在 decode 阶段被反复使用,避免重复计算。
四、为什么 prefill 的计算成本那么高?
让我们做个简单对比:
Prefill
Decode(单步)
处理 token 数
全部 prompt(如几百)
1 个
Attention 计算
全 attention matrix
只看已有 KV
是否可并行
✅ 是
❌ 否(必须串行)
计算资源
重
轻
Prefill 最大的特点是:
-
需要 “每个 token 与前面所有 token 做 attention”
-
不能复用 KV Cache(因为是第一次建立)
Prefill 是典型的 compute-bound 阶段:
-
-
大量矩阵乘法和 attention 计算主导性能瓶颈
-
GPU 的算力利用率很高,但内存带宽压力较小
因此如果你的 prompt 很长,Prefill 阶段就会非常耗时。很多模型响应慢,不是生成慢,而是 prompt 处理慢。
五、Decode:token-by-token 地生成输出
在 prefill 之后,模型已经建立了一个完整的 KV Cache,可以开始逐步生成 token。
每次 decode 只需要:
-
把最新生成的 token 输入进去
-
拿之前的 KV Cache 来做 attention
-
预测下一个 token
Decode 是典型的 memory-bound 阶段:
-
每生成一个 token,都需要访问所有历史的 KV Cache(多层、多头)
-
计算量小,但内存带宽压力大。
-
特别在 batch size 小、生成序列长的场景,GPU 利用率会很低。
六、Prefill vs Decode 的性能瓶颈差异
由于Prefill、Decode这两个阶段的输入特性和计算方式本质不同,所以将其拆分成两个阶段是为了精准优化每一步的计算路径,比如:
-
Prefill 可用 FlashAttention 等并行技术提升性能
-
Decode 可用 KV Cache、speculative decoding 等加速生成
在推理过程中,Prefill 和 Decode 阶段不仅在结构上不同,在性能瓶颈上也大相径庭:
阶段 | 特点 | 性能瓶颈 | 原因 |
---|---|---|---|
Prefill | 一次处理整个输入序列 | Compute-bound | 多 token 并行计算,Attention + MLP 计算密集 |
Decode | 每次生成一个 token,逐步执行 | Bandwidth-bound | 每次要读取大量 KV Cache,但计算量小,等数据成为瓶颈 |
为什么 Decode 会是 Bandwidth-bound?
在 Decode 阶段,虽然只生成一个新 token,但为了计算它的注意力得分,需要加载 全部历史 token 的 KV Cache。这意味着:
-
每层都要从 GPU 内存中读取大量数据;
-
实际计算(比如 Q × K^T)规模却很小;
-
导致 GPU 大量时间都在等内存传输,而不是在计算。
这就是典型的 Bandwidth-bound 场景 —— 内存带宽成为限制性能的关键因素,而不是算力本身。
类型 | 具体含义 | 常见表现 |
---|---|---|
Compute-bound | 受限于计算单元(ALU、CUDA 核心等) | GPU 计算占满 |
Bandwidth-bound | 受限于 访问速度:内存太慢,等数据成为瓶颈 | GPU 闲着在等内存 |
Memory-bound | 受限于 内存容量,模型或缓存太大放不下 | OOM / 频繁调度数据 |
七、PD分离原理
通过以上内容的分析,我们就能够很容易的理解PD分离式部署的原理了。简单来说,将Prefill(预填充)和Decode(解码)这两个推理阶段分开处理的技术,通常适用于对时延有严格要求的场景。
将Prefill实例和Decode实例分开部署,减少Prefill阶段和Decode阶段分时复用在时延上造成的互相干扰,实现同等时延下,提升吞吐量。
PD分离工作原理如下图所示。
PD分离部署的优势:
-
资源利用优化:由于Prefill阶段计算密集,而Decode阶段计算较为稀疏,将这两个阶段分离可以更好的利用GPU的计算资源。
-
提高吞吐量:分离后的Prefill和Decode可以同时处理不同的请求,这意味着在Prefill阶段处理新请求的同时,Decode阶段可以继续处理之前请求的解码任务,从而提高了整体的处理能力。
-
降低延迟:由于Prefill和Decode分别在不同的阶段进行,可以减少等待时间,特别是当有多个请求并发到达时。
八、追溯PD分离技术
(一)论文《SARATHI: Efficient LLM Inference by Piggybacking Decodes with Chunked Prefills》
时间:2023.8
提出了SARATHI技术来解决LLM推理效率低下的问题。
随着语言模型的规模不断扩大,推理所需的GPU计算资源显著增加,尤其是在小批量情况下,解码阶段的计算利用率较低,导致整体推理效率低下。
通过改进预填充(prefill)和解码(decode)阶段的调度策略来提高LLM推理的效率。具体来说,SARATHI通过使用分块预填充和最大解码批处理来解决这些问题。
-
分块预填充(Chunked-prefills):
-
将一个预填充请求分割成多个等大小的块,以最大化GPU的计算利用率。
-
通过分割预填充请求,可以在单个预填充请求中构建多个解码最大批次,从而提高解码的覆盖范围。
-
-
最大解码批处理(Decode-maximal batching):
-
使用单个预填充块构建一个批次,并用解码请求填充剩余的槽位。
-
这种混合批处理提供了既计算饱和又均匀的工作单元,解决了低效解码和管道气泡的问题。
-
(二)论文《DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving》
时间:2024.1月
https://github.com/LLMServe/DistServe
提出DistServe,一种通过解耦预填充和解码计算来优化LLM服务性能的系统。
现有系统将预填充和解码阶段合并处理,导致强烈的预填充-解码干扰和资源分配与并行计划的耦合;不同应用对每个阶段的延迟要求不同,如实时聊天机器人强调低首次token时间(TTFT),而文档摘要则强调低每个输出token的耗时(TPOT)。
相关工作:该问题的研究相关工作有:vLLM和DeepSpeed-MII等系统采用了批处理和模型并行策略来提高整体系统吞吐量,但这些方法未能有效解决预填充和解码阶段的干扰问题。
DistServe将预填充和解码阶段的计算分配到不同的GPU上,从而消除预填充-解码干扰。预填充阶段处理用户提示以生成响应的第一个token,而解码阶段则逐步生成后续token。
(三)论文《LoongServe: Efficiently Serving Long-Context Large Language Models with Elastic Sequence Parallelism》
时间:2024.4月
https://github.com/LoongServe/LoongServe
提出LoongServe系统,通过弹性序列并行性(ESP)来高效地服务长上下文LLMs。
大语言模型的上下文窗口迅速增加,导致不同请求和同一请求的不同阶段之间的资源使用差异巨大。现有的静态并行策略无法有效利用底层资源来处理可变长度的请求。
弹性序列并行性(ESP),以适应不同请求和阶段的动态变化。基于ESP,设计了LoongServe系统,旨在提高计算效率、通信效率和GPU内存效率。
ESP动态调整每个迭代的并行度(Degree of Parallelism, DoP),以适应不同请求和阶段的资源需求。在预填充阶段,ESP可以设置较高的DoP以快速处理请求;在解码阶段,ESP可以降低DoP以减少通信开销并释放资源。
(四)论文《Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving》
时间:2024.6月
https://github.com/kvcache-ai/Mooncake
https://github.com/vllm-project/vllm/pull/10502
Mooncake,一种以KVCache为中心的分散化架构,用于大语言模型(LLM)的推理服务。
这篇文章要解决的问题是如何在LLM服务中,特别是处理长上下文和过载场景时,提高整体有效吞吐量并满足延迟相关的服务水平目标(SLOs)。
该问题的研究难点包括:如何在过载场景下预测未来的负载并提前拒绝某些请求以节省计算资源;如何有效地分离预填充和解码阶段以提高缓存利用率;如何在保证延迟要求的前提下最大化吞吐量。
该问题的研究相关工作有:Orca使用迭代级调度以实现各阶段的并发处理;vLLM利用动态KV缓存管理优化内存;FlexGen、SARATHI和FastServe结合创新的调度和交换策略以有效分配工作负载。此外,Splitwise提出了分离预填充和解码阶段的分解架构,DistServe优化了每阶段的资源分配和并行策略,TetraInfer结合了分块预填充和两级分解以及预测的两级调度算法。
(五)论文《Speculative Prefill: Turbocharging TTFT with Lightweight and Training-Free Token Importance Estimation》
时间:2025.2.5日
SPECPREFILL的框架,旨在通过轻量级和无需训练的标记重要性估计来加速大语言模型(LLM)的推理时间。
这篇文章的研究背景是提高时间到第一个标记(TTFT)在现代大型语言模型(LLM)推理引擎中至关重要。优化TTFT可以直接提高最大每秒查询数(QPS),满足许多关键应用的需求。然而,提升TTFT极具挑战性,因为它是计算受限的,并且性能瓶颈从自注意力转移到了多层感知机(MLP)部分。
预填充阶段主要是计算受限的,且瓶颈可能会随着提示长度和批量大小的变化而变化;直接优化TTFT会导致自注意力部分向MLP部分转移,从而增加计算复杂度。
(六)论文《LServe: Efficient Long-sequence LLM Serving with Unified Sparse Attention》
时间:2025.2.20日
LServe的系统,旨在通过混合稀疏注意力机制来高效地服务长序列大型语言模型(LLMs)。该系统通过统一块稀疏注意力框架来加速长序列LLM的预填充和解码阶段。
背景:
-
长序列LLMs在处理复杂任务时表现出色,但其在预填充和解码阶段的效率问题仍然存在。预填充阶段的注意力计算复杂度为二次,而解码阶段的内存占用较大。
-
现有的加速方法主要集中在KV缓存的量化或静态稀疏注意力上,但这些方法在保持长上下文能力方面存在不足。
LServe系统:
-
LServe通过引入混合稀疏注意力机制来解决这些问题。它将不同的硬件友好的结构化稀疏模式统一到一个框架中,通过在块级别跳过不重要的计算来加速注意力计算。
-
在预填充阶段,LServe将一半的注意力头转换为几乎免费的流式头,并在解码阶段使用查询为中心的动态稀疏性来优化KV缓存。
实验表明,LServe在预填充阶段比现有的vLLM系统快2.9倍,在解码阶段平均快1.3到2.1倍,同时保持了长上下文的准确性。
九、vLLM中的PD分离架构
vLLM的PD分离架构主要由三个组件构成:Proxy API server、vLLM prefill和vLLM decode。以下是它们的工作原理:
1️⃣ 当请求到来时,首先会进入Proxy API server。Proxy API server会将请求转发给vLLM prefill。
2️⃣ vLLM prefill负责进行prefill操作,生成kv cache,并将这个缓存转发给vLLM decode。
3️⃣ Proxy API server继续将请求发送给vLLM decode。vLLM decode会执行drop_select操作,这个操作主要是获取kv和跳过prefill。完成drop_select后,vLLM decode会生成First token。
4️⃣ vLLM decode阶段也会生成First token。Proxy API server最终获取的所有token都是从vLLM decode获取的。vLLM prefill只负责生成kv cache。
通过这种方式,vLLM的PD分离架构能够实现高效的请求处理和缓存管理。
推荐阅读
► AGI新时代的探索之旅:2025 AIGCmagic社区全新启航
► 项目应用:开源视界
► 技术专栏: 多模态大模型最新技术解读专栏 | AI视频最新技术解读专栏 | 大模型基础入门系列专栏 | 视频内容理解技术专栏 | 从零走向AGI系列
► 技术综述: 一文掌握视频扩散模型 | YOLO系列的十年全面综述 | 人体视频生成技术:挑战、方法和见解 | 一文读懂多模态大模型(MLLM)|一文搞懂RAG技术范式演变及Agentic RAG|强化学习技术全面解读 SFT、RLHF、RLAIF、DPO|一文搞懂DeepSeek的技术演进之路
参考资料
[1]SARATHI: Efficient LLM Inference by Piggybacking Decodes with Chunked Prefills: https://arxiv.org/pdf/2308.16369v1.pdf
[2]DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving: https://arxiv.org/pdf/2401.09670v3.pdf
[3]LoongServe: Efficiently Serving Long-Context Large Language Models with Elastic Sequence Parallelism: https://arxiv.org/pdf/2404.09526v2.pdf
[4]Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving: https://arxiv.org/pdf/2407.00079v3.pdf
[5]Speculative Prefill: Turbocharging TTFT with Lightweight and Training-Free Token Importance Estimation: https://arxiv.org/pdf/2502.02789v2.pdf
[6]LServe: Efficient Long-sequence LLM Serving with Unified Sparse Attention: https://arxiv.org/pdf/2502.14866v2.pdf