当前位置: 首页 > news >正文

vllm学习笔记之 PD分离 kv connector

目录

    • Disaggregated Prefilling
      • 什么是Disaggregated Prefilling
      • PD分离的两大好处/原因
        • 1. 分别优化首 token 延迟(TTFT)和 token 间延迟(ITL)
        • 2. 控制Tail ITL
      • vllm中的--kv-transfer-config参数设置
        • kv_connector
        • kv_role
    • KVConnectorBase_V1 class模板解析
    • 学习资料参考

vllm官方文档中部署PD分离的参数说明:https://docs.vllm.ai/en/latest/features/disagg_prefill.html?h=kv_connector 英文名叫做disaggregated prefilling,即预填充/解码分离。

Disaggregated Prefilling

Prefill 阶段:把用户给的 prompt(输入)喂给模型,一次性处理全上下文,生成一批 KV cache。它在计算上“重”的特点多(因为整个 prompt 都参与 attention、很多操作),但在生成阶段结束后,它的输出(KV cache)会被后续重用。Prefill阶段的计算复杂度是O(N^2)
Decode 阶段:模型基于前面生成/缓存的结果,一次一个 token 地继续生成输出的新内容。由于可以复用prefill阶段预先计算好的kv cache,复杂度降到O(N)。
如果prefill和decode阶段混在一起,Prefill 在占用大量计算资源的时候,可能会“抢”decode 所需的资源(GPU 时间/memory bandwidth),导致 decode 变慢,影响实时性。Decode 又可能在等待 prefill 完成,或者受到 prefill 执行的不确定延迟影响。

什么是Disaggregated Prefilling

将prefill和decode放在两个节点上,可以是两个不同的计算单元,两个不同的进程。 prefill 放在一个专用资源池/机器上,优化它的吞吐(batching、长 prompt 支持等)。 decode 放在另一个池/机器上,优化实时生成、token-by-token延迟。前端系统只需要将 prefill 阶段产生的 KV cache 传输给 decode 端即可,资源利用更高效、两阶段互不干扰、可以按负载独立扩展。

在这里插入图片描述

PD分离的两大好处/原因

1. 分别优化首 token 延迟(TTFT)和 token 间延迟(ITL)

PD分离的 prefill 机制让大模型推理的 prefill 阶段和 decode 阶段运行在不同的 vLLM 实例中。
这样你就可以灵活地为它们分配不同的并行策略(例如 tensor parallelism、pipeline parallelism),从而单独调节 TTFT 而不影响 ITL,或者反过来单独优化 ITL 而不影响 TTFT。

2. 控制Tail ITL

在没有使用disaggregated prefill 的情况下,vLLM 可能会在某个请求的decode过程中插入新的 prefill 任务,这会让尾部延迟变高。使用disaggregated prefill 可以避免这种情况,帮助更好地控制tail ITL。虽然“分块 prefill(chunked prefill)”也可以达到类似效果,但在实际中很难精确选择合适的 chunk 大小。因此,disaggregated prefill 是一种更稳定可靠的方式。

注意:对提高throughput无用。

vllm中的–kv-transfer-config参数设置

使用例子
--kv-transfer-config '{"kv_connector":"OffloadingConnector","kv_role":"kv_both","kv_connector_extra_config":{"block_size": 64, "num_cpu_blocks": 1000}}'

kv_connector
• 含义:选择用哪一种机制来在 prefill 节点和 decode 节点之间传输或者存储 KV 缓存。
• 选择考量:○ 如果部署在同一台机器/同一 GPU 上,可能用 SharedStorageConnector 就足够。○ 如果有跨 GPU/跨节点传输,或者想用高性能传输(比如 NVLink、RDMA),就可能使用 NixlConnector 或 P2pNcclConnector。○ 如果目标是释放 GPU 显存,把 KV 缓存卸载到 CPU 上,也可用 OffloadingConnector。
• 适用场景示例:○ 单机但用两卡分担 prefill + decode → SharedStorageConnector。○ 多机/有高速互联 → NixlConnector。○ 显存受限但 CPU 容量大 → OffloadingConnector。
kv_role
• 含义:标识当前运行实例是“产生 KV”的那一方还是“使用 KV”的那一方。
• 考量:○ Prefill 节点为 kv_producer,它生成 KV 缓存。○ Decode 节点为 kv_consumer,它接收并使用已生成的 KV 缓存。○ 设置为 kv_both,表示该实例可能既生成又使用 KV,适用于单机/无分离部署。
• 选择场景:○ 完全分离部署:一侧只做 prefill,另一侧只做 decode。○ 传统部署(prefill+decode 在同一进程内):可以用 kv_both。
  • 适合的场景:
    多用户/高并发、大批量 prompt,同时生成任务也多。
    Prompt 长度很长、需要做较大的 prefill 批量计算。比如多轮对话场景等。
    生成阶段要求低延迟/高吞吐。
    硬件资源可以分成预填充专用节点 + 生成专用节点。
    网络/存储传输 KV 缓存的成本可控。
  • 不太适合或需谨慎的场景:
    Prompt 很短、或者几乎都是 “小 prompt +快速生成” 的轻量任务,此时 prefill/ decode 混在一起可能更简单更快。
    无法保证两端之间传输 KV cache 有足够带宽或低延迟。传输成本高反而抵消分离带来的收益。
    硬件资源受限,无法独立地为 prefill & decode 分配节点。
    系统对复杂部署(多节点、缓存传输、同步机制)不熟悉、维护成本较高。

KVConnectorBase_V1 class模板解析

