news 2026/9/28 23:54:02

大模型推理PD分离实战:Prefill与Decode拆解及KV Cache传输优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
大模型推理PD分离实战:Prefill与Decode拆解及KV Cache传输优化

推理优化这两年成了大模型落地绕不开的话题,尤其是当你的服务从"能跑通"进入"要扛量"的阶段,Prefill 和 Decode 这两个阶段的资源争抢问题就会赤裸裸地摆在面前。PD 分离(Prefill-Decode Disaggregation)不是什么新概念,但真正把它讲清楚、讲透"为什么这么拆""拆完怎么接""哪些坑必须提前踩"的资料并不多。我最近在几个推理服务项目里反复折腾这套架构,从最初的"看起来很美"到中间的"性能反而下降",再到最后稳定跑起来,中间踩的坑足够写一篇长文。这篇就把 PD 分离的基础逻辑、核心机制、实操要点和我自己的经验教训一次性讲清楚,适合正在做推理服务优化、准备上 PD 分离或者已经上了但效果不达预期的同学参考。不管你是刚接触推理优化的新手,还是已经在调参一线的老手,应该都能从里面找到对自己有用的东西。

1. 为什么要把 Prefill 和 Decode 拆开看

1.1 两个阶段的本质差异

大模型推理的过程,说白了就是两件事:先把你的输入 prompt 吃进去算出第一波结果,然后一个 token 一个 token 地往外吐。前者叫 Prefill,后者叫 Decode。很多人一开始会觉得这不就是同一个模型的前后两步吗,为什么要拆?问题恰恰出在"同一个模型"这四个字上。

Prefill 阶段是一次性处理整个输入序列,所有 token 并行计算,矩阵乘法的规模大、并行度高,属于典型的计算密集型任务。GPU 的算力在这个阶段能被吃得很满,显存带宽反而没那么紧张。而 Decode 阶段每次只处理一个新 token,但需要读取之前所有 token 的 KV Cache,计算量小、访存量大,属于典型的访存密集型任务。这两个阶段的硬件需求方向完全相反:一个要算力,一个要带宽。

我打个比方,Prefill 像是餐厅后厨一次性接了个大单,所有厨师一起上,灶台火力全开;Decode 像是客人一道一道点菜,每道菜都要翻一遍之前的菜单记录,厨师大部分时间花在翻记录上而不是炒菜。你把这两种活儿混在一个厨房里干,必然互相干扰。

1.2 混部带来的真实问题

在实际服务中,Prefill 和 Decode 混在同一个 GPU 上跑,会出现几个很典型的问题。

第一个是长尾延迟。当一个长 prompt 的 Prefill 任务进来时,它会占用大量算力,导致正在进行的 Decode 任务被卡住。用户那边看到的就是"打字机突然卡了一下"。这个卡顿在交互式应用里非常致命,因为人对延迟的感知是非线性的,偶尔卡一下比整体慢一点更让人难受。

第二个是资源利用率上不去。因为两个阶段的资源需求不同,你没法针对性地优化。给 Prefill 配的算力在 Decode 阶段闲置,给 Decode 配的带宽在 Prefill 阶段用不上。整体 GPU 利用率可能只有 30% 到 40%,剩下的都浪费在等待和切换上。

第三个是批处理策略难做。Prefill 适合大 batch 提升吞吐,Decode 适合小 batch 降低延迟,两者的最优 batch size 往往差一个数量级。混在一起时,你只能取个折中值,结果两边都不讨好。

提示:如果你的服务 QPS 很低、延迟要求也不严格,混部其实够用,没必要为了架构而架构。PD 分离的收益在规模化场景下才明显。

1.3 分离之后能拿到什么

把两个阶段拆到不同的实例上,最直接的好处是各管各的。Prefill 实例可以专门堆算力,用大 batch 把吞吐拉满;Decode 实例可以专门优化访存,用小 batch 保证低延迟。两者通过 KV Cache 的传输来衔接。

实测下来,在合适的负载下,PD 分离能把整体吞吐提升 1.5 到 3 倍,同时把 P99 延迟压下来。但这个"合适"两个字很关键,后面会详细讲什么情况下收益最大、什么情况下反而亏。

2. KV Cache 的搬运才是 PD 分离的真正主角

2.1 KV Cache 到底是什么

要理解 PD 分离,必须先搞明白 KV Cache。Transformer 在生成每个 token 时,需要用到之前所有 token 的 Key 和 Value 向量。如果每次都重新算一遍,计算量会随序列长度平方增长,完全没法用。所以工程上会把已经算过的 K 和 V 缓存下来,Decode 时直接读取,这就是 KV Cache。

