PD-Multiplexing: Unlocking High-Goodput LLM Serving With GreenContext
PD-Multiplexing: Unlocking High-Goodput LLM Serving With GreenContext
发表时间: 2025-09 · Blog post by Weihao Cui, Yukang Chen, Xiaoze Fan, Han Zhao, Ziyi Xu, Xusheng Chen, Bingsheng He, Quan Chen (lmsys.org)
原文: https://lmsys.org/blog/2025-09-28-pdmux
作者/机构:Weihao Cui, Yukang Chen, Xiaoze Fan, Han Zhao, Ziyi Xu, Xusheng Chen, Bingsheng He, Quan Chen
速读
一句话结论
提出了一种名为 PD-Multiplexing 的大模型推理服务新范式,通过利用 NVIDIA 的 GreenContext 技术在单 GPU 进程内动态划分计算资源,实现了 Prefill 和 Decode 阶段的无气泡空间复用,在严格满足延迟服务等级协议的前提下,将系统的有效吞吐量提升了最高 3.06 倍。
要解决什么问题
大模型服务需要在不牺牲吞吐量的情况下,严格满足两个阶段的延迟服务等级协议(SLO):首字延迟(TTFT,对应 Prefill 阶段)和词间延迟(ITL,对应 Decode 阶段)。由于 Prefill 和 Decode 在同实例上交替运行,两者会激烈争抢 GPU 资源。为了保证延迟达标,现有系统通常采用两条路线,但均存在严重的机制卡点。第一条路线是实例级别的 PD 分离(PD-disaggregation),即将 Prefill 和 Decode 拆分到不同的物理实例上。这种做法的卡点在于 GPU 资源被静态隔离,且在实例间迁移庞大的 KV Cache 引入了极高的系统复杂性,严重依赖高性能的互联网络和通信库。第二条路线是序列级别的 Chunked-prefill,即把长序列切分成多个小块,将每个小块与一次 Decode 迭代融合执行以控制 ITL 延迟。其卡点在于陷入脆弱的权衡困境:为了满足严格的 ITL 约束,必须将 Chunk 尺寸设置得非常小(例如小于 1024),但这会导致 Prefill 阶段的矩阵乘法尺寸过小,根本无法打满 GPU 的计算单元,造成算力严重闲置。特别是在处理长上下文任务或面对严苛的工业级 SLO 阈值时,无论是跨节点的传输开销,还是切块带来的算力闲置,都会导致系统整体的有效吞吐量大幅下降。
怎么做的
核心思路是放弃跨实例的物理隔离和时间维度上的切块融合,转而在同一个 GPU 实例内部,通过空间共享机制对 Prefill 和 Decode 阶段进行多路复用(Multiplexing)。这种设计让两个阶段共享同一个 KV Cache 池,彻底绕开了跨实例迁移的昂贵通信开销;同时解耦了两者的执行过程,使得 GPU 的流多处理器(SM)能够根据实时负载在两个阶段之间动态流动。关键设计由两个核心部件构成:无气泡复用引擎和感知 SLO 的调度器。首先,底层依赖 NVIDIA 在 CUDA 12.4 引入的 GreenContext 技术,该技术允许在同一个进程内创建多个分配了专属 SM 资源的 CUDA 流,实现轻量级的细粒度资源隔离。为规避 Python 全局解释器锁(GIL)对真并行的限制,系统采用单线程异步调度,通过在专属的 GreenContext 流之间切换分发来实现复用。然而,直接引入该技术会产生严重的 GPU 气泡:一方面,Prefill 阶段的内核启动时间远长于仅包含单个 CUDA Graph 的 Decode 阶段,导致启动期间资源闲置;另一方面,Decode 阶段的迭代次数是不确定的,如果一个批次提前生成完毕,预分配的 SM 就会空转。为了消除这些气泡,引擎将庞大的 Prefill 阶段切分为更小的 Prefill 块,由于 Prefill 的计算密度极高,这种块级切分带来的额外开销微乎其微,却能完美填补调度间隙。其次,感知 SLO 的调度器负责生成具体的复用计划。因 GreenContext 无法隔离显存带宽,两阶段存在难以建模的带宽争抢。系统通过离线压测收集代表性负载数据,训练出延迟预测器。调度器的核心分配逻辑遵循明确的贪心策略:优先为 Decode 阶段分配刚好足够的 SM 数量以卡住 ITL 的 SLO 红线;随后,将 GPU 上所有剩余的 SM 资源全部倾斜给 Prefill 阶段,并同步计算出当前周期内可安全发射的 Prefill 块数量。通过这种机制,Decode 始终在严格的延迟保护下运行,而 Prefill 则利用一切剩余算力全速推进。
效果如何
实验在单张 H200 和 8 张 A100 GPU 服务器上展开,测试模型包括 CodeLlama-34b-hf 和 Llama3.1-70B。对比基线明确选取了代表两条主流路线的 SOTA 实现:代表序列切分路线的 Chunked-prefill(基于 SGLang 框架,Chunk 尺寸设为 512 或动态调整),以及代表实例分离路线的 PD-disaggregation(P:D 节点比例设为 1:1,开启前缀缓存共享)。在 8 张 A100 上回放 Mooncake-Tool&Agent 真实流量时,随着请求速率的增加,PD-Multiplexing 展现出极强的抗压能力,其达标的有效吞吐量分别达到了 Chunked-prefill 的 3.06 倍和 PD-disaggregation 的 1.62 倍。在单张 H200 上设定 60 毫秒的严苛 ITL 目标时,Chunked-prefill 必须将块大小降至 1024 以下才能勉强达标,代价是首字延迟大幅恶化;而 PD-Multiplexing 不仅稳稳守住了 60 毫秒的 ITL 红线,还实现了最快的首字延迟。在面对极端差异化的任务时,系统展现了精准的动态调度能力:在 OpenThoughts(极短输入、极长输出)任务中,调度器自动将极少的资源分配给 Prefill;而在 LooGLE(极长输入、极短输出)任务中,则将极少的资源分配给 Decode。该方法目前也存在明确的代价和局限性。首先,它强依赖于针对特定模型和硬件的一次性离线压测来构建调度策略,部署成本较高。其次,在工程实现上,当 PyTorch 版本高于 2.6 时,结合分布式 CUDA Graphs 和 NCCL 会触发 NVIDIA 底层的 Bug,导致显著的额外开销。此外,对于采用多令牌预测(MTP,如 DeepSeek-V3)或复杂投机解码机制的模型,由于其一次生成多个 Token,现有的资源划分策略将会失效,需要重新设计调度逻辑。
主要贡献
在大规模提供模型即服务(MaaS)时,大型语言模型(LLM)服务系统面临着一个核心挑战:必须在不牺牲吞吐量的前提下,严格满足服务级别目标(SLOs)。具体而言,需要同时满足推理两个阶段的延迟要求——预填充(prefill)阶段的首Token延迟(TTFT)和解码(decode)阶段的Token间延迟(ITL / TBT)。由于预填充和解码在同一个服务实例上交替进行,导致了对GPU资源的激烈竞争。
为了解决这一问题,本文提出了一种名为 PD-Multiplexing 的全新服务范式,并已在 SGLang 中进行初步支持。该范式利用了 NVIDIA GPU 的新特性 GreenContext(允许在同一进程内的任务之间进行轻量级、细粒度的 GPU 资源划分),在同一个 GPU 实例内部实现预填充和解码阶段的空间多路复用。PD-Multiplexing 旨在为 MaaS 部署提供更强的 SLO 保证和更高的有效吞吐量(Goodput)。
背景知识与设计原则
LLM服务中有效吞吐量(Goodput)的持续挑战
在实际应用中,确保严格的 SLO 是一项艰巨的任务。为了解决预填充和解码阶段资源竞争的问题,业界通常采用两种主要方法来保证 SLO 的合规性:
- 实例级PD分离(Instance-level PD-disaggregation):将预填充和解码分离到不同的实例中执行。这种方法存在明显的权衡代价:GPU 资源被静态划分,且实例之间的 KV缓存迁移(KV cache migration) 引入了额外的复杂性,需要依赖高性能的互连网络和通信库。
- 序列级分块预填充(Sequence-level chunked-prefill):将长序列拆分成较小的块(chunks),并将每个块与解码迭代融合以控制 ITL。这也引入了微妙的权衡:块大小必须在严格的 ITL 保证和高 GPU 利用率之间取得平衡。
特别是在针对实际 LLM 服务设定严格的 SLO 阈值时,无论是分离架构还是分块策略,其固有的缺陷都会变得越来越明显。
方法细节
PD-Multiplexing的提出与核心优势
为了应对上述挑战,作者提出了 PD-Multiplexing 这一新的服务范式,以实现更高的有效吞吐量。该范式通过 GPU 内部的空间共享(intra-GPU spatial sharing),在同一个实例中对预填充和解码阶段进行多路复用。这种设计提供了几个重要的优势:
- 预填充和解码在同一实例内共享一个公共的 KV 缓存池,消除了昂贵的跨实例迁移需求。
- GPU 内部的空间共享允许 GPU 计算资源(SMs)在预填充和解码之间根据工作负载的变化动态流动。
- 这种共享还解耦了预填充和解码的执行,确保在满足严格的 ITL SLO 时,预填充的性能不会受到损害。
PD-Multiplexing架构概览
PD-Multiplexing 的架构主要由两个核心模块组成:一个是无气泡(bubble-less)的多路复用引擎,用于独立且高效地执行预填充和解码阶段;另一个是感知 SLO 的调度器(SLO-aware dispatcher),用于迭代生成符合 SLO 的多路复用计划。
基于GreenContext的轻量级空间共享机制
这一新范式建立在 NVIDIA GPU(从 CUDA 12.4 开始引入)的 GreenContext 功能之上。GreenContext 支持轻量级的进程内(intra-process)空间共享。简而言之,从 CUDA 12.6 开始,系统可以为并发的 GPU 内核创建多个具有专用 SM 分配的 CUDA 流。借助 GreenContext,GPU 资源可以在预填充和解码阶段之间动态划分,从而实时适应 SLO 要求、工作负载模式以及其他服务需求。
单线程调度与多路复用的实现
为了保留现有的服务架构,系统采用了单线程调度来多路复用预填充和解码,而不是为每个阶段创建单独的线程。这一设计选择也是因为 Python 的全局解释器锁(GIL)仍然阻止真正的并行执行,并且在未来的版本中仍将是默认设置。幸运的是,预填充和解码都是异步的,这使得该设计具有可行性。通过在预填充和解码专属的 GreenContext 流之间切换调度,系统成功实现了多路复用。
GPU气泡问题的成因
然而,集成 GreenContext 会引入 GPU 气泡(如上图 Fig 2(a) 所示)。这些气泡产生的原因有两个:首先,预填充阶段的启动时间明显长于解码阶段(解码阶段仅涉及单个 CUDA 图)。在某些情况下,启动预填充阶段所需的时间甚至比执行整个解码阶段还要长,从而导致 GPU 资源闲置。其次,解码阶段的迭代次数是不确定的。当解码批次中的所有请求都提前完成时,如果已经启动了预填充,那么预先分配给解码的 SM 可能会处于未充分利用的状态。
通过预填充块拆分消除气泡
为了解决上述气泡问题,系统将预填充阶段拆分为更小的预填充块(prefill blocks),如 Fig 2(b) 所示。由于预填充的计算密集度通常远高于解码,这种块级别的拆分所带来的开销微乎其微,同时能够在多路复用期间有效地消除 GPU 气泡。
离线分析与延迟预测器的训练
在构建了无气泡的多路复用引擎之后,接下来的挑战是如何调度预填充块和解码批次。离线分析表明,这两个阶段在 GreenContext 下会竞争资源。根本原因在于,虽然 GreenContext 对 SM 进行了分区,但它并没有对内存带宽进行分区,这使得资源竞争难以建模。为了解决这个问题,作者对具有代表性的工作负载进行了离线分析,并利用这些结果训练了一个延迟预测器(latency predictor),该预测器用于驱动感知 SLO 的调度策略。由于建模依赖于特定的模型和硬件环境,具体细节在此省略,但未来会提供包含实际操作指导的详细教程。
调度策略的核心直觉
该调度策略背后的直觉非常明确:为解码阶段分配恰好足够的 SM 以保证满足 ITL SLO,然后将所有剩余的 SM 专用于预填充。同时,系统会确定要启动的预填充块的数量。 通过这种方式,解码始终在严格的 SLO 保证下运行,而预填充则尽可能快地进行,从而扩大解码的批处理大小(batch size)。
实验环境
- 硬件配置:单张 H200 GPU;以及配备 8 张 A100 GPU 的服务器。
- 软件配置:基于 SGLang 代码库进行公平比较,开启前缀缓存共享(Prefix cache sharing),底层依赖 PyTorch 2.6 及 CUDA >= 12.4 环境。
- 模型:CodeLlama-34b-hf, Llama3.1-70B, Qwen-235B (MoE初步测试)。
-
数据集/工作负载:
- ShareGPT:输入较长,输出较短。
- LooGLE:长上下文工作负载,输入最长,输出最短。
- Mooncake-Tool&Agent:真实世界的工作负载追踪(Trace)。
- OpenThoughts:输入最短,输出最长。
-
对比基线(Baselines):序列级分块预填充(Chunked-prefill)、实例级PD分离(PD-disaggregation,P:D比例为1:1)。
实验结果
1. 不同分块大小下与分块预填充(Chunked-prefill)的对比
- 实验内容:在单张 H200 GPU 上运行 CodeLlama-34b-hf,评估 ShareGPT 和 LooGLE 负载。设定 ITL 的 SLO 目标为 60 ms,不对 TTFT 施加 SLO 限制,而是报告 TTFT 的 P99 延迟以展示效率。
- 实验结果:PD-Multiplexing 提供了最快的 TTFT,同时始终满足 60 ms 的严格 ITL 目标(图中实心点表示满足 SLO)。相比之下,Chunked-prefill 通常必须将分块大小减小到 1024 以下才能满足如此严格的 ITL 要求(图中空心点表示违反 SLO),这严重降低了预填充性能并导致 GPU 资源未充分利用。
- 分析结论:PD-Multiplexing 在严格的 SLO 约束下具有显著优势,这种优势在 LooGLE 等长上下文工作负载中更为明显,因为分块策略的低效性在此类负载中被放大了。
2. 真实世界追踪(Real-world Traces)的评估结果
- 实验内容:在 8x A100 服务器上运行 Llama3.1-70B,使用 Mooncake-Tool&Agent 真实追踪数据。对比基线包括分块大小为 512 的 Chunked-prefill 和 P:D 比例为 1:1 的 PD-disaggregation。
- 实验结果:在 TTFT 和 ITL 两个指标上,PD-Multiplexing 均优于 Chunked-prefill。与 PD-disaggregation 相比,PD-Multiplexing 实现了明显更短的 TTFT,同时两者均满足了解码阶段的 SLO。在逐步增加请求率以测量有效吞吐量(Goodput)时,PD-Multiplexing 维持了显著更高的有效吞吐量。
- 分析结论:PD-Multiplexing 相比 Chunked-prefill 和 PD-disaggregation 分别实现了高达 3.06 倍和 1.62 倍的有效吞吐量提升。
3. 多样化任务的结果与调度可视化
- 实验内容:在 8x A100 服务器上运行 Llama3.1-70B,评估三种具有截然不同工作负载模式的任务:OpenThoughts、ShareGPT 和 LooGLE。
- 实验结果:PD-Multiplexing 在这些任务中始终保持强大的性能,并获得了比基线高得多的有效吞吐量(见 Fig 5)。运行时的调度时间线(见 Fig 6)显示了其动态适应资源分配的过程:对于 OpenThoughts,它为预填充分配了最少的资源;而对于 LooGLE,它为解码分配了最少的资源。
- 分析结论:调度器能够随着工作负载的变化在不同的 SM 分配计划之间无缝切换,从而确保了 SLO 的合规性和系统的高效率。
结论与未来工作
PD-Multiplexing 在 MaaS 部署中展现出了巨大的潜力。目前,该方案已在 SGLang 中实现了概念验证,全面集成的路线图正在推进中。作者指出未来的工作将集中在以下几个领域:
- 支持 MTP 和投机解码(Speculative Decoding):针对具有多 Token 预测(MTP)机制的模型(如 DeepSeek-V3)以及采用复杂验证方法的投机解码方法,需要调整调度策略以保证 SLO。未来将扩展定制化的资源划分策略并报告端到端收益。
- 面向更真实的工业级 SLO 与细粒度参数控制:PD-Multiplexing 需要针对目标模型和硬件进行一次性分析。团队计划发布详细的实操教程,帮助用户复现分析工作流,并为真实的工业场景设计有效的调度策略。
- 与 PD 分离(PD-Disaggregation)的集成:PD-Multiplexing 与分离架构并不互斥,两者可以结合以进一步提升有效吞吐量。例如,当解码实例在变化的工作负载下无法维持其最大批处理大小时,可以将其替换为 PD-Multiplexing 实例,通过重叠解码与多路复用的预填充来回收浪费的资源。
- 解决 PyTorch > 2.6 的兼容性问题:在较新版本的 PyTorch 中,结合 CUDA Graphs 和 NCCL(特别是启动分布式 CUDA Graphs)会产生显著的开销。团队正与上游开发者合作解决此内部 Bug。
- MoE 模型支持:在 Qwen-235B 上的初步实验表明 PD-Multiplexing 能带来持续的改进,未来计划在更大的分布式环境中发布针对大型 MoE 模型(如 DeepSeek-V3)的全面评估结果。
💬 评论讨论
欢迎在这里分享您的想法和见解!