Evict swa kv cache during decoding (#17220)

This commit is contained in:
Ke Bao
2026-01-19 22:36:52 +08:00
committed by GitHub
parent ebca5879a1
commit ce8a6ac690
8 changed files with 167 additions and 107 deletions
+6 -48
View File
@@ -84,62 +84,20 @@ class ChunkCache(BasePrefixCache):
class SWAChunkCache(ChunkCache):
"""ChunkCache with support for hybrid KV cache operations."""
"""ChunkCache with support for sliding window attention."""
def __init__(self, params: CacheInitParams):
def __init__(self, params: CacheInitParams, sliding_window_size: int):
assert isinstance(params.token_to_kv_pool_allocator, SWATokenToKVPoolAllocator)
super().__init__(params)
assert (
params.sliding_window_size is not None
or params.attention_chunk_size is not None
), "Sliding window size or attention chunk size must be set for SWAChunkCache"
if (
params.sliding_window_size is not None
and params.attention_chunk_size is not None
):
logger.warning(
"Sliding window size and attention chunk size are both set, use sliding window size for chunk cache eviction."
)
self.sliding_window_size = params.sliding_window_size
self.attention_chunk_size = params.attention_chunk_size
self.window_size = self.sliding_window_size or self.attention_chunk_size
self.sliding_window_size = sliding_window_size
self.chunked_prefill_size = params.chunked_prefill_size
def supports_swa(self) -> bool:
assert (
self.sliding_window_size is not None
), "sliding_window_size must be set for SWAChunkCache"
return True
def evict_swa(
self,
req: Req,
prelen: int,
):
if self.sliding_window_size is not None:
# Sliding window attention (e.g. mimo-v2-flash, gpt-oss)
new_evicted_seqlen_local = max(
req.evicted_seqlen_local, prelen - self.sliding_window_size
)
elif self.attention_chunk_size is not None:
# Local attention (e.g. llama4)
new_evicted_seqlen_local = max(
req.evicted_seqlen_local,
prelen // self.attention_chunk_size * self.attention_chunk_size,
)
if self.page_size > 1:
new_evicted_seqlen_local = (
new_evicted_seqlen_local // self.page_size
) * self.page_size
if new_evicted_seqlen_local > req.evicted_seqlen_local:
free_slots = self.req_to_token_pool.req_to_token[
req.req_pool_idx, req.evicted_seqlen_local : new_evicted_seqlen_local
]
self.token_to_kv_pool_allocator.free_swa(free_slots)
req.evicted_seqlen_local = new_evicted_seqlen_local
def evict(self, num_tokens: int):
pass