vLLM PD 分离实战:从请求流程理解 Prefill、Decode 与 KV Cache 传输

vLLM PD 分离实战:从请求流程理解 Prefill、Decode 与 KV Cache 传输

💡 原文中文,约12700字,阅读约需31分钟。
📝

内容提要

本文介绍如何用 vLLM、NixlConnector 和 toy Proxy 搭建单容器 PD 分离 Demo:Proxy 将请求改写为 max_tokens=1 发给 Prefill,Prefill 计算 Prompt 并生成 KV Cache,返回临时 Token 和传输元数据;Proxy 丢弃 Token,携带 kv_transfer_params 转发给 Decode;Decode 通过 NIXL 从 Prefill 拉取 KV Cache 并继续生成,结果经 Proxy 返回客户端。日志中 Num successful transfers=1 可确认传输成功。

🔎

延伸解读

控制流与数据流分离:Proxy 与 NIXL 各司其职

文章明确区分了两条链路:控制请求通过 Proxy 的 HTTP 端口在 Prefill 和 Decode 之间转发,而 KV Cache 数据不经过 Proxy,由 Decode 根据元数据通过 NIXL 直接从 Prefill 拉取。这意味着 Proxy 只负责请求编排和参数改写,Connector/NIXL 负责实际的数据传输。理解这一分工,有助于排查问题时快速定位是编排层还是传输层出现异常。

单容器 Demo 的边界:简化环境不等于合并实例

Demo 将 Prefill、Decode 和 Proxy 放在同一个容器、同一张 GPU 上,HTTP 地址和 NIXL 地址都表现为回环地址。但文章强调,Prefill 和 Decode 仍是两个独立的 vLLM 实例,分别监听不同端口,拥有各自的 KV Cache 管理和 NIXL Connector。这种简化降低了环境准备和网络配置的复杂度,适合观察请求与 KV Cache 流向,但不能据此推断生产环境中的网络与调度行为。

验证传输成功:不能只看 HTTP 200

文章指出,HTTP 200 只能证明接口返回成功,还需要结合 Decode 日志确认 KV Cache 传输。关键证据是 Decode 日志中的 Num successful transfers=1,它表示 Decode 侧至少完成了一次 NIXL KV Cache 传输。NIXL compatibility check passed 仅说明两端配置兼容,不能单独证明本次请求已完成传输。因此,验证 PD 分离是否真正生效,应同时检查传输计数和请求日志。

从 Demo 到生产:关注点会从“能否传输”转向“如何管理”

文章提醒,Demo 只有一个 Prefill、一个 Decode,且同容器同 GPU,而生产环境面临更多挑战:KV Cache 的生命周期、释放回收、超时重试与跨节点带宽;多实例下的 P/D 调度与容量配比;Prefill 成功但 Decode 失败等故障处理;以及性能与可观测性。PD 分离主要解决 Prefill 和 Decode 相互干扰的问题,让 TTFT 和 ITL 可分别优化,但代价是多了一层调度和传输,需要判断收益是否大于成本。

❓

Q&A

vLLM PD 分离中,Prefill 和 Decode 分别负责什么?

Prefill 负责计算完整 Prompt 并生成 KV Cache,同时返回一个临时 Token 和 KV Transfer 元数据;Decode 负责根据元数据通过 NIXL 拉取 KV Cache,并基于已有上下文继续逐 Token 生成最终结果。

PD 分离 Demo 中,Proxy 是如何改写请求并转发给 Prefill 和 Decode 的?

Proxy 先将客户端请求改写为 max_tokens=1 发送给 Prefill;Prefill 返回临时 Token 和 KV Transfer 元数据后,Proxy 丢弃临时 Token,取出 kv_transfer_params 覆盖到原始请求上,并恢复客户端要求的 max_tokens,再发送给 Decode。

KV Cache 在 PD 分离中是如何从 Prefill 传输到 Decode 的?

KV Cache 不经过 Proxy,而是由 Decode 根据 Prefill 返回的元数据(如 remote_engine_id、remote_request_id、remote_block_ids、NIXL side channel 地址和端口等),通过 NIXL 直接从 Prefill 拉取。

如何确认 PD 分离中 KV Cache 传输成功?

可以查看 Decode 日志,出现“KV Transfer metrics: Num successful transfers=1”即表示 Decode 侧至少完成了一次 NIXL KV Cache 传输;同时 Prefill、Decode 和 Proxy 的请求日志都应返回 200 OK。

为什么最终返回给客户端的响应中 kv_transfer_params 为 null?

因为 kv_transfer_params 是 KV Transfer 元数据,只在 Proxy 内部从 Prefill 传给 Decode,用于定位和拉取 KV Cache;最终响应是 Decode 生成并返回给客户端的,所以其中的 kv_transfer_params 为 null 是正常的。

PD 分离在生产环境中面临哪些主要挑战?

主要挑战包括:KV Cache 管理(生命周期、释放回收、超时重试、跨节点带宽开销)、P/D 实例调度(根据负载和缓存命中选择实例)、P/D 容量配比与扩缩容、故障处理(重试、状态清理、缓存回收),以及性能与可观测性(关注排队时间、传输耗时、带宽和失败情况,判断拆分收益是否大于成本)。

🏷️

标签

➡️

继续阅读