费曼视角|PD分离:谁修了路,却没收到过路费
谁修了那条路,却没收到过路费:用费曼的眼镜看 PD 分离与计费黑洞 题注:以下用费曼的镜片看事,基于公开言论与可检索事实推断,绝非费曼本人观点。老头 1988 年就走了,不会搞大模型,也不会写中文。 先说个画面。 一座收费亭。卡车开过来,亭子里的人看了一眼货单,说:「这批货你上周就存进我们仓库了,按『已入库』算,便宜走。」刷一下,放行。 可事实上,这批货从来没进过仓库。是另一座城的分厂,连夜把这整批货的「影子」拷贝了一份,用专线运到了这座收费亭。真正的搬运、真正的成本,发生在分厂那头。可收费亭只认自己眼前的「货已经在」这个状态——于是整批货按最便宜的价格过了关,分厂那头干活的工钱,没人付。 你猜怎么着?这座收费亭,正是大模型推理服务里干「计费」的那个模块。那批「货的影子」,就是 KV Cache。那座连夜干活的「分厂」,就是 Prefill 节点。 先别背名字,看它到底在干嘛 大伙儿一张嘴就是「Prefill」「Decode」「PD 分离」「KV Connector」——一串名词。费曼的父亲会皱眉:你知道这鸟叫什么不等于你懂这只鸟。 剥掉名字,大模型生成文字,本质就两步: 第一步,Prefill(预填充)。 把用户整段提问一次性塞进模型,并行算出每个词对应的 KV Cache(键值缓存)。这一步是大矩阵乘法,吃算力,瓶颈在 GPU 的浮点运算能力。每个请求只发生一次,像你为了写篇长文,先把整本参考书一口气读完、划满重点。 第二步,Decode(解码)。 基于那份划好重点的笔记,一个词一个词往外蹦。每蹦一个词,都得回头翻一遍前面所有重点。这一步吃显存带宽,瓶颈在 HBM 内存带宽。它占掉请求整体延迟的大头,像你写文章时,每落一个字,都要重翻一遍那本划满线的书。 一句话:Prefill 是「一口气读完、做满笔记」(算力活);Decode 是「逐字写、每字都翻笔记」(带宽活)。两种活,两种瓶颈,天生就该分开养。 为什么不分开就别扭 传统部署把两步塞同一台机器。问题来了:Prefill 那一下大矩阵乘法,会卡住正在跑的 Decode 流,于是 ITL(词间延迟)忽高忽低、像发了癫。更糟的是资源闲置——Prefill 时显存闲着,Decode 时算力闲着。 PD 分离的做法:Prefill 节点专跑算力活,算出 KV Cache;Decode 节点专跑带宽活,消费那份 KV Cache 往外生成。中间靠 NIXL、LMCache、Mooncake 这类连接器,把 KV Cache 从 P 节点搬到 D 节点。两边从此各算各的账:独立扩缩容、用不同型号硬件、各自配最优 batch size。 听起来清爽。可清爽之下,埋了个计费黑洞。 黑洞长这样 计费系统对 token 分三档:输入价、输出价、缓存命中价。缓存命中价远低于输入价——因为「命中前缀缓存」意味着这部分算力你省了,收费自然该打折。 判断「命中没命中」的依据,是返回字段 prompt_tokens_details.cached_tokens——它数的是请求里有多少 token 命中了已有 KV Cache。 坑就在这:PD 分离下,Prompt 真正的 Prefill 计算发生在 Prefill 节点,算完把整段 KV Cache 经连接器搬到了 Decode 节点。从 Decode 节点的视角看,整段 Prompt 的 KV Cache 都「已经在这了」,于是它把整段都报成「缓存命中」。 计费模块若只看 Decode 侧回报的 cached_tokens,就会把整个 Prompt 按缓存命中价收费。而真正付出算力成本的 Prefill 计算,压根没被算进「输入 token」那一档。 结果:每天少收一大笔钱。Prefill 节点白干了修路的活,收费亭却按「路早修好了」的廉价档把车放走了。 这不是我瞎猜。vLLM 社区早在一堆 PR / Issue 里吵这事。我专门去核验了—— vLLM RFC #24256(题名 Add a cache hit threshold to handle Preemptions in PD-Disaggregation),原文明写:缓存命中率「includes cache from external and previously offloaded KV-Cache, obtained via the KVConnector, and not just the local APC」。即:跨实例迁移来的 KV,确实会被算进「命中」。这正是黑洞的源头。 配套的 PR #24520 落地了这个「缓存命中阈值」,核心思路就是要把「本地 APC 命中」和「来自外部连接器的迁移缓存」区分开,让路由层能据此做准入控制——说白了,就是想把这种跨实例迁移的缓存行为,重新纳入「可计量、可计费」的范畴。 一个刚发生的、极妙的佐证 我顺手核了下大家最爱举的那个价目例子——DeepSeek V4-Pro。你给的数「命中 0.025 元 / 百万、未命中 3 元、差 120 倍」,是 2026 年 8 月 17 日涨价前的旧价,确有其事。 但八天前(2026-08-17),DeepSeek 动手大调价,且峰谷定价。看清这组数: 档位 缓存命中(元/百万) 缓存未命中(元/百万) 价差倍数 8-17 前旧价 0.025 3 120 倍 8-17 后·低谷 0.15 4.5 30 倍 8-17 后·高峰 0.3 9 30 倍 注意两件事: 其一,缓存命中价涨了 1100%(12 倍),是所有档位里涨幅最猛的。 一个推理厂商,为什么突然把「便宜档」的价格拔高十倍?合理的解释是:缓存命中这块,过去被严重低估,而它恰恰是利润与风险的交叉点。厂商自己都在拼命把「命中」的账算清楚——这从商业侧反证了:缓存命中计费,是命脉。 其二,黑洞的「绝对漏损」反而更大了。 旧价下,把 100 万「本该按未命中收」的 token 误记成命中,少收 3 − 0.025 = 2.975 元;新价低谷下少收 4.5 − 0.15 = 4.35 元,高峰下少收 9 − 0.3 = 8.7 元。倍数从 120 倍缩到 30 倍,可每漏一个 token,丢的真金白银是原来的 1.5 到 3 倍。黑洞没变小,它只是换了个形状,吞得更狠。 (另注:8-23 起周末全天改按低谷价,但这不改上面的结论。) 一句话收住 PD 分离,是把「读书记笔记」和「动笔写文章」拆给两台机器干的聪明架构。可它顺手制造了个假象:Decode 节点把从 Prefill 节点「搬来的整段笔记」当成了「我本来就有的缓存」,计费模块因此把整段 Prompt 按最便宜的命中价放过——干活的分厂没拿到工钱,收费亭还以为自己捡了便宜。 大自然不会被你骗,账却会被你骗——直到月底对账,或者直到厂商把命中价涨十二倍,你才发现那道缝里漏掉的是一片海。 所以费曼会问的那句:「你报告里的那个 cached_tokens,到底是『本地真命中』,还是『别人替你算完搬过来的』?分清楚之前,别急着说你算明白了。」 That's all there is to it.生成时间: 2026-08-25 00:45 · 源文件 SHA256: 30bcbbce40688933 · 步子哥 · 费曼视角