版本声明:本文分析基于 vLLM Ascend commit
215028c0bd94(2026-05-16)、vLLM commit504a26ce2be2(2026-05-17)与 Mooncake commit26b24565ffa9(2026-05-17);除非特别说明,以下描述均基于这些版本。
昇腾这篇 KV Pool 文章最有信息量的地方,是它把一个常见工程抱怨落到了接口层:如果 vLLM 要用 Mooncake 做共享 KV 池,继续走 vLLM -> LMCache -> Mooncake,调用链会把硬件最关心的数据路径藏在第三方抽象后面[1]。对昇腾来说,影响已经超过少一次函数调用:device 侧链路、NPU 内存注册、跨节点读写和 P/D 组合方式,能不能被同一个 connector 直接控制,才是这件事的关键。
代码演进能印证这个判断。vLLM Ascend 早在 2025 年 9 月的 #2913 就合入了 2033 行 Mooncake Store 直连接入,随后在 2026 年 2-3 月连续补上 sparse attention、HIXL FabricMem、Yuanrong 后端和 AscendMultiConnector 组合路径;vLLM 主仓 2026 年 5 月的 #40900 又把这套已验证的设计回流成通用 MooncakeStoreConnector,PR 规模达到 2600 行[2][3]。这条时间线说明,昇腾版本更像是一个先行试验场:先在 NPU 场景里把 KV pool 数据面跑通,再抽象回 vLLM 社区主线。
一、AscendStoreConnector 把 KV Pool 放进 vLLM V1 的正式路径
AscendStoreConnector 当前实现的是 vLLM V1 KVConnectorBase_V1,按 scheduler / worker 角色拆分:scheduler 侧创建 KVPoolScheduler,worker 侧创建 KVPoolWorker,rank 0 额外启动 LookupKeyServer,用 ZMQ IPC 接 scheduler 的前缀命中查询[4]。这点很关键:共享 KV 池没有被包装成普通 Python 库调用,它进入了 vLLM 调度循环原本就会调用的 get_num_new_matched_tokens、update_state_after_alloc、build_connector_meta、wait_for_save、get_finished。
从 scheduler 看,外部 KV 池参与的是“本轮还需要分配多少 token 的 block”这个问题。KVPoolScheduler.get_num_new_matched_tokens() 会先按 block size 截断到完整 chunk,再通过 LookupKeyClient 把 block hash 发给 worker rank 0 查询;如果外部命中 token 数大于本地已计算 token,就生成 LoadSpec,让 KVCacheManager 为这些外部 KV 预留 block[5]。共享 KV 池在调度阶段已经改变了分配决策,数据回填不再只是执行后的补救动作。
worker 侧的接口更像数据面。KVPoolWorker 当前支持 mooncake、memcache、yuanrong 三种后端,通过 backend_map 动态加载;同时把模型名、TP/PCP/DCP/PP rank 和 block hash 组合进 PoolKey,避免不同并行切分下的 KV 分片互相污染[6][7]。这里的工程含义是:KV pool 的 key identity 已经包含硬件并行拓扑,而不只是 prompt 内容 hash。
二、为什么“直连 Mooncake”对昇腾更重要
公众号文章里反复强调的路径差异,可以在 MooncakeBackend 里找到落点。当前 vLLM Ascend 的 Mooncake 后端只接受 protocol == "ascend";初始化时,如果没有打开 ASCEND_ENABLE_USE_FABRIC_MEM=1,它会从全局 transfer engine 取 engine 和 RPC port,再把 engine 交给 MooncakeDistributedStore.setup();如果打开 FabricMem,就把 local buffer size 设为 0,直接走统一内存地址传输方案[8]。
这和通用 GPU 路线的差别在于,昇腾希望 KV 数据尽量停留在设备侧可达的地址空间。vLLM Ascend 文档把 A3 FabricMem 的环境要求写得很硬:800 I/T A3 需要 HDK ≥ 25.5、CANN ≥ 9.0.0、LingQu Computing Network ≥ 1.5,并推荐 ASCEND_ENABLE_USE_FABRIC_MEM=1;Mooncake 配置里 global_segment_size 还要求按 1GB 对齐[9]。这些约束看起来繁琐,却说明这条路径的目标已经超出普通 host buffer offload:KV pool 要直接贴近 NPU 互联和内存注册机制。
Mooncake 主仓也在为这条路线补底座。Transfer Engine 初始化时,在 USE_ASCEND 或 USE_ASCEND_DIRECT 下会直接安装 ascend transport;本地内存注册会遍历所有已安装 transport 调用 registerLocalMemory(),把 buffer 暴露给传输层[10]。到了 Store 层,allocate_buffer_allocator_memory() 对 ascend / ubshmem 协议走 Ascend 专用内存分配;2026 年 5 月 #2005 还专门修了 Ascend FabricMem 模式下 SSD offload staging buffer 的协议感知分配问题[11]。换言之,Mooncake 已经不只是“RDMA 对象存储”,它正在把 Ascend FabricMem、UBShmem、SSD offload 这些路径变成 Store 可以识别的 tier。
三、Memcache 路线让后端抽象变得具体
AscendStoreConnector 的另一个信号来自 Memcache 后端。MemcacheBackend 通过 memcache_hybrid.DistributedObjectStore 初始化,在 A2 设备上还会先做一次 torch.distributed.all_gather 触发必要的设备侧准备;读写接口分别调用 batch_get_into_layers(..., COPY_G2L) 和 batch_put_from_layers(..., COPY_L2G)[12]。文档则要求先安装 MemFabric,再安装 Memcache,并在 mmc-local.conf 中选择 host_rdma、device_rdma 或 device_sdma;A2 推荐 device_rdma,A3 推荐 device_sdma[9]。
这组代码让“后端可插拔”变得具体。Mooncake 后端把对象存储和 Transfer Engine 合在一起;Memcache 后端更依赖昇腾生态里的 MemFabric 内存池化能力;Yuanrong 后端又走 openYuanrong datasystem,并对 key 做归一化以避开长度和字符限制[13]。三者共用的是 exists / get / put / register_buffer 这组最小接口,差异留在后端内部。这种拆分比把 Mooncake 写死成唯一远端 store 更稳,因为硬件插件真正需要控制的是数据路径,绑定某一个存储项目反而会缩小空间。
四、P/D 分离场景里,KV Pool 和 KV Transfer 是两件事
昇腾文档里的 P/D 配置很容易被误读。PD 分离时推荐用 MultiConnector 同时挂 MooncakeConnectorV1 和 AscendStoreConnector:前者负责 prefill 与 decode 之间的点对点 KV transfer,后者负责 prefix cache 对应的共享 KV pool[9]。这份配置的目的,是把两类 KV 移动拆开:一次请求内部的 P/D 交接,和多请求、多实例之间的前缀复用。
2026 年 3 月的 #7032 专门引入 AscendMultiConnector,让 mooncake_layerwise_connector 可以和 KV Pool 一起启用;#7022 又让 Mooncake layerwise connector 支持 hybrid attention manager 的多 KV cache group;#6627 则补了 PCP/DCP 感知[14][15][16]。这些 PR 的共同方向很明确:KV 传输已经不能假设“一个模型、一组 KV、一个 TP 维度”就足够,DeepSeek V3.2 这类 sparse / MLA / context parallel 组合会把 KV layout 切成多组,connector 必须理解这些分片边界。
KVPoolWorker 里也能看到这种复杂度。它会根据 MLA 或 sparse attention 调整 block length 计算;PCP/DCP 开启时,内部 block size 会乘上对应 parallel size;当 consumer 也需要回写 KV pool 时,还要处理 prefill PP 分层分区。由此带来的结果是,KV Pool 已经超过“把完整请求 KV 保存一次”的简单缓存形态,变成一套跟并行配置同步演化的分片对象系统。
五、vLLM 主仓 #40900 是一次反向验证
vLLM 主仓的 MooncakeStoreConnector 文件开头直接写着:它 adapted from vllm_ascend/distributed/kv_transfer/kv_pool/ascend_store/[17]。这很少见,也很有价值:硬件插件里的实现没有停留在厂商分支,反过来塑造了 vLLM 主线的通用 Mooncake Store 接入。
不过主仓版本和 Ascend 版本并不完全等价。vLLM 主仓当前的 Store connector 没有 layerwise support,start_load_kv() 与 wait_for_save() 是 no-op,load/store 被推迟到 get_finished() 中发出以争取 compute overlap;它还补了 disk offload staging buffer 的 batch split、replica tier 日志和 store pressure 保护[18]。Ascend 版本则保留了 layerwise 的 wait_for_layer_load() / save_kv_layer(),并要求 layerwise 模式下使用 piecewise graph,避免异步同步被整图捕获[19]。
这处差异说明了一个边界:社区主线先收敛出通用 Store 语义,硬件插件继续保留更贴近平台的传输时序。对用户来说,通用 vLLM 的 MooncakeStoreConnector 适合跨实例共享 KV pool;昇腾上的 AscendStoreConnector 则进一步把后端选择、FabricMem、MemFabric、layerwise 和 MultiConnector 组合放到同一套启动参数里。
六、这条路线的真实边界
我认为这篇昇腾文章应该按“架构重接”来读,单纯按“性能优化公告”来读会漏掉更重要的接口变化。它没有给出公开可复现的 TTFT 数字,v0.18.0 release note 只说 KV Pooling 相比前版本有 “huge performance optimization on TTFT”[20]。真正能被源码确认的是:connector 已经接入 vLLM V1 调度路径;后端抽象覆盖 Mooncake / Memcache / Yuanrong;Mooncake 路线支持 Ascend protocol 和 FabricMem;Memcache 路线暴露 device_rdma / device_sdma;P/D 场景通过 MultiConnector 把点对点 KV transfer 和共享 KV pool 拆成两个独立能力。
这也给使用者留下几个现实问题。第一,部署复杂度明显上升,Mooncake 路线需要 HCCN、Mooncake master、1GB 对齐的 segment、HIXL/FabricMem 环境变量和超时参数;Memcache 路线还要 MemFabric / Memcache meta/local service。第二,命中收益高度依赖 workload:系统 prompt、多轮对话、RAG 模板和 agent trace 会受益,短单轮随机请求很难摊薄 lookup 与传输开销。第三,多后端可插拔还没有自动策略层,什么时候选 Mooncake、Memcache、Yuanrong,仍然需要按硬件、介质、网络和运维栈手工判断。
所以这条路线留下的重点,已经超过某个 backend 名字。vLLM Ascend 把 KV cache 的三层问题合在了一条接口链里:scheduler 负责问“外部已经有多少 prefix”;worker 负责把本地 paged KV tensor 注册成可远端读写的地址;backend 负责选择 Mooncake / Memcache / Yuanrong 的实际数据路径;MultiConnector 再把 P/D 传输和跨请求复用并排组合。KV cache 在这里已经从显存里的临时张量,变成了带硬件拓扑、后端协议和调度语义的数据面。
参考资料
[1] 昇腾vLLM深度优化:全新池化后端对接方案,重构KV Cache池化架构!
[2] vLLM Ascend PR #2913: A Connector that supports Mooncake store
[3] vLLM PR #40900: Add MooncakeStoreConnector for KV cache offloading via Mooncake distributed store
[4] AscendStoreConnector source, commit 215028c0
[5] KVPoolScheduler source, commit 215028c0
[6] KVPoolWorker source, commit 215028c0
[7] Ascend Store config data source, commit 215028c0
[8] MooncakeBackend source in vLLM Ascend, commit 215028c0
[9] Ascend Store Deployment Guide, commit 215028c0
[10] Mooncake TransferEngine implementation, commit 26b24565
[11] Mooncake PR #2005: add SSD offload support for ascend platform
[12] MemcacheBackend source in vLLM Ascend, commit 215028c0
[13] vLLM Ascend PR #6869: Add Yuanrong backend support to KV Pool
[14] vLLM Ascend PR #7032: Mooncake Layerwise Connector supports kv_pool
[15] vLLM Ascend PR #7022: Mooncake Layerwise Connector supports hybrid attention manager
[16] vLLM Ascend PR #6627: mooncake layerwise support PCP function
[17] vLLM MooncakeStoreConnector source, commit 504a26ce
[18] vLLM MooncakeStore worker source, commit 504a26ce
[19] vLLM Ascend PR #8514: MooncakeBackend handles protocol besides ascend
[20] vLLM Ascend v0.18.0 release notes
版本对齐信息
| 项目 / PR | 版本或状态 | 日期 |
|---|---|---|
| vLLM Ascend main | commit 215028c0bd94 |
2026-05-16 |
| vLLM main | commit 504a26ce2be2 |
2026-05-17 |
| Mooncake main | commit 26b24565ffa9 |
2026-05-17 |
| vLLM Ascend #2913 | merged cef43b52 |
2025-09-18 |
| vLLM Ascend #6339 | merged 33b8ca4e |
2026-02-05 |
| vLLM Ascend #6627 | merged b881fab4 |
2026-02-12 |
| vLLM Ascend #6806 | merged ae394767 |
2026-03-05 |
| vLLM Ascend #6882 | merged 6852a2e2 |
2026-03-13 |
| vLLM Ascend #6869 | merged 5ae3ded9 |
2026-03-27 |
| vLLM Ascend #7032 | merged 675387f1 |
2026-03-09 |
| vLLM Ascend #9154 | merged 1af470fc |
2026-05-14 |
| vLLM #40900 | merged ebeb09d8 |
2026-05-12 |
| Mooncake #2005 | merged 253d889b |
2026-05-13 |
Discussion
留言
评论由 GitHub Discussions 承载,需要 GitHub 账号登录后发布。
滚动到这里时加载评论。