目录
sumingZero

[Bugfix] Fix FULL cudagraph bypass on partial cache hits for layerwise/hybrid connectors (#1130)

Purpose

When a cache hit falls just a few tokens short of the full request length (e.g. request 8193 tokens, 8192 cached), vLLM dispatches the prefill as uniform decode into FULL cudagraph. FULL cudagraph replay skips wait_for_layer_load / save_kv_layer, breaking layerwise KV load/save. The previous workaround only fired on full hit (num_total_hit_tokens == request.num_tokens), missing the partial-hit case. For hybrid models, the old external_hit_tokens -= 1 also left total_hit_block_num unchanged, causing the mamba-align state block to be loaded at a position beyond num_computed_tokens – feeding the SSM a “future” state that already includes the recomputed positions. Additionally, the dump wrote mamba state at every LCM boundary within a chunk, but only the last boundary (chunk end) has a valid running state in HBM, leaving intermediate state entries as garbage in the store.

Modifications

  • UCMDirectConnector._get_full_hit_recompute_tokens: Consolidate the layerwise/non-layerwise logic here (check self.use_layerwise, return 2 + num_speculative_tokens for layerwise, 1 otherwise). Remove the UCMLayerWiseConnector override – both UCMLayerWiseConnector and the hybrid connectors now inherit directly.
  • UCMDirectConnector.get_num_new_matched_tokens (non-hybrid): Change the workaround condition from num_total_hit_tokens == request.num_tokens (full hit only) to actual_recompute_tokens < recompute_tokens, so partial hits that would leave too few recompute tokens also trigger the workaround. Only the deficit is subtracted from external_hit_tokens; total_hit_block_num is unchanged.
  • UCMHybridLinearAttentionConnector.get_num_new_matched_tokens (hybrid): Move the workaround BEFORE the lookup – compute max_hit_lcm_blocks = (request.num_tokens - recompute_tokens) // lcm_block_size and truncate lookup_block_ids before querying the store. This ensures the last block(s) whose mamba state may not be valid are never looked up; if the state is absent, stage 2 of the lookup naturally degrades to a shorter hit instead of returning stale data. No post-lookup reduction is needed.
  • _generate_hla_dispatch_meta (hybrid dump): Only dump the mamba-align state at last_lcm_b (the last LCM boundary in the chunk), not at every LCM boundary. Intermediate states within a chunk are not valid in HBM because the mamba kernel only keeps the running state at the current position. Dumping them wrote garbage data with valid keys into the store, which the lookup would later find and return as a hit.

Test

Non-hybrid: QwQ-32B (block_size=128, spec=3, recompute=5,

max_num_batched_tokens=8192)

Send a first request of 8192 tokens to populate 64 blocks in the cache, then send a second request sharing the same 8192-token prefix:

| Case | Request B length | Hit tokens | actual_recompute | Workaround? | deficit | ext_hit_tokens returned | vLLM recompute | |—|—|—|—|—|—|—|—| | Full hit | 8192 | 8192 | 0 | Yes (0<5) | 5 | 8187 | 5 | | 1 token short | 8193 | 8192 | 1 | Yes (1<5) | 4 | 8188 | 5 | | 4 tokens short | 8196 | 8192 | 4 | Yes (4<5) | 1 | 8191 | 5 | | Borderline (no workaround) | 8197 | 8192 | 5 | No (5<5 is False) | – | 8192 | 5 | | Enough new tokens | 8200 | 8192 | 8 | No | – | 8192 | 8 | | No hit | Different prompt | 0 | – | No | – | 0 | Full |

Hybrid: Qwen3.5-35B-A3B (block_size=2048, spec=3, recompute=5)

With MTP (EAGLE pruning active)

EAGLE forces the last block into a separate chunk (last_cache_position = num_tokens - block_size), so an 8192-token request is chunked into 6144 + 2048. Each chunk boundary has a valid running state.

| Case | Request B length | max_hit_lcm_blocks | Truncated? | Blocks looked up | ext_hit_tokens | vLLM recompute | |—|—|—|—|—|—|—| | Full hit | 8192 | (8192-5)//2048=3 | Yes (4->3) | 3 | 6144 | 2048 | | 1 token short | 8193 | (8193-5)//2048=3 | Yes (4->3) | 3 | 6144 | 2049 | | 4 tokens short | 8196 | (8196-5)//2048=3 | Yes (4->3) | 3 | 6144 | 2052 | | Borderline (no truncation) | 8197 | (8197-5)//2048=4 | No (4==4) | 4 | 8192 | 5 | | Enough new tokens | 8200 | (8200-5)//2048=4 | No | 4 | 8192 | 8 | | No hit | Different prompt | 0 | No | 0 | 0 | Full |

Without MTP (no EAGLE pruning)

Without MTP, recompute_tokens = 2 (layerwise baseline). The request is a single chunk, so only the last block boundary has a valid mamba state. Pre-lookup truncation removes the last block; the backward scan finds no valid intermediate states and degrades to 0 hit. This is correct but sacrifices cache benefit.

| Case | Request B length | max_hit_lcm_blocks | Truncated? | ext_hit_tokens | vLLM recompute | |—|—|—|—|—|—| | Full hit | 8192 | (8192-2)//2048=3 | Yes (4->3) | 0 (graceful degradation) | 8192 | | Borderline (no truncation) | 8194 | (8194-2)//2048=4 | No (4==4) | 8192 | 2 | | Enough new tokens | 8200 | (8200-2)//2048=4 | No | 8192 | 8 |

To maximize cache hit without MTP, set max_num_batched_tokens = lcm_block_size (2048) so each chunk = 1 block and every block boundary has a valid state.

1天前642次提交

UCM

| 文档 | 网站 | 发展路线图 | EN |

DeepWiki


概述

统一缓存管理器(Unified Cache Management, UCM)的核心原理是持久化 LLM 的 KVCache,并通过多种检索机制替代冗余计算。UCM 不仅支持前缀缓存(prefix cache, PC),还提供了多种无需训练的稀疏注意力检索方法,在处理极长序列推理任务时达到更高性能。此外,UCM 基于存算分离架构提供了 PD 分离方案,使得异构计算资源的管理更加简单灵活。与 vLLM 集成后,UCM 在多轮对话和长上下文推理等多种场景下可将推理延迟降低 3–10 倍。


动机

随着模型尺寸的不断增长,KV 缓存也变得越来越大,且越来越稀疏,对于长序列请求来说尤为明显。为了减小 GPU 显存的使用,主流的方向是将全量的 KV 数据卸载到外部存储中,而在 GPU 显存中只保留部分或者被压缩的 KV 数据。这同时可以减小 GPU 的运算量,在解码时增加最大生成序列长度和批大小。

有许多种不同的稀疏 KV 缓存的实现。最新的论文指出,能够最好地适配所有场景和所有模型的方法是不存在的。因此,更好的做法是搭建一套公共的框架,并在此之上接入不同的稀疏化算法,就像 KV 连接器和 PC 一样。

architecture.png

图中所有灰色框代表vLLM 0.9.2版本中的现有类,绿色框则代表UCM新增组件。浅绿色框展示了基于此框架未来规划扩展的子类。

UcmSparseBase是不同稀疏算法的基类。类似于KV连接器的设计,它将在scheduler和layer.py中的关键位置植入hook点,用于执行稀疏KVCache block的加载、转储和计算操作。

SparseKVManager允许用户针对不同算法自定义KVCache block的分配策略。为了将所有实现统一在SparseKVBase框架下,系统会调用SparseKVBase基类,而具体实现则由稀疏算法的子类完成。

KVStoreBase有助于实现稀疏算法与外部存储的解耦。它定义了与外部存储的通信方法,使得任何稀疏算法都能与任意外部存储系统无缝协作。其核心机制是通过ID和偏移量来标识数据块。这种方法不仅适用于稀疏场景,还能天然支持前缀缓存。KVStoreConnector将其与vLLM的KVConnectorBase_V1连接以提供前缀缓存功能。例如,NFSStore作为参考实现,提供了在单机本地文件系统或多服务器环境下通过NFS挂载点存储KVCache的能力。


支持特性

  • 前缀匹配
  • 缓存融合
  • 模型窗口外推
  • 预填充卸载
  • 稀疏注意力
  • 稀疏注意力卸载
  • 异构PD分离

快速开始

请参考 快速开始_vLLM快速开始_vLLM-Ascend.


分支

分支 状态 vLLM 版本
main 维护中 v0.17.0
develop 维护中 v0.17.0

联系我们

  1. 如需技术咨询或功能请求,请提交 GitHub Issues
  2. 微信技术交流群:扫描下方二维码。
wechat-gh

许可协议

UCM 采用 MIT 许可证(附加额外条件),详情请参阅 LICENSE 文件。

关于

统一缓存管理器(Unified Cache Management, UCM)的核心原理是持久化 LLM 的 KVCache,并通过多种检索机制替代冗余计算。UCM 不仅支持前缀缓存(prefix cache, PC),还提供了多种无需训练的稀疏注意力检索方法,在处理极长序列推理任务时达到更高性能。此外,UCM 基于存算分离架构提供了 PD 分离方案,使得异构计算资源的管理更加简单灵活。

151.0 MB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号