跳到内容

分离式预填充(实验性)

本页面将介绍 vLLM 中的分离式预填充功能。

注意

此功能为实验性功能,可能会有所更改。

为何使用分离式预填充?

两个主要原因

  • 独立调整首词时间 (TTFT) 和词间延迟 (ITL)。分离式预填充将 LLM 推理的预填充阶段和解码阶段置于不同的 vLLM 实例中。这使您能够灵活地为不同的并行策略(例如 tppp)分配,以在不影响 ITL 的情况下调整 TTFT,或在不影响 TTFT 的情况下调整 ITL。
  • 控制尾部 ITL。在没有分离式预填充的情况下,vLLM 可能会在请求解码期间插入一些预填充任务。这会导致更高的尾部延迟。分离式预填充有助于您解决此问题并控制尾部 ITL。使用适当分块大小的分块预填充也可以实现相同的目标,但在实践中很难确定正确的块大小值。因此,分离式预填充是控制尾部 ITL 的更可靠方法。

注意

分离式预填充并不能提高吞吐量。

使用示例

请参考 examples/online_serving/disaggregated_prefill.sh 以获取分离式预填充的使用示例。

性能基准

请参考 benchmarks/disagg_benchmarks 以获取分离式预填充的性能基准。

开发

我们通过运行 2 个 vLLM 实例来实现分离式预填充。一个用于预填充(我们称之为预填充实例),另一个用于解码(我们称之为解码实例),然后使用连接器将预填充的 KV 缓存和结果从预填充实例传输到解码实例。

所有分离式预填充的实现都在 vllm/distributed/kv_transfer 目录下。

分离式预填充的关键抽象

  • 连接器:连接器允许 KV 消费者KV 生产者 检索一批请求的 KV 缓存。
  • 查找缓冲区:查找缓冲区提供两个 API:insert KV 缓存和 drop_select KV 缓存。insertdrop_select 的语义类似于 SQL,其中 insert 将 KV 缓存插入到缓冲区中,drop_select 则返回与给定条件匹配的 KV 缓存并将其从缓冲区中删除。
  • 管道:一个用于张量传输的单向 FIFO 管道。它支持 send_tensorrecv_tensor

注意

insert 是非阻塞操作,而 drop_select 是阻塞操作。

下图展示了上述 3 种抽象的组织方式

Disaggregated prefilling abstractions

分离式预填充的工作流程如下

Disaggregated prefilling workflow

buffer 对应于 LookupBuffer 中的 insert API,而 drop_select 对应于 LookupBuffer 中的 drop_select API。

第三方贡献

分离式预填充与基础设施高度相关,因此 vLLM 依赖第三方连接器来实现生产级别的分离式预填充(vLLM 团队将积极审查并合并用于第三方连接器的新 PR)。

我们推荐以下三种实现方式

  • 完全定制的连接器:实现您自己的 Connector,并调用第三方库来发送和接收 KV 缓存,以及更多功能(例如修改 vLLM 的模型输入以执行定制的预填充等)。这种方法提供了最大的控制权,但存在与未来 vLLM 版本不兼容的风险。
  • 数据库式连接器:实现您自己的 LookupBuffer,并像 SQL 一样支持 insertdrop_select API。
  • 分布式 P2P 连接器:实现您自己的 Pipe,并像 torch.distributed 一样支持 send_tensorrecv_tensor API。