KV Cache 的大小可以粗略估算:2 × 层数 × 注意力头数 × 头维度 × 序列长度 × 数据类型字节数。以一个 70B 级别的模型为例,单条 4K 长度的序列,KV Cache 可能就要几百 MB 甚至上 GB。这个数字直接决定了 PD 分离的传输成本。

2.2 传输为什么是瓶颈

PD 分离后,Prefill 实例算完 KV Cache,需要把它传给 Decode 实例。这个传输过程有几个特点让它特别容易成为瓶颈。

首先是数据量大。上面算过,单条序列的 KV Cache 就是几百 MB 级别,如果并发几十条,瞬间就是几十 GB 的传输量。其次是延迟敏感。Decode 实例必须等 KV Cache 到齐才能开始生成第一个 token,传输慢一点,首 token 延迟就高一点。最后是传输频率高。每个请求都要传一次,不是一次性的。

所以 PD 分离架构里,KV Cache 的传输方案设计得好不好,直接决定了整套系统能不能用。这也是为什么很多团队兴冲冲上了 PD 分离,结果发现性能还不如混部——传输开销把分离带来的收益全吃掉了。

2.3 几种传输方案的取舍

目前主流的 KV Cache 传输方案有这么几种,各有适用场景。

方案原理优点缺点适用场景
网络传输通过 RDMA 或 TCP 在节点间传灵活,支持跨节点带宽受限,延迟较高大规模分布式部署
共享存储写入共享内存或分布式存储解耦彻底读写延迟大对延迟不敏感的场景
同机共享同节点内通过共享内存传延迟极低无法跨节点单机多卡场景
计算换传输Decode 端重算部分 KV省传输浪费算力传输成本极高的场景

我自己的经验是,同机共享内存是延迟最低的方案,如果 Prefill 和 Decode 能部署在同一台机器的不同 GPU 上,优先考虑这个。跨节点的话,RDMA 是标配,但要注意网卡带宽和拓扑,别让流量绕远路。

注意:传输方案的选择要和你的部署规模匹配。小规模部署硬上 RDMA 是浪费,大规模部署用 TCP 会拖垮性能。

3. 调度策略决定了 PD 分离的上限

3.1 请求怎么分配

PD 分离后,一个请求要经过 Prefill 实例和 Decode 实例两道手,调度器需要决定:这个请求的 Prefill 交给哪个实例,算完的 KV Cache 又该送到哪个 Decode 实例。

最简单的做法是轮询,请求依次分给各个 Prefill 实例,KV Cache 再依次分给各个 Decode 实例。这个方案实现简单,但在负载不均时会出问题——某个 Prefill 实例可能因为处理了长 prompt 而变慢,后续请求还往它身上堆,雪上加霜。

好一点的做法是基于负载的调度,调度器实时感知各实例的队列长度和资源占用,把新请求分给最闲的实例。这个方案需要维护全局状态,实现复杂度上来了,但效果明显更好。

再进一步是亲和性调度,尽量让同一个请求的 Prefill 和 Decode 落在网络距离近的实例上,减少 KV Cache 传输开销。这个在跨节点部署时特别重要。

3.2 Prefill 和 Decode 的配比

一个经常被问到的问题是:Prefill 实例和 Decode 实例该按什么比例配?这个没有标准答案,取决于你的负载特征。

如果输入普遍很长、输出很短(比如文档问答、摘要生成),Prefill 的压力大,需要多配 Prefill 实例。如果输入短、输出长(比如创意写作、对话),Decode 的压力大,需要多配 Decode 实例。实际生产中,负载是动态变化的,所以理想情况下配比也应该能动态调整。

我见过一些团队用固定配比,结果白天和晚上的负载特征不一样,白天 Prefill 排队、Decode 闲置,晚上反过来。这种时候要么做弹性伸缩,要么至少准备两套配比按时间段切换。

3.3 批处理的时机把握

Prefill 端适合攒大 batch,但攒 batch 意味着等待,等待就意味着延迟。这里有个权衡:batch 越大吞吐越高,但首 token 延迟也越高。

我的做法是设置一个最大等待时间,比如 50ms,在这个时间内尽量攒 batch,超时了就立即发车。这样既保证了吞吐,又给延迟设了个上限。Decode 端则相反,batch 要小,甚至可以考虑 continuous batching,让新请求随时插入,不用等当前 batch 结束。

4. 动手搭一套最小可用的 PD 分离

4.1 环境准备与组件选型

要搭一套能跑的 PD 分离,你需要这么几个组件:推理引擎(vLLM、TensorRT-LLM、SGLang 都支持 PD 分离)、KV Cache 传输层、调度器。

推理引擎我推荐从 vLLM 入手,它的 PD 分离支持比较成熟,社区文档也全。传输层如果同机部署,直接用共享内存;跨节点的话,vLLM 支持通过 NCCL 或 RDMA 传输。调度器可以自己写个简单的,也可以直接用引擎自带的。

