A high-throughput and memory-efficient inference and serving engine for LLMs
[Mooncake] Skip KV lookup for non-reachable SWA blocks (#45444)
Signed-off-by: wzhao18 <wzhao18.sz@gmail.com>
Wei Zhao committed
Jun 18, 2026 at 05:23 UTC
5fd3b276f8fa34b70d3c83314700f626c66f9a22
4 files changed
+120
-18
tests/v1/kv_connector/unit/test_mooncake_store_coordinator.py
+10
-10
@@ -200,7 +200,7 @@ def test_store_mask_full_attention_all_true():
200
groups = [KVCacheGroupSpec(["L0"], _full(16))]
201
coord = _make_coord(groups, hash_block_size=16)
202
masks = coord.store_mask(64)
203
- assert masks == ([True, True, True, True],)
203
+ assert masks == (None,)
204
205
206
def test_store_mask_zero_aligned_returns_empty_per_group():
@@ -210,7 +210,7 @@ def test_store_mask_zero_aligned_returns_empty_per_group():
210
]
211
coord = _make_coord(groups, hash_block_size=16)
212
masks = coord.store_mask(0)
213
- assert masks == ([], [])
213
+ assert masks == (None, None)
214
215
216
def test_store_mask_swa_only_window_around_each_lcm_boundary():
@@ -224,7 +224,7 @@ def test_store_mask_swa_only_window_around_each_lcm_boundary():
224
coord = _make_coord(groups, hash_block_size=8)
225
masks = coord.store_mask(64)
226
# Full-attn: 2 chunks * 32 tokens.
227
- assert masks[0] == [True, True]
227
+ assert masks[0] is None
228
# SWA: 8 chunks * 8 tokens. Only chunks ending at 32 and 64 are stored.
229
assert masks[1] == [False, False, False, True, False, False, False, True]
230
@@ -237,7 +237,7 @@ def test_store_mask_swa_wider_window_covers_more_blocks_per_lcm():
237
groups = [KVCacheGroupSpec(["L0"], full), KVCacheGroupSpec(["L1"], swa)]
238
coord = _make_coord(groups, hash_block_size=8)
239
masks = coord.store_mask(64)
240
- assert masks[0] == [True, True]
240
+ assert masks[0] is None
241
# Boundary at 32: blocks ending in [16, 32) — chunks 2 and 3.
242
# Boundary at 64: chunks 6 and 7. Others stay False.
243
assert masks[1] == [False, False, True, True, False, False, True, True]
@@ -265,12 +265,12 @@ def test_store_mask_dsv4_5_groups_full_mla_plus_4_swa():
265
masks = coord.store_mask(512)
266
267
# Full-MLA: 2 chunks of 256, both stored.
268
- assert masks[0] == [True, True]
268
+ assert masks[0] is None
269
# SWA(64, sw=128): tail = ceil(127/64) = 2; C = 256/64 = 4.
270
# Per-segment template = [F,F,T,T]; tiled twice.
271
assert masks[1] == [False, False, True, True] * 2
272
# SWA(64, sw=512): tail = 8 >= C = 4 → entire segment True.
273
- assert masks[2] == [True] * 8
273
+ assert masks[2] is None
274
# SWA(4, sw=16): tail = ceil(15/4) = 4; C = 256/4 = 64.
275
# Last 4 of each 64-chunk segment True.
276
assert masks[3] == ([False] * 60 + [True] * 4) * 2
@@ -289,7 +289,7 @@ def test_store_mask_fast_path_all_block_sizes_equal_lcm():
289
assert coord.lcm_block_size == 64
290
masks = coord.store_mask(256)
291
# Every block in every group is True — no sub-lcm filtering possible.
292
- assert masks == ([True] * 4, [True] * 4)
292
+ assert masks == (None, None)
293
294
295
def test_store_mask_fast_path_single_attention_group():
@@ -300,7 +300,7 @@ def test_store_mask_fast_path_single_attention_group():
300
coord = _make_coord(groups, hash_block_size=16)
301
assert len(coord.attention_groups) == 1
302
masks = coord.store_mask(64)
303
- assert masks == ([True] * 4, [True] * 4)
303
+ assert masks == (None, None)
304
305
306
# ----- store_mask with retention_interval (DSV4 sparse SWA checkpointing) -----
@@ -319,7 +319,7 @@ def test_store_mask_dense_default_matches_every_lcm_boundary():
319
boundary: tokens 32/64/96/128 -> chunks 3/7/11/15."""
320
coord = _make_coord(_retention_groups(), hash_block_size=8)
321
masks = coord.store_mask(128)
322
- assert masks[0] == [True, True, True, True]
322
+ assert masks[0] is None
323
assert masks[1] == [i % 4 == 3 for i in range(16)]
324
325
@@ -329,7 +329,7 @@ def test_store_mask_retention_interval_sparsifies_swa_tails():
329
boundaries at 32 and 96."""
330
coord = _make_coord(_retention_groups(), hash_block_size=8, retention_interval=64)
331
masks = coord.store_mask(128)
332
- assert masks[0] == [True, True, True, True] # full attn unaffected
332
+ assert masks[0] is None # full attn unaffected
333
assert masks[1] == [i in (7, 15) for i in range(16)]
334
335
tests/v1/kv_connector/unit/test_mooncake_store_worker.py
+61
@@ -1233,6 +1233,67 @@ def test_lookup_swa_single_group_returns_full_when_tail_window_present():
1233
assert worker.lookup(64, [b"h0", b"h1", b"h2", b"h3"]) == 64
1234
1235
1236
+def test_lookup_checks_all_potential_swa_hit_boundaries():
1237
+ """Lookup should skip SWA chunks that can never validate a hit, but still
1238
+ check earlier aligned boundaries when sparse retention stores only the
1239
+ current request's replay boundary.
1240
+ """
1241
+ from vllm.v1.kv_cache_interface import (
1242
+ FullAttentionSpec,
1243
+ KVCacheGroupSpec,
1244
+ SlidingWindowSpec,
1245
+ )
1246
+
1247
+ worker = _make_bare_worker(block_size=8)
1248
+ full = FullAttentionSpec(block_size=32, num_kv_heads=8, head_size=64, dtype=None)
1249
+ swa = SlidingWindowSpec(
1250
+ block_size=8, num_kv_heads=8, head_size=64, dtype=None, sliding_window=8
1251
+ )
1252
+ worker._kv_cache_groups = [
1253
+ KVCacheGroupSpec(["full"], full),
1254
+ KVCacheGroupSpec(["swa"], swa),
1255
+ ]
1256
+ worker.token_dbs = [
1257
+ ChunkedTokenDatabase(
1258
+ KeyMetadata("test-model", 0, 0, 0, 0, group_id=0),
1259
+ block_size=32,
1260
+ hash_block_size=8,
1261
+ ),
1262
+ ChunkedTokenDatabase(
1263
+ KeyMetadata("test-model", 0, 0, 0, 0, group_id=1),
1264
+ block_size=8,
1265
+ hash_block_size=8,
1266
+ ),
1267
+ ]
1268
+ worker.coord = mooncake_store_worker.MooncakeStoreCoordinator(
1269
+ worker._kv_cache_groups,
1270
+ scheduler_block_size=32,
1271
+ hash_block_size=8,
1272
+ retention_interval=0,
1273
+ )
1274
+ # Candidate order: 3 full-attention chunks, then SWA chunks 3, 7, 11.
1275
+ # Only the first full chunk and the SWA chunk ending at token 32 exist, so
1276
+ # lookup should recover a 32-token external prefix hit. A sparse
1277
+ # prompt-specific store mask for num_prompt_tokens=96 would only check SWA
1278
+ # chunk 7 and miss this earlier reusable prefix.
1279
+ worker.store.batch_is_exist.return_value = [1, 0, 0, 1, 0, 0]
1280
+
1281
+ result = worker.lookup(
1282
+ 96,
1283
+ [f"h{i}".encode() for i in range(12)],
1284
+ )
1285
+
1286
+ assert result == 32
1287
+ keys = worker.store.batch_is_exist.call_args.args[0]
1288
+ assert len(keys) == 6
1289
+ swa_keys = [key for key in keys if "@group:1@" in key]
1290
+ assert swa_keys == [
1291
+ "test-model@tp_rank:0@pcp0@dcp0@pp_rank:0@group:1@6833",
1292
+ "test-model@tp_rank:0@pcp0@dcp0@pp_rank:0@group:1@6837",
1293
+ "test-model@tp_rank:0@pcp0@dcp0@pp_rank:0@group:1@683131",
1294
+ ]
1295
+
1296
+
1297
# ---------------------------------------------------------------------------
1298
# register_kv_caches tests
1299
# ---------------------------------------------------------------------------
vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/coordinator.py
+40
-7
@@ -172,19 +172,50 @@ class MooncakeStoreCoordinator:
172
self,
173
aligned_token_len: int,
174
num_prompt_tokens: int | None = None,
175
- ) -> tuple[list[bool], ...]:
176
- """Per-group store masks: ``mask[g][i]`` is True iff chunk ``i`` of
177
- group ``g`` should be written to the store so a future cache hit can
178
- consume it.
175
+ ) -> tuple[list[bool] | None, ...]:
176
+ """Per-group store masks.
177
+
178
+ ``mask[g][i]`` is True iff chunk ``i`` of group ``g`` should be
179
+ written to the store so a future cache hit can consume it. ``None`` is
180
+ the all-True sentinel.
181
182
Reuses the engine's ``SingleTypeKVCacheManager.reachable_block_mask``
183
so the store retains exactly the blocks the local prefix cache would.
184
"""
185
+ return self._reachable_masks(
186
+ aligned_token_len,
187
+ retention_interval=self.retention_interval,
188
+ num_prompt_tokens=num_prompt_tokens,
189
+ )
190
+
191
+ def lookup_mask(
192
+ self,
193
+ aligned_token_len: int,
194
+ ) -> tuple[list[bool] | None, ...]:
195
+ """Per-group lookup masks.
196
+
197
+ ``mask[g][i]`` is True iff chunk ``i`` of group ``g`` should be
198
+ looked up as an aligned hit boundary. ``None`` is the all-True
199
+ sentinel.
200
+ """
201
+ return self._reachable_masks(
202
+ aligned_token_len,
203
+ retention_interval=None,
204
+ num_prompt_tokens=None,
205
+ )
206
+
207
+ def _reachable_masks(
208
+ self,
209
+ aligned_token_len: int,
210
+ *,
211
+ retention_interval: int | None,
212
+ num_prompt_tokens: int | None,
213
+ ) -> tuple[list[bool] | None, ...]:
214
assert aligned_token_len % self.lcm_block_size == 0, (
215
f"aligned_token_len ({aligned_token_len}) must be a multiple of "
216
f"lcm_block_size ({self.lcm_block_size})"
217
)
187
- masks: list[list[bool]] = []
218
+ masks: list[list[bool] | None] = []
219
for g_idx, g in enumerate(self.kv_cache_groups):
220
spec = _unwrap_spec(g.kv_cache_spec)
221
num_chunks = aligned_token_len // spec.block_size
@@ -196,10 +227,12 @@ class MooncakeStoreCoordinator:
227
alignment_tokens=self.lcm_block_size,
228
kv_cache_spec=spec,
229
use_eagle=g_idx in self.eagle_group_ids,
199
- retention_interval=self.retention_interval,
230
+ retention_interval=retention_interval,
231
num_prompt_tokens=num_prompt_tokens,
232
)
202
- masks.append([True] * num_chunks if mask is None else mask)
233
+ if mask is not None:
234
+ assert len(mask) == num_chunks
235
+ masks.append(mask)
236
return tuple(masks)
237
238
def block_hashes_for_spec(
vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/worker.py
+9
-1
@@ -548,7 +548,9 @@ class KVCacheStoreSendingThread(KVTransferThread):
548
for chunk_idx, (start, end, key) in enumerate(
549
db.process_tokens(token_len, req_meta.block_hashes)
550
):
551
- if chunk_idx >= len(mask) or not mask[chunk_idx]:
551
+ if mask is not None and (
552
+ chunk_idx >= len(mask) or not mask[chunk_idx]
553
+ ):
554
continue
555
starts.append(start)
556
ends.append(end)
@@ -1375,9 +1377,11 @@ class MooncakeStoreWorker:
1377
# candidate_meta[i] is the (group_id, hash_bytes) for candidate_keys[i].
1378
candidate_keys: list[str] = []
1379
candidate_meta: list[tuple[int, bytes]] = []
1380
+ lookup_masks = self.coord.lookup_mask(token_len)
1381
tp_count = min(self.tp_size, self.num_kv_head)
1382
for g_idx, db in enumerate(self.token_dbs):
1383
spec_block_size = db.block_size
1384
+ lookup_mask = lookup_masks[g_idx]
1385
group_hashes = self.coord.block_hashes_for_spec(
1386
block_hashes, self._kv_cache_groups[g_idx].kv_cache_spec
1387
)
@@ -1385,6 +1389,10 @@ class MooncakeStoreWorker:
1389
start_idx = chunk_id * spec_block_size
1390
if start_idx >= token_len:
1391
break
1392
+ if lookup_mask is not None and (
1393
+ chunk_id >= len(lookup_mask) or not lookup_mask[chunk_id]
1394
+ ):
1395
+ continue
1396
for tp in range(tp_count):
1397
for pp in range(self.pp_size):
1398
md = dataclasses.replace(db.metadata, tp_rank=tp, pp_rank=pp)