LLM推理架构革新:解耦Prefill与Decode提升服务性能

📅 2026/8/12 14:18:11
LLM推理架构革新:解耦Prefill与Decode提升服务性能
1. 项目概述为什么我们需要重新审视 LLM 推理架构最近在跟几个做 AI 应用落地的朋友聊天大家普遍被一个问题困扰模型效果是越来越好了但服务的成本和延迟却成了“拦路虎”。尤其是在高并发场景下比如一个智能客服系统高峰期同时涌入成千上万的用户提问后台的 LLM 推理服务很容易就“撑不住”了要么响应慢如蜗牛要么直接崩溃。这背后一个核心的瓶颈就在于我们当前普遍采用的推理架构。传统的 LLM 推理无论是使用 Hugging Face 的transformers库还是像 vLLM、TGI 这样的高性能推理框架其核心流程可以概括为“接收请求 - 执行 Prefill预填充- 循环执行 Decode解码生成 Token - 返回结果”。这里的Prefill指的是根据用户的输入Prompt计算第一个输出 Token 之前的所有计算它需要将整个 Prompt 序列加载到注意力机制中进行计算计算量大但具有很强的并行性。而Decode则是自回归地生成后续的每一个 Token每次只处理一个 Token计算量相对较小但严重依赖前一步的结果是串行且内存带宽敏感的。问题就出在这里。在高并发下多个请求的 Prefill 和 Decode 阶段会混杂在一起被调度到同一个计算设备如 GPU上执行。Prefill 阶段因为要处理长序列会瞬间吃满 GPU 的计算核心和显存带宽导致同一时间本可以进行的多个轻量级 Decode 计算被“堵”在后面整体吞吐量Throughput上不去延迟Latency也下不来。这就好比一条高速公路既有需要长时间占用超车道进行检修的工程车Prefill又有大量的小轿车Decode工程车一上路整条路的通行效率就骤降。“Prefill 与 Decode 分离”这个架构思路正是在这种背景下被提出来的。它不是一个具体的产品而是一种设计范式的转变。其核心思想是将计算特性截然不同的 Prefill 阶段和 Decode 阶段解耦到不同的、专有的计算资源上去执行。让擅长并行计算的设备去专心处理 Prefill让擅长低延迟串行计算的设备去高效处理 Decode从而从系统层面优化资源利用率和整体服务性能。这听起来有点像计算机体系结构里的“异构计算”思想在 LLM 服务领域的应用。接下来我们就深入拆解一下这个架构的方方面面。2. 架构核心解耦 Prefill 与 Decode 的动机与优势为什么要把它们分开这得从它们各自的计算属性和对硬件资源的需求矛盾说起。2.1 Prefill 与 Decode 的计算特性对比我们可以用一个简单的表格来直观对比特性维度Prefill 阶段Decode 阶段计算模式高度并行。一次性处理整个输入序列注意力机制中的(Q, K, V)矩阵运算可以充分利用 GPU 的数千个核心进行并行计算。串行自回归。每次只生成一个 Token计算依赖于前一个时刻的KV Cache计算并行度低更类似于 RNN 的步进计算。计算强度计算密集型Compute-Bound。涉及大量矩阵乘加运算FLOPs对 GPU 的算力TFLOPS非常敏感。内存带宽密集型Memory-Bound。每次生成主要操作是读取上一时刻的KV Cache并进行一次小的矩阵运算对 GPU 显存带宽GB/s更敏感。资源占用短时、爆发式占用。消耗大量计算核心和显存用于存储当前 Prompt 的KV Cache但持续时间相对较短。长时、稳定式占用。每个请求的 Decode 周期可能很长生成数百个 Token持续占用计算资源但每个时刻的瞬时计算需求不高。关键瓶颈GPU 的算力峰值和片上缓存SRAM大小。算力不足会导致 Prefill 时间过长片上缓存不足会导致需要频繁访问高延迟的 HBM 显存。GPU 的显存带宽和推理引擎调度效率。带宽不足会成为取KV Cache的瓶颈调度效率低会导致 GPU 算力闲置等待数据。2.2 传统混合调度的困境在现有框架中Prefill 和 Decode 任务通常在一个 GPU 上通过时间片轮转或事件驱动的调度器混合执行。这带来了几个明显问题资源争抢与尾部延迟激增一个大的 Prefill 任务比如处理一个 2000 Token 的长文档摘要请求会“霸占”GPU 核心数十甚至数百毫秒。在这期间所有其他正在 Decode 的请求都会被挂起等待。对于这些 Decode 请求的用户来说他们感知到的就是响应突然卡顿这就是可怕的“尾部延迟Tail Latency”问题。硬件利用率不均衡在 Decode 阶段GPU 强大的并行计算单元其实处于“吃不饱”的状态因为任务并行度低。而在 Prefill 阶段显存带宽又可能成为瓶颈。混合调度无法让硬件始终工作在最适合当前任务类型的状态导致整体利用率达不到最优。批处理Batching策略复杂为了提高吞吐推理框架会对请求进行批处理。但 Prefill 和 Decode 对批大小的容忍度不同。Prefill 批太大显存可能爆炸Decode 批太大容易因个别长序列请求而拖慢整个批。混合在一起调度使得制定高效的批处理策略变得异常复杂。2.3 分离架构带来的核心优势将两者分离分别用不同的硬件资源池来服务上述问题就能得到系统性缓解提升吞吐与降低延迟Prefill 专用设备可以堆积一批 Prompt 进行大批次、高并行的计算充分发挥算力。Decode 专用设备则专注于以高带宽、低延迟的方式服务大量并发的生成请求。两者互不阻塞系统整体吞吐量QPS得以大幅提升同时 Decode 的延迟也更加稳定可预测。优化硬件资源配置与成本我们可以为不同阶段“量身定制”硬件。Prefill 池可以选用核心数多、算力强高 TFLOPS的 GPU甚至可以考虑使用针对矩阵乘法优化的其他加速芯片。Decode 池可以选用显存带宽高、能效比好的 GPU或者利用 CPU 大内存配合优化过的推理引擎来处理对延迟不敏感但量极大的超长文本生成尾部。这种异构配置相比给所有节点配置同一款高端 GPU往往能在满足性能目标的前提下显著降低总体拥有成本TCO。实现更精细的调度与弹性伸缩Prefill 和 Decode 成为两个独立的微服务。我们可以根据实时流量特征独立地伸缩这两个资源池。例如在白天客服问答高峰期扩大 Decode 池以应对海量短交互在夜间批量处理报告时扩大 Prefill 池以快速消化积压的长文本任务。调度系统也变得更简单、更高效。注意分离架构并非没有代价。它引入了跨设备的通信开销Prefill 完成后需要将KV Cache传输到 Decode 设备也增加了系统的复杂性。因此它更适合于中大规模、对性能和经济性有明确要求的服务场景对于小规模或实验性服务传统单体架构可能更简单直接。3. 系统设计与关键技术拆解一个完整的 Prefill/Decode 分离架构服务系统其设计远比“用两个程序”复杂。它涉及请求的生命周期管理、状态维护、数据传递和故障恢复等多个层面。3.1 整体架构与数据流一个典型的设计如下图所示此处用文字描述[客户端] -- (负载均衡器 / API Gateway) | | (携带完整Prompt的请求) v [Prefill 服务集群] | | (完成Prefill输出: 1. 首个Token 2. 对应的KV Cache) v [调度与状态管理中间件] --- 核心 | | (分配Decode节点传递KV Cache) v [Decode 服务集群] | | (流式返回生成的Tokens) v [客户端]核心组件解析负载均衡器 / API Gateway接收用户请求并将其路由到 Prefill 服务集群。它需要具备基本的限流、鉴权等功能。Prefill 服务集群由专门负责 Prefill 计算的节点组成。每个节点加载模型权重但只执行 Prefill 阶段。完成 Prefill 后它生成两个关键结果首个输出 Token可以立即返回给客户端实现快速首字响应。计算好的 KV Cache这是为当前 Prompt 生成的键值对缓存是后续 Decode 的“状态”。这个状态需要被序列化并传递给下游。调度与状态管理中间件这是整个架构的“大脑”也是最复杂的部分。它需要会话Session管理维护请求的上下文将 Prefill 阶段和后续的 Decode 阶段关联起来。通常需要一个唯一的Session ID。Decode 节点调度根据当前各个 Decode 节点的负载内存使用率、队列长度等决定将新的KV Cache调度到哪个节点上执行后续生成。状态存储与传递负责接收来自 Prefill 节点的KV Cache并将其高效地传输到被选中的 Decode 节点。这里对网络带宽和延迟有较高要求。故障转移如果某个 Decode 节点宕机需要能将其中运行的会话状态迁移到其他健康节点。Decode 服务集群由专门负责 Decode 计算的节点组成。节点接收调度器分配来的KV Cache和生成参数如最大长度、采样温度等然后以流式的方式持续生成 Token并通过类似 Server-Sent Events (SSE) 或 WebSocket 的技术返回给客户端。3.2 状态管理与 KV Cache 传递这是分离架构中技术挑战最大的一环。KV Cache的大小与 Prompt 长度和模型层数、注意力头数成正比对于一个大型模型如 Llama 3 70B和长 Prompt它可能达到数百 MB 甚至 GB 级别。如何高效、低延迟地传递这个状态序列化与压缩KV Cache通常是 GPU 内存中的张量Tensor。在通过网络传输前需要将其序列化为字节流。直接使用原生格式如 PyTorch 的.pt文件体积庞大。可以采用以下优化量化将KV Cache从 FP16/BF16 量化为 INT8 甚至更低精度传输在 Decode 端再反量化使用。这能直接减少 50% 以上的数据量。研究表明在 Decode 阶段KV Cache对精度有一定容忍度合理量化对生成质量影响很小。压缩应用轻量级的通用压缩算法如 Snappy、LZ4对字节流进行快速压缩/解压。传输协议与链路高速网络Prefill 和 Decode 集群之间最好通过 RDMA如 InfiniBand 或 RoCE网络互联实现 GPU 显存到 GPU 显存的直接内存访问GPUDirect RDMA绕过 CPU 和系统内存极大降低传输延迟和 CPU 开销。专用通道可以设计一个轻量级的 RPC 框架专门用于传输KV Cache和控制命令而不是走通用的 HTTP/gRPC以减少协议开销。状态存储后端对于需要支持超长会话或故障恢复的场景KV Cache可能需要持久化到外部存储如高速 SSD、内存数据库如 Redis 或更专业的向量数据库。但这会引入额外的 I/O 延迟需要精心设计缓存策略。3.3 调度策略详解调度器的目标是最大化系统吞吐同时保证公平性和满足 SLA服务等级协议。它需要做两种主要决策Prefill 请求的批处理Batching调度器会短暂地收集一批到达的 Prefill 请求例如一个时间窗口内的所有请求然后将这批请求发送给同一个 Prefill 节点。Prefill 节点利用 GPU 的并行能力同时计算这批请求。批大小的选择是个权衡批越大计算密度越高吞吐越大但单个请求的等待时间队列延迟也会增加并且显存占用也越大。Decode 节点的负载均衡调度器需要监控所有 Decode 节点的状态。一个简单的策略是基于当前节点管理的KV Cache总大小即显存占用进行加权轮询。更复杂的策略可以考虑每个节点上 Decode 请求的预估剩余生成时间将新请求调度到预计最早空闲的节点上以最小化尾部延迟。实操心得在早期实践中我们发现调度器本身不能成为瓶颈。一个常见的错误是将调度器设计得过于复杂引入了大量计算和通信开销。实际上一个基于一致性哈希Consistent Hashing的轻量级调度往往在初期就足够有效。它将Session ID映射到固定的 Decode 节点避免了全局状态同步的开销。只有当节点故障时才需要将受影响会话重新调度到其他节点。4. 实操部署与性能调优指南理论再好也需要落地。下面我们以一个假设的、基于开源组件构建的分离架构服务为例拆解关键实操步骤和调优点。4.1 硬件选型与集群规划假设我们的服务目标是日均处理百万级请求平均 Prompt 长度 500 Token平均生成长度 100 TokenP99 延迟要求低于 2 秒。Prefill 集群选型选择单卡算力强大的 GPU例如 NVIDIA H100。它的 FP16 张量核心算力极高能快速消化大批量 Prefill。数量根据峰值 Prefill QPS 和单卡批处理能力估算。例如单张 H100 可能每秒能处理数十个中等长度 Prompt 的 Prefill。预留 20%-30% 的冗余以应对流量波动。网络Prefill 节点之间无需高速互联但与调度器/存储的网络带宽要足。Decode 集群选型选择显存带宽高、能效比优秀的 GPU例如 NVIDIA A100 80GB 或甚至 A10。对于成本极度敏感的场景可以探索使用高端 CPU配大内存和 DeepSpeed-FastGen、llama.cpp 等优化引擎来处理部分 Decode 流量。数量Decode 节点数量通常远多于 Prefill 节点因为每个 Decode 请求占用资源时间长。需要根据并发会话数目标来估算。网络至关重要。Decode 集群内部以及 Decode 与 Prefill/状态存储之间强烈建议使用 RDMA 网络InfiniBand 或 200G RoCE这是保证低延迟状态传输的关键。调度器与状态存储调度器可以是一个无状态的微服务多实例部署前面用负载均衡。状态存储存放KV Cache是核心状态组件需要高可用。可选方案内存数据库集群如 Redis Cluster 或 KeyDB延迟极低亚毫秒但容量受限于内存总大小。分布式内存对象存储如开源的dragonfly或商业解决方案提供更大容量和持久化能力。直接点对点传输对于超高性能场景在调度器协调下Prefill 节点直接通过 RDMA 将KV Cache写入 Decode 节点的 GPU 显存完全 bypass 外部存储。但这要求稳定的网络和复杂的故障处理机制。4.2 软件栈与组件实现目前没有“开箱即用”的完整解决方案需要组合多个开源项目并进行深度定制。Prefill 服务可以使用vLLM或TGI的引擎但需要修改其服务逻辑使其在完成 Prefill、生成KV Cache后即停止并将状态通过 gRPC 或自定义协议发送给调度器而不是继续执行 Decode。需要实现一个轻量级服务包装处理请求接收、批处理组装、调用引擎、结果打包和发送。Decode 服务同样基于 vLLM 或 TGI 引擎修改。它需要从一个“状态接收接口”加载KV Cache而不是从零开始 Prefill。核心修改点是引擎的初始化过程需要能够注入已有的KV Cache并在此基础上继续生成。调度与状态服务这是自定义开发的核心。可以用 Go 或 Rust 实现保证高性能和低资源消耗。需要实现会话管理 API、节点健康检查、负载均衡逻辑、状态转发从 Prefill 接收向 Decode 发送。状态传输的客户端/服务器端 SDK 需要精心设计集成上述提到的量化和压缩功能。API 网关可以使用Nginx、Envoy或Kong。它负责将/v1/chat/completions之类的初始请求路由到 Prefill 集群并可能处理后续的流式响应这部分可能直接由 Decode 服务流式推回。4.3 关键配置与性能调优参数Prefill 批处理大小prefill_batch_size这是 Prefill 吞吐的关键。需要通过压测找到“甜蜜点”。在显存不溢出的前提下逐步增大批大小观察 GPU 利用率和吞吐量的变化曲线。通常这个值会远大于 Decode 的批大小。Decode 批处理大小decode_batch_sizeDecode 阶段GPU 同时处理多个并发生成请求。这个值主要受限于每个请求KV Cache占用的显存。采用PagedAttentionvLLM 的核心技术可以极大优化显存碎片从而提高批大小。KV Cache 量化精度这是平衡传输开销和生成质量的关键。例如可以配置为fp16 - int8进行传输。必须在测试集上验证量化对特定任务如代码生成、创意写作输出质量的影响。调度器心跳与超时调度器需要定期如每秒与 Prefill/Decode 节点通信检查健康状态。节点无响应超时时间如 30 秒需要合理设置太短可能导致网络抖动误判太长则故障恢复慢。流式返回缓冲区Decode 服务流式返回 Token 时客户端可能消费不及时。需要设置合理的缓冲区大小和超时丢弃策略防止服务端内存泄漏。5. 常见问题、挑战与排查实录分离架构在带来性能收益的同时也引入了新的复杂性和故障点。以下是一些实践中可能遇到的典型问题。5.1 典型问题与解决方案速查表问题现象可能原因排查思路与解决方案首 Token 延迟TTFT过高1. Prefill 队列过长。2. Prefill 批处理太大单个请求等待时间久。3. Prefill 节点算力不足。1. 监控 Prefill 服务队列深度增加 Prefill 节点实例。2. 动态调整 Prefill 批处理策略例如设置最大等待时间超时即执行当前批。3. 升级 Prefill 节点 GPU 型号或优化模型计算图如使用更好的算子库。生成速度慢或不稳定1. Decode 节点负载过高调度不均。2. 网络传输KV Cache延迟高或丢包。3. Decode 阶段未有效利用 PagedAttention 等内存优化技术。1. 检查调度器负载均衡策略查看是否有节点“热点”。优化调度算法。2. 使用ping、iperf3检查网络确保使用 RDMA 且配置正确。检查状态传输服务的 CPU 使用率是否过高。3. 确认 Decode 服务配置确保 vLLM 的block_size等参数设置合理监控显存碎片情况。会话中断或状态丢失1. Decode 节点宕机状态未持久化。2. 调度器故障会话映射丢失。3. 状态存储如 Redis故障或内存不足被驱逐。1. 实现 Decode 节点的定期状态检查点Checkpoint并持久化到共享存储。调度器需具备故障转移逻辑。2. 调度器本身需要高可用部署多副本选主。3. 监控状态存储容量和性能设置合理的驱逐策略如 LRU对于重要长会话可考虑持久化到 SSD。系统吞吐未达预期1. Prefill 和 Decode 资源比例失调。2.KV Cache传输成为瓶颈。3. 调度器或 API 网关成为瓶颈。1. 进行全链路压测分析各环节资源利用率。根据瓶颈调整两类集群的节点数量比例。2. 对KV Cache实施更激进的量化如 INT4或压缩。升级网络硬件。3. 对调度器和网关进行性能剖析Profiling优化代码或水平扩展其实例数。生成内容质量下降1.KV Cache在传输过程中发生数据错误。2. 量化精度损失过大。3. Prefill 和 Decode 使用了不同版本的模型或不同的计算精度。1. 在传输协议中加入校验和Checksum机制。2. 回调量化精度或在 Decode 端采用更精细的反量化策略。3. 严格统一整个服务链的模型文件、权重精度和推理框架版本。5.2 核心挑战与演进思考状态同步的精确性与一致性在超大规模部署中如何保证一个用户会话的KV Cache在多个潜在的 Decode 备选节点之间快速、一致地同步或迁移这涉及到分布式系统经典的一致性问题。目前业界有探索利用类似分布式共享内存DSM或高性能分布式缓存的技术来解决。成本与复杂度的权衡分离架构引入了额外的组件调度器、状态存储和网络开销。对于中小规模或流量波动不大的服务其带来的性能收益可能无法覆盖增加的运维复杂度和硬件成本。需要一个清晰的性能模型和成本模型来做决策。与现有生态的融合目前的推理框架和云服务商提供的托管服务大多是基于单体架构优化的。采用分离架构意味着需要更多的自研和集成工作在框架更新、模型支持等方面可能滞后。更极端的异构化未来的架构可能会进一步细分。例如将 Decode 阶段中不同的计算部分如注意力头的计算、前馈网络的计算也调度到不同的特化硬件上。甚至一些研究正在探索用更节能的 NPU 或 ASIC 来专门处理 Decode 中的某些固定模式计算。从我个人的实践经验来看Prefill/Decode 分离架构是 LLM 推理服务走向工业化、规模化的必然路径之一。它本质上是一种“拆解-专化-重组”的系统工程思想。在项目初期我们可能只需要一个简单的、全功能的推理服务快速验证想法。但当流量和成本成为核心考量时就必须从系统架构层面去思考如何“把好钢用在刀刃上”。这个架构的落地过程也是对团队在分布式系统、高性能计算和模型推理优化等方面综合能力的一次考验。它没有银弹需要根据自身的业务特征、流量模式和基础设施条件进行深度定制和持续调优。