环境上,确保你的 GPU 驱动、CUDA 版本、NCCL 版本匹配,这几个版本不匹配是新手最容易踩的坑。我建议先用官方推荐的版本组合跑通,再考虑升级。

4.2 配置的关键参数

以 vLLM 为例,PD 分离的核心配置大概长这样:

# Prefill 实例 python -m vllm.entrypoints.openai.api_server \ --model /path/to/model \ --port 8000 \ --kv-transfer-config '{"kv_connector":"PyNcclConnector","kv_role":"kv_producer","kv_rank":0,"kv_parallel_size":2}' # Decode 实例 python -m vllm.entrypoints.openai.api_server \ --model /path/to/model \ --port 8001 \ --kv-transfer-config '{"kv_connector":"PyNcclConnector","kv_role":"kv_consumer","kv_rank":1,"kv_parallel_size":2}'

几个关键参数要理解清楚:kv_role区分生产者和消费者,kv_rank和kv_parallel_size决定传输拓扑。这些参数配错了,实例之间连不上,请求会一直卡着。

4.3 跑通第一个请求

配置好之后,先别急着压测,用单个请求验证链路是否通。发一个简单的请求到 Prefill 实例,观察日志里 KV Cache 是否成功传输到 Decode 实例,Decode 是否正常生成。

这一步最容易出问题的地方是网络配置。如果 Prefill 和 Decode 在不同节点,确保它们之间的端口是通的,防火墙没拦。我遇到过折腾半天发现是安全组没开端口的情况,白白浪费一下午。

跑通单请求后,逐步增加并发,观察延迟和吞吐的变化曲线。如果并发一上来性能就崩,多半是传输层或者调度出了问题。

5. 那些让我熬夜的坑

5.1 传输带宽被吃满

第一次上 PD 分离时,我按理论值算了带宽需求,觉得千兆网够用。结果一压测,KV Cache 传输直接把网卡打满,Decode 端等数据等到超时。

后来才想明白,理论值算的是平均带宽,但实际传输是突发的。Prefill 算完一批 KV Cache,会瞬间产生一个传输高峰,这个峰值带宽可能是平均值的几倍。所以网络容量要按峰值留余量,至少留 2 到 3 倍。

5.2 显存碎片导致 OOM

KV Cache 在 Decode 端需要显存来存放,如果显存管理没做好,跑一段时间就会出现碎片,明明总显存够用,却分配不出连续空间,直接 OOM。

解决办法是用分页显存管理,把 KV Cache 切成固定大小的块,按块分配,避免大块连续分配。vLLM 的 PagedAttention 就是干这个的,一定要开启。

5.3 调度器的状态不一致

分布式调度器最容易出的问题是状态不一致:调度器以为某个实例空闲,实际它已经排队了。结果请求分过去,延迟飙升。

根因通常是状态同步有延迟。解决办法是缩短心跳间隔,同时在调度时加一层"乐观锁"——分配前再确认一次实例状态。这个额外确认会增加一点开销,但比请求分错地方强。

5.4 长 prompt 的特殊处理

超长 prompt(比如 32K 以上)的 Prefill 会占用大量资源,如果和普通请求混在一起调度,会把普通请求全堵住。

我的做法是给长 prompt 单独开一条队列,用专门的 Prefill 实例处理,和普通请求隔离。这样长 prompt 慢就慢,不影响其他用户。

6. 什么情况下 PD 分离反而拖后腿

6.1 低负载场景

如果你的服务 QPS 很低,GPU 本来就闲着,PD 分离带来的传输开销和调度复杂度纯属负担。这种场景下混部简单直接,性能也够用。

判断标准很简单:如果混部时 GPU 利用率长期低于 50%,说明负载不够,没必要分离。

6.2 短序列场景

如果输入输出都很短(比如分类任务、短问答),KV Cache 本身就很小,传输开销占比低,分离的收益不明显,反而增加了架构复杂度。

6.3 网络条件差

如果 Prefill 和 Decode 之间的网络带宽有限或者延迟高,KV Cache 传输会成为瓶颈,分离后的性能可能还不如混部。这种情况下要么改善网络,要么放弃分离。

提示:上 PD 分离前,先用小规模流量做 A/B 测试,对比分离前后的吞吐和延迟。数据说话,别凭感觉。

7. 一些实战中的调优心得

7.1 监控要到位

PD 分离后,链路变长了,出问题的环节也多了。必须把每个环节的指标都监控起来:Prefill 的排队时间、计算时间、KV Cache 传输时间、Decode 的等待时间、生成时间。哪个环节是瓶颈,一眼就能看出来。