KVConnector 是 “prefill → decode” 之间传输 KV 缓存的桥梁,除了使用vllm已经提供的几种kv connector外,我们也可以自定义结合硬件的kv connector, 参考vLLM v1 中实现 KV Connector 的模板接口(KVConnectorBase_V1)。主要要求实现以下内容:
Scheduler 端(调度器)要怎么跟 worker 协作
Worker 端(执行推理的 GPU 节点)要怎么加载/保存 KV
以及两边之间如何通信、同步状态

Scheduler vs Worker

class KVConnectorRole(enum.Enum):SCHEDULER = 0WORKER = 1

Scheduler 端:掌握全局状态,知道哪些请求要分配、哪些已经完成
Worker 端:真正运行模型 forward() 的那台机器(GPU worker)
每个 connector 都在这两边各有一个实例,互相协作。

Scheduler side method(调度器逻辑)

方法名功能作用阶段
get_num_new_matched_tokens()询问当前请求还能从外部 KV 加载多少个 tokenScheduler 在分配显存前调用
update_state_after_alloc()通知 connector:显存块已经分配好,可以加载了调度器分配 buffer 后
build_connector_meta()生成 metadata(元信息),发给 Worker,用来指导加载Prefill → Decode 之间
request_finished()通知 connector 请求完成,是否需要异步保存 KV生成完毕后清理

Worker Side Method 实际的执行者

方法名功能说明
bind_connector_metadata()绑定 scheduler 发来的 metadata每次执行前
start_load_kv()异步加载 KV 缓存(可以边加载边算)Prefill → Decode 过渡
wait_for_layer_load()等待某一层 KV 加载完解码过程中,确保同步
save_kv_layer()异步保存某层 KV(Prefill 结束时)反方向传输
wait_for_save()等待所有层保存完成避免覆盖数据
get_finished()通知哪些请求的 KV 传输已完成异步确认状态

Metadata:
存kvcache的tokenid blockid定位,存一些存储状态。目的是让worker找到并加载kv cache。
以下是vllm V1中SharedStorageConnectorMetadata的实现。

class ReqMeta:# Request tokenstoken_ids: torch.Tensor# Slot mappings, should have the same length as token_idsslot_mapping: torch.Tensor# Is store or loadis_store: bool@staticmethoddef make_meta(token_ids: list[int], block_ids: list[int], block_size: int,is_store: bool) -> "ReqMeta":valid_num_tokens = align_to_block_size(len(token_ids), block_size)token_ids_tensor = torch.tensor(token_ids)[:valid_num_tokens]block_ids_tensor = torch.tensor(block_ids)num_blocks = block_ids_tensor.shape[0]block_offsets = torch.arange(0, block_size)slot_mapping = block_offsets.reshape((1, block_size)) + \block_ids_tensor.reshape((num_blocks, 1)) * block_sizeslot_mapping = slot_mapping.flatten()[:valid_num_tokens]return ReqMeta(token_ids=token_ids_tensor,slot_mapping=slot_mapping,is_store=is_store,)@dataclass
class SharedStorageConnectorMetadata(KVConnectorMetadata):requests: list[ReqMeta]def __init__(self):self.requests = []def add_request(self,token_ids: list[int],block_ids: list[int],block_size: int,is_store: bool,) -> None:self.requests.append(ReqMeta.make_meta(token_ids, block_ids, block_size, is_store))

学习资料参考

https://devpress.csdn.net/aibjcy/68d01bfa8867235e1386e0dd.html?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogOpenSearchComplete%7Eactivity-1-151937207-blog-154493882.235%5Ev43%5Epc_blog_bottom_relevance_base9&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogOpenSearchComplete%7Eactivity-1-151937207-blog-154493882.235%5Ev43%5Epc_blog_bottom_relevance_base9&utm_relevant_index=1

http://www.dtcms.com/a/581744.html

相关文章:

  • 有经验的佛山网站设计东莞华为外包公司
  • 什么是AIGC的创作者?
  • 51单片机基础-GPIO结构详解
  • 织梦系统如何做网站专属头像制作免费
  • 2025高校网络安全管理运维赛--电子取证分析师赛道-决赛WriteUp
  • 蒲公英异地组网路由器全新固件:4G联网、策略路由、日志管理升级
  • 网站建设规划总结做高考题的网站
  • wordpress网站被镜像wordpress邮件功能用不了
  • (111页PPT)智能工厂总体设计方案(附下载方式)
  • sh -c
  • 在若依框架中修改了 Vue 路由的 base 路径后,还需要修改以下几个地方才能正常访问?
  • Spring Boot 注册登录接口进阶(bcrypt密码加密 + Apifox 测试)
  • 重庆住房城乡建设厅官方网站自己做直播网站
  • 服装网站制作网站建设需要的条件
  • 【把Linux“聊”明白】编译器gcc/g++与调试器gdb/cgdb:从编译原理到高效调试
  • LeetCode算法日记 - Day 96: 最长回文子串
  • 汽车ECU诊断刷写和OTA升级中的验签和校验
  • 网站主题旁边的图标怎么做的套模板网站
  • x265 编码器Analysis::compressInterCU_rd0_4 函数详细分析
  • 小杰-大模型(two)——RAG与Agent设计——Langchain-prompt提示词
  • Rust 练习册 :Luhn Trait与Trait实现
  • 家庭机器人,从科幻到日常的二十年突围战
  • 网站html地图导航代码大全网站功能的介绍
  • Android开发(Kotlin) 高阶函数、内联函数
  • AI安全与网络安全的融合:从挑战到解决方案
  • 从零开始构建现代化React应用:最佳实践与性能优化
  • 国外的网站建设公司广州工商注册服务中心
  • 【tips】常用不同状态小圆点样式css
  • 保险微网站制作公司网站费用计入什么科目
  • SSM网上水果商城s7436(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。