[Bugfix][Qwen4Exp] Release the profiling KV cache held by QSA key views (#58961)
Signed-off-by: Zihua Wu <13583761+lucifer1004@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
parent
66d2d4b2e7
commit
a2be4d3cc7
@@ -17,6 +17,7 @@ from vllm.models.qwen4_exp.nvidia.ops import qsa as qsa_ops
|
||||
from vllm.models.qwen4_exp.nvidia.ops import qsa_indexer as qsa_indexer_ops
|
||||
from vllm.platforms import current_platform
|
||||
from vllm.triton_utils import HAS_TRITON
|
||||
from vllm.v1.worker.utils import clear_layer_kv_caches
|
||||
|
||||
requires_qsa_kernels = pytest.mark.skipif(
|
||||
not current_platform.is_cuda() or not HAS_TRITON,
|
||||
@@ -365,7 +366,9 @@ def test_qsa_circular_buffer_survives_one_speculative_step(chunk_start: int) ->
|
||||
assert set(slots.tolist()).isdisjoint((committed % capacity).tolist())
|
||||
|
||||
|
||||
def _qsa_key_cache(block_size: int, compress_ratio: int) -> qsa_cache.QSAKeyStateCache:
|
||||
def _qsa_key_cache(
|
||||
block_size: int, compress_ratio: int, **kwargs
|
||||
) -> qsa_cache.QSAKeyStateCache:
|
||||
return qsa_cache.QSAKeyStateCache(
|
||||
head_size=64,
|
||||
dtype=torch.bfloat16,
|
||||
@@ -375,6 +378,7 @@ def _qsa_key_cache(block_size: int, compress_ratio: int) -> qsa_cache.QSAKeyStat
|
||||
compilation_config=SimpleNamespace(static_forward_context={})
|
||||
),
|
||||
compress_ratio=compress_ratio,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
|
||||
@@ -402,6 +406,23 @@ def test_qsa_state_caches_adapt_the_unified_logical_layout() -> None:
|
||||
assert compressed_cache.kv_cache.data_ptr() == compressed_view.data_ptr()
|
||||
|
||||
|
||||
def test_clearing_qsa_key_cache_releases_its_storage() -> None:
|
||||
"""Profiling teardown clears `kv_cache`; no derived view may keep it alive."""
|
||||
raw_cache = _qsa_key_cache(
|
||||
block_size=32, compress_ratio=4, cache_rope_positions=True
|
||||
)
|
||||
kv = torch.zeros(2, 1, 8, raw_cache.head_size, dtype=torch.bfloat16)
|
||||
references_before_bind = torch._C._storage_Use_Count(kv.untyped_storage()._cdata)
|
||||
raw_cache.bind_kv_cache(kv)
|
||||
assert raw_cache.key_cache.shape[-1] == 64
|
||||
assert raw_cache.rope_position_cache.dtype == torch.int64
|
||||
|
||||
clear_layer_kv_caches([raw_cache])
|
||||
|
||||
references = torch._C._storage_Use_Count(kv.untyped_storage()._cdata)
|
||||
assert references == references_before_bind
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("compress_ratio", "num_spec", "expected"),
|
||||
[(4, 0, 4), (4, 1, 8), (4, 3, 8), (4, 4, 8), (4, 5, 12), (2, 3, 6)],
|
||||
|
||||
@@ -825,15 +825,18 @@ class QSAKeyStateCache(_QSAStateCache):
|
||||
)
|
||||
super().__init__(head_size=storage_head_size, **kwargs)
|
||||
|
||||
def bind_kv_cache(self, kv_cache: torch.Tensor) -> None:
|
||||
super().bind_kv_cache(kv_cache)
|
||||
qsa_cache = self.kv_cache
|
||||
self.key_cache = qsa_cache[..., : self.key_head_size]
|
||||
if self.cache_rope_positions:
|
||||
position_tail = qsa_cache[..., self.rope_position_offset :]
|
||||
self.rope_position_cache = position_tail.view(torch.int64)
|
||||
else:
|
||||
self.rope_position_cache = None
|
||||
# Derived on access so `kv_cache` stays the only reference to the bound
|
||||
# storage: clearing it (e.g. after CUDA graph memory profiling) must free
|
||||
# the cache, or the freed block stays pinned in the allocator.
|
||||
@property
|
||||
def key_cache(self) -> torch.Tensor:
|
||||
return self.kv_cache[..., : self.key_head_size]
|
||||
|
||||
@property
|
||||
def rope_position_cache(self) -> torch.Tensor | None:
|
||||
if not self.cache_rope_positions:
|
||||
return None
|
||||
return self.kv_cache[..., self.rope_position_offset :].view(torch.int64)
|
||||
|
||||
def get_kv_cache_spec(self, vllm_config: VllmConfig) -> KVCacheSpec:
|
||||
# Hold the open group's committed keys plus every row a speculative
|
||||
|
||||
Reference in New Issue
Block a user