我习惯用一张链路耗时分解图,把每个请求的各阶段耗时画出来,瓶颈一目了然。这个图在排查问题时特别有用。

7.2 压测要贴近真实

压测时别只用固定长度的请求,真实负载的输入输出长度是变化的。用真实流量的分布来压测,才能暴露真实问题。我一般会从生产环境采样一批请求,脱敏后作为压测集。

7.3 灰度上线

PD 分离是个架构级改动,别想着一次性全量切换。先灰度一小部分流量,观察稳定性和性能,确认没问题再逐步放量。灰度期间保留混部通道,出问题能快速回滚。

7.4 参数调优的顺序

调优要有顺序,别东一榔头西一棒子。我的顺序是:先调传输层(确保不是瓶颈),再调调度策略(让负载均衡),最后调批处理参数(优化吞吐和延迟的平衡)。顺序错了,可能在一个不是瓶颈的地方使劲,白费功夫。

8. 关于 PD 分离未来的一些判断

从目前的技术演进看,PD 分离正在从"可选优化"变成"标配架构"。越来越多的推理引擎原生支持,传输方案也越来越成熟。但它的复杂度是实打实的,不是所有团队都需要。

我的判断是,当你的推理服务达到一定规模——比如需要多卡多节点、对延迟有明确 SLA、GPU 利用率需要压榨到 60% 以上——PD 分离就是值得投入的。规模不到这个程度,先把混部调优做好,收益可能更直接。

另外,KV Cache 的压缩和量化技术也在发展,未来 KV Cache 变小了,传输压力也会小,PD 分离的门槛会进一步降低。但那是后话,眼下还是得老老实实把传输和调度这两块啃下来。

我在实际项目里最大的体会是:PD 分离的难点不在"拆",而在"接"。拆开两个阶段是明面上的事,真正花时间的是把 KV Cache 的传输、调度器的状态同步、显存的管理这些衔接环节做扎实。这些环节任何一个出问题,整套架构的性能就上不去。所以如果你准备上 PD 分离,把至少一半的精力放在衔接环节的设计和验证上,别只盯着 Prefill 和 Decode 各自的优化。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 23:53:54

基于24577张图像的光伏板检测:YOLO训练与RK3588部署实战

简介:本资源为面向YOLO目标检测学习者的太阳能光伏板检测数据集,适合从事新能源运维、智能巡检及计算机视觉方向的研究者与开发者,用于训练和验证光伏板识别与缺陷检测模型。压缩包共收录2000个文件,以XML标注文件为主&#xff0c…

作者头像 李华
网站建设 2026/9/28 23:50:30

MIPI双模协议深度解析:DPHY与CPHY底层差异与调试实战

1. 为什么今天必须搞懂MIPI双模——不是选DPHY还是CPHY,而是看懂协议底层逻辑MIPI联盟的CSI-2接口在车载、手机、工业相机领域已经不是“可选项”,而是“必选项”。但真正落地时,工程师常被两个词反复卡住:DPHY和CPHY。很多人以为…

作者头像 李华
网站建设 2026/9/28 23:47:28

箱体目标检测数据集实战:YOLO格式解析与训练避坑指南

简介:箱体目标检测数据集面向物流仓储、工业制造、机器人抓取及运输零售等场景的算法开发者与研究者,提供真实环境下的箱体识别训练素材,可直接用于YOLO系列等主流目标检测框架的模型训练与评估。资源包共1568个文件,包含783张jpg…

作者头像 李华
网站建设 2026/9/28 23:43:41

无障碍测试实战:从TalkBack到Appium的完整流程指南

1. 无障碍测试的前置认知:它解决的是"被挡在门外的人"先说个我自己遇到的事。去年给一款金融类App做无障碍适配,测试机上装了TalkBack,我第一次戴着耳机、闭着眼睛、顺着语音提示去走一遍"转账"的核心流程,结…

作者头像 李华
网站建设 2026/9/28 23:41:56

Ubuntu虚拟机搭建Hadoop伪分布式集群:SSH免密与共享文件夹配置指南

简介:这份资源面向大数据入门学习者与高校云计算课程学生,提供在Ubuntu系统上从零搭建Hadoop分布式环境的完整教程,覆盖虚拟机安装、SSH免密登录、共享文件夹挂载、JDK环境配置、Hadoop安装与参数调优、环境变量设置等关键环节,帮…

作者头像 李华
网站建设 2026/9/28 23:40:36

Java Swing捕鱼达人:面向对象与游戏开发实战

简介:这是一份基于Java开发的「捕鱼达人」休闲游戏完整实现项目,面向Java初学者与游戏开发入门者,帮助理解面向对象设计、图形界面编程及游戏逻辑架构。资源包含223个文件,以60个核心Java源码(如FishManager、CannonMa…

作者头像 李华