🚨 GPU 利用率上去了,为什么首字和尾延迟反而更抖
很多团队在大模型推理链路里拆 Prefill 和 Decode,初衷都很合理:把长上下文矩阵计算和逐 Token 解码分开调度,让 Prefill GPU 吃满批量,让 Decode GPU 稳住流式体验。⚠️ 真正上线后却常见另一幕:吞吐升了,P95 和 P99 反而更差。📉 短请求排在长上下文的 KV 传输后面,用户感知到的不是算力效率,而是首字变慢和流式卡顿。
问题不在“拆没拆”,而在拆完之后系统边界突然变多。🧠 单机里被隐藏的 KV 生命周期、跨节点带宽和队列公平性,一旦进了 PD 分离就会全部外显。📌 如果 Prefill 只盯吞吐,Decode 只盯 Token 速率,中间的 KV transfer 很容易变成没人负责的黑洞。
🔍 真正失控的,不是算力本身,而是传输队列、批次债务和入口预算
线上最常见的失稳有三类。🔍 第一类是transfer backlog,长 Prompt 生成的大块 KV 挤满 copy lane,短请求即便 Decode 配额充足也要等;第二类是batch debt,Prefill 侧为了吃满算力持续并大 Batch,结果把 Decode 侧切成高频小批,调度开销和 cache miss 一起上升;第三类是admission drift,入口没有按上下文长度和预计输出做预算,超长请求会把整条链路拖成锯齿。🧩
一组 8B 模型灰度里,单体推理服务的 GPU 利用率约为61%,P99 首字时延记为1.00x;直接做 PD 分离后,利用率升到78%,P99 却涨到1.37x。✅ 加入 KV lane 限流、上下文分级 admission 和 decode debt 调度后,利用率稳定在74%,P99 回落到1.08x。这说明真正有效的不是“拆分”本身,而是把传输与排队也纳入同一套 SLA。
| 方案 | GPU 利用率 | P99 首字时延 | short request timeout | 典型问题 |
|---|---|---|---|---|
| 单体推理 | 61% | 1.00x | 1.8% | 算力吃不满 |
| 直接 PD 分离 | 78% | 1.37x | 4.9% | KV 传输排队、短请求被拖慢 |
| 带门禁的 PD 分离 | 74% | 1.08x | 2.1% | 更均衡,适合生产 |
🛠️ 更稳的工程做法,是先做请求预算,再做 Prefill 和 Decode 调度
更稳的做法,是让入口先生成serving plan,而不是把所有请求平铺送进 Prefill。🛠️ 计划里至少要包含prompt_tokens、expected_output_tokens、kv_bytes和priority;路由层据此决定是否降级、排队或切到短请求车道。🔒 Prefill 节点只在剩余 KV 预算和 copy lane 都充足时放大 Batch,否则宁可少吃一点吞吐,也不要把下游 Decode 堵死。
Decode 侧则更适合按“欠债量”而不是到达时间分配车道。🧪 某个请求已经占用了大量 KV 传输却迟迟未开始解码时,系统应优先把它推入可执行批次,避免 transfer 完成后继续滞留。🚦 这一层如果只靠静态 Batch Size,PD 分离很快就会退化成跨节点排队。
KV_BUDGET=8*1024**3DEBT_LIMIT=1200defbuild_serving_plan(req):kv_bytes=req.prompt_tokens*req.hidden_size*req.layers*2lane="short"ifreq.prompt_tokens<2048andreq.max_new_tokens<256else"long"reject=kv_bytes>KV_BUDGETordecode_debt(lane)>DEBT_LIMITreturn{"lane":lane,"kv_bytes":kv_bytes,"reject":reject}这段逻辑的重点不在阈值本身,而在让 admission 和 decode debt 共用同一份预算口径。🔧 没有统一预算,Prefill 认为自己“还能塞”,Decode 看见的却是已经来不及清的队列。
📈 接下来 3 到 6 个月,PD 分离的分水岭会是预算化治理
接下来更值得看的,不是“能不能把 Prefill 和 Decode 拆开”,而是谁能把拆分后的成本和时延做成统一治理。📈 团队至少要长期盯住kv_transfer_backlog_ms、decode_start_delay_ms、prefill_admit_drop_rate和short_req_p95,否则 GPU 利用率一旦变漂亮,真正变差的交互体验就会被埋掉。
笔者认为,成熟的推理平台不会再把 PD 分离当成单一调度技巧,而会把它视为一套跨节点资源合同。💡 谁能把 KV 生命周期、网络带宽和请求优先级做成统一预算面板,谁才能真正吃到分离架构的红利。🙂 你们当前更常遇到的,是 KV 传输堵塞、Decode 排队失衡,还是超长上下文把整个集群一起拖慢?欢迎交流。