Keep CP HiCache reuse page-safe without eviction log churn
Page-aligned CP shared KV can pad out_cache_loc beyond valid current rows, so current reuse now gates MLA composition on the valid extend rows and permits draft partial-current reuse once the TAI sparse-page capability check passes. The TAI current-slot path self-tests sparse pages before use and falls back to the torch reference when the installed kernel is stale. Eviction success and no-op diagnostics were also moved from INFO to DEBUG so owner-lane and host-admission churn does not flood production logs; true write failures remain WARNING. Constraint: CP shared KV uses page-aligned physical reservations where valid suffix rows can be shorter than padded out_cache_loc. Constraint: Production failure/fallback logs must remain visible, but hot successful eviction paths should not emit INFO per victim/rank. Rejected: Keep draft partial-current reuse disabled | would preserve avoidable full materialization on draft cache-hit suffixes. Rejected: Trust the TAI current-slot kernel unconditionally | stale kernels can corrupt sparse current-page composition. Confidence: medium Scope-risk: moderate Directive: Do not reintroduce INFO logging in eviction hot paths without rate limiting and runtime evidence. Tested: local py_compile for touched Python files Tested: local git diff --check Tested: remote container py_compile for touched Python files Tested: remote PYTHONPATH=python python -m pytest -q test/registered/unit/mem_cache/test_cp_hicache_metadata.py::TestHiCacheEvictLoggingLevels::test_evict_hot_path_success_logs_are_debug_only test/registered/unit/mem_cache/test_cp_shared_kv_runtime.py -> 82 passed, 5 warnings, 2 subtests passed Not-tested: full ETE traffic after this commit; draft partial-current accept length still needs user-driven runtime validation
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import inspect
|
||||
import re
|
||||
import sys
|
||||
import types
|
||||
import unittest
|
||||
@@ -97,6 +99,8 @@ from sglang.srt.managers.cache_controller import (
|
||||
HiCacheWriteFailure,
|
||||
HiCacheWriteReservation,
|
||||
)
|
||||
import sglang.srt.mem_cache.common as mem_cache_common
|
||||
import sglang.srt.mem_cache.hiradix_cache as hiradix_cache
|
||||
from sglang.srt.mem_cache.base_prefix_cache import (
|
||||
EvictParams,
|
||||
InsertParams,
|
||||
@@ -117,6 +121,57 @@ from sglang.test.test_utils import CustomTestCase
|
||||
register_cpu_ci(est_time=2, suite="stage-a-test-cpu")
|
||||
|
||||
|
||||
class TestHiCacheEvictLoggingLevels(CustomTestCase):
|
||||
def assert_debug_marker(self, source: str, marker: str):
|
||||
self.assertIn(marker, source)
|
||||
self.assertRegex(
|
||||
source,
|
||||
r"logger\.debug\(\s*\n\s*\"" + re.escape(marker),
|
||||
msg=f"{marker} should be debug-only on the success/no-op hot path",
|
||||
)
|
||||
self.assertNotRegex(
|
||||
source,
|
||||
r"logger\.info\(\s*\n\s*\"" + re.escape(marker),
|
||||
msg=f"{marker} must not stay at INFO on the success/no-op hot path",
|
||||
)
|
||||
|
||||
def test_evict_hot_path_success_logs_are_debug_only(self):
|
||||
common_source = inspect.getsource(mem_cache_common)
|
||||
hiradix_source = inspect.getsource(hiradix_cache)
|
||||
|
||||
for marker in (
|
||||
"[MemCache-evict] evict_from_tree_cache:",
|
||||
"[MemCache-evict] _evict_for_compute_owner_lanes: evictable_size",
|
||||
"[MemCache-evict] _evict_for_compute_owner_lanes attempt=%d:",
|
||||
"[MemCache-evict] _evict_for_compute_owner_lanes attempt=%d result:",
|
||||
):
|
||||
self.assert_debug_marker(common_source, marker)
|
||||
|
||||
for marker in (
|
||||
"[HiCache-load] owner-lane device eviction before CP load-back: ",
|
||||
"[HiCache-evict] owner-lane evict found no contributing victims: ",
|
||||
"[HiCache-evict] owner-lane evict victim no longer evictable: ",
|
||||
"[HiCache-evict] owner-lane evict END: requested_tokens=%d ",
|
||||
"[HiCache-evict] deterministic CP host eviction before write: ",
|
||||
"[HiCache-write] write_backup CP retry after deterministic host eviction: ",
|
||||
"[HiCache-evict] evict START:",
|
||||
"[HiCache-evict] evict END:",
|
||||
"[HiCache-evict] _evict_backuped:",
|
||||
"[HiCache-evict] _evict_regular:",
|
||||
"[HiCache-evict] _evict_host_for_physical_slots:",
|
||||
):
|
||||
self.assert_debug_marker(hiradix_source, marker)
|
||||
|
||||
self.assertRegex(
|
||||
hiradix_source,
|
||||
r"logger\.warning\(\s*\n\s*\"\[HiCache-write\] write_backup CP FAILED after deterministic retry:",
|
||||
)
|
||||
self.assertNotRegex(
|
||||
hiradix_source,
|
||||
r"logger\.info\(\s*\n\s*\"\[HiCache-write\] write_backup CP FAILED after deterministic retry:",
|
||||
)
|
||||
|
||||
|
||||
class TestCpHiCacheImports(CustomTestCase):
|
||||
def test_cp_hicache_public_imports_without_sgl_kernel(self):
|
||||
import subprocess
|
||||
|
||||
@@ -54,9 +54,7 @@ for _name in ("flash_attn_varlen_func", "flash_attn_with_kvcache"):
|
||||
if not hasattr(flash_attn_stub, _name):
|
||||
setattr(flash_attn_stub, _name, lambda *args, **kwargs: None)
|
||||
|
||||
sgl_kernel_stub = sys.modules.setdefault(
|
||||
"sgl_kernel", types.ModuleType("sgl_kernel")
|
||||
)
|
||||
sgl_kernel_stub = sys.modules.setdefault("sgl_kernel", types.ModuleType("sgl_kernel"))
|
||||
if not hasattr(sgl_kernel_stub, "__path__"):
|
||||
sgl_kernel_stub.__path__ = []
|
||||
if not hasattr(sgl_kernel_stub, "flash_attn"):
|
||||
@@ -361,9 +359,7 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
|
||||
with patch.dict(
|
||||
sys.modules,
|
||||
{
|
||||
"sglang.srt.layers.attention.nsa.index_buf_accessor": index_accessor_stub
|
||||
},
|
||||
{"sglang.srt.layers.attention.nsa.index_buf_accessor": index_accessor_stub},
|
||||
):
|
||||
from sglang.srt.mem_cache.memory_pool import MLATokenToKVPool
|
||||
|
||||
@@ -457,7 +453,9 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
self.assertIs(out, buffer)
|
||||
dist_all_reduce.assert_called_once()
|
||||
self.assertIs(dist_all_reduce.call_args.args[0], buffer)
|
||||
self.assertIs(dist_all_reduce.call_args.kwargs["group"], dummy_group.device_group)
|
||||
self.assertIs(
|
||||
dist_all_reduce.call_args.kwargs["group"], dummy_group.device_group
|
||||
)
|
||||
|
||||
def test_build_dense_page_remap_preserves_sentinels(self):
|
||||
from sglang.srt.layers.attention.nsa.cp_shared_kv_runtime import (
|
||||
@@ -492,9 +490,7 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
)
|
||||
|
||||
current_locs = torch.tensor([100, 64, 256, 128], dtype=torch.int64)
|
||||
query_locs = torch.tensor(
|
||||
[[128, -1, 64], [512, 100, 256]], dtype=torch.int32
|
||||
)
|
||||
query_locs = torch.tensor([[128, -1, 64], [512, 100, 256]], dtype=torch.int32)
|
||||
|
||||
is_current, compact_rows = build_current_loc_remap(query_locs, current_locs)
|
||||
|
||||
@@ -569,7 +565,7 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
forward_batch.out_cache_loc = torch.arange(64, dtype=torch.int64)
|
||||
self.assertFalse(can_reuse_current_extend_kv(forward_batch))
|
||||
|
||||
def test_should_reuse_current_extend_kv_disables_draft_partial_cache_hit_suffix(
|
||||
def test_should_reuse_current_extend_kv_enables_draft_partial_cache_hit_suffix(
|
||||
self,
|
||||
):
|
||||
from sglang.srt.environ import envs
|
||||
@@ -595,13 +591,7 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
)
|
||||
|
||||
with envs.SGLANG_CP_SHARED_KV_CURRENT_REUSE.override(True):
|
||||
with self.assertLogs(runtime.logger.name, level="WARNING") as logs:
|
||||
self.assertFalse(runtime.should_reuse_current_extend_kv(forward_batch))
|
||||
self.assertIn(
|
||||
"[CP_SHARED_KV_FALLBACK][current_reuse]",
|
||||
logs.output[0],
|
||||
)
|
||||
self.assertIn("draft_partial_current_reuse_disabled", logs.output[0])
|
||||
self.assertTrue(runtime.should_reuse_current_extend_kv(forward_batch))
|
||||
|
||||
forward_batch.spec_info = TargetSpecInfo()
|
||||
forward_batch.cp_shared_kv_mla_prefetcher = object()
|
||||
@@ -619,6 +609,73 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
forward_batch.cp_shared_kv_mla_prefetcher = None
|
||||
self.assertTrue(runtime.should_reuse_current_extend_kv(forward_batch))
|
||||
|
||||
def test_current_extend_kv_rows_for_reuse_accepts_padded_out_cache_loc(self):
|
||||
from sglang.srt.environ import envs
|
||||
from sglang.srt.layers.attention.nsa import cp_shared_kv_runtime as runtime
|
||||
|
||||
class DraftSpecInfo:
|
||||
def is_draft_input(self):
|
||||
return True
|
||||
|
||||
forward_batch = SimpleNamespace(
|
||||
forward_mode=_FakeExtendForwardMode(),
|
||||
batch_size=1,
|
||||
extend_prefix_lens_cpu=[40384],
|
||||
extend_seq_lens_cpu=[65],
|
||||
seq_lens_cpu=torch.tensor([40384 + 65], dtype=torch.int32),
|
||||
out_cache_loc=torch.arange(128, dtype=torch.int64),
|
||||
spec_info=DraftSpecInfo(),
|
||||
)
|
||||
k = torch.empty((65, 2, 4), dtype=torch.float32)
|
||||
k_rope = torch.empty((65, 2, 1), dtype=torch.float32)
|
||||
|
||||
with envs.SGLANG_CP_SHARED_KV_CURRENT_REUSE.override(True):
|
||||
self.assertEqual(
|
||||
runtime.current_extend_kv_rows_for_reuse(forward_batch, k, k_rope),
|
||||
65,
|
||||
)
|
||||
|
||||
self.assertIsNone(
|
||||
runtime.current_extend_kv_rows_for_reuse(
|
||||
forward_batch,
|
||||
k[:64],
|
||||
k_rope,
|
||||
)
|
||||
)
|
||||
|
||||
def test_mla_current_reuse_gate_accepts_padded_out_cache_loc(self):
|
||||
from pathlib import Path
|
||||
|
||||
source = (
|
||||
Path(__file__).resolve().parents[4]
|
||||
/ "python/sglang/srt/layers/attention/nsa_backend.py"
|
||||
).read_text()
|
||||
start = source.index(" current_kv_rows_for_reuse =")
|
||||
end = source.index(
|
||||
" if cp_shared_kv_mla_prefetch_log_enabled()", start
|
||||
)
|
||||
gate_source = source[start:end]
|
||||
|
||||
self.assertIn("current_extend_kv_rows_for_reuse", gate_source)
|
||||
self.assertNotIn(
|
||||
"k.shape[0] == forward_batch.out_cache_loc.numel()",
|
||||
gate_source,
|
||||
)
|
||||
self.assertNotIn(
|
||||
"k_rope.shape[0] == forward_batch.out_cache_loc.numel()",
|
||||
gate_source,
|
||||
)
|
||||
body_start = source.index(" if can_reuse_current_kv:", end)
|
||||
body_end = source.index(
|
||||
" logical_page_table_1 = page_table_1", body_start
|
||||
)
|
||||
body_source = "".join(source[body_start:body_end].split())
|
||||
|
||||
self.assertIn("valid_current_rows=int(current_kv_rows_for_reuse)", body_source)
|
||||
self.assertIn("k[:valid_current_rows]", body_source)
|
||||
self.assertIn("k_rope[:valid_current_rows]", body_source)
|
||||
self.assertIn("forward_batch.out_cache_loc[:valid_current_rows]", body_source)
|
||||
|
||||
def test_runtime_fallback_helpers_use_standard_warning_marker(self):
|
||||
from sglang.srt.layers.attention.nsa import cp_shared_kv_runtime as runtime
|
||||
|
||||
@@ -738,6 +795,53 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
self.assertEqual(current_mask.tolist(), [[False, True, True, False, False]])
|
||||
self.assertEqual(mixed_locs.tolist(), [[4, 12, 13, -1, -1]])
|
||||
|
||||
def test_tai_current_slot_fill_is_skipped_when_sparse_page_self_test_fails(self):
|
||||
from sglang.srt.environ import envs
|
||||
from sglang.srt.layers.attention.nsa import cp_shared_kv_runtime as runtime
|
||||
|
||||
class BadKernels:
|
||||
@staticmethod
|
||||
def fill_current_token_kv_page_slots_and_remap_locs(*args, **kwargs):
|
||||
raise AssertionError("stale TAI fill kernel should not be called")
|
||||
|
||||
with envs.SGLANG_CP_SHARED_KV_USE_TAI_MATERIALIZE.override(True), patch.object(
|
||||
runtime,
|
||||
"_tai_current_slot_fill_supports_sparse_pages",
|
||||
return_value=False,
|
||||
), patch.object(
|
||||
runtime,
|
||||
"_load_tai_materialize_kernels",
|
||||
return_value=BadKernels,
|
||||
):
|
||||
result = runtime._try_tai_fill_current_kv_page_slots_and_remap_locs(
|
||||
dense_kv_cache=torch.zeros((16, 1), dtype=torch.float32),
|
||||
materialized_dense_locs=torch.tensor([[4, 5, 8, 9]], dtype=torch.int64),
|
||||
current_kv_cache=torch.ones((2, 1), dtype=torch.float32),
|
||||
logical_locs=torch.tensor([[20, 21, 40, 41]], dtype=torch.int64),
|
||||
current_locs=torch.tensor([20, 21], dtype=torch.int64),
|
||||
page_inverse=torch.tensor(
|
||||
[0, -1, -1, -1, -1, 1, -1, -1, -1, -1, 2],
|
||||
dtype=torch.long,
|
||||
),
|
||||
page_size=4,
|
||||
mask_non_current_in_current_pages=True,
|
||||
)
|
||||
|
||||
self.assertIsNone(result)
|
||||
|
||||
@unittest.skipIf(not torch.cuda.is_available(), "CUDA is required")
|
||||
def test_tai_current_slot_fill_sparse_page_self_test_passes_on_installed_kernel(
|
||||
self,
|
||||
):
|
||||
from sglang.srt.layers.attention.nsa import cp_shared_kv_runtime as runtime
|
||||
|
||||
runtime._tai_current_slot_fill_sparse_pages_self_test.cache_clear()
|
||||
self.assertTrue(
|
||||
runtime._tai_current_slot_fill_supports_sparse_pages(
|
||||
torch.device("cuda", torch.cuda.current_device())
|
||||
)
|
||||
)
|
||||
|
||||
def test_materialize_prefix_and_reuse_current_kv_page_slots_without_prefetcher(
|
||||
self,
|
||||
):
|
||||
@@ -913,9 +1017,7 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
|
||||
with patch.object(
|
||||
prefetch.torch.cuda, "current_stream", return_value=current_stream
|
||||
), patch.object(
|
||||
prefetcher, "launch_pending_reduce"
|
||||
) as launch_pending_reduce:
|
||||
), patch.object(prefetcher, "launch_pending_reduce") as launch_pending_reduce:
|
||||
prefetcher.wait_attention_window()
|
||||
|
||||
launch_pending_reduce.assert_not_called()
|
||||
@@ -1402,8 +1504,7 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
|
||||
self.assertTrue(
|
||||
any(
|
||||
"token slot remap cache not reused (missing_cached_value)"
|
||||
in message
|
||||
"token slot remap cache not reused (missing_cached_value)" in message
|
||||
for message in logs.output
|
||||
)
|
||||
)
|
||||
@@ -1549,13 +1650,17 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
)
|
||||
self.assertIn("prefix_not_page_aligned", logger.call_args.args[1])
|
||||
|
||||
def test_mla_prefetch_min_prefix_pages_uses_cached_token_default_and_can_override(self):
|
||||
def test_mla_prefetch_min_prefix_pages_uses_cached_token_default_and_can_override(
|
||||
self,
|
||||
):
|
||||
from sglang.srt.environ import envs
|
||||
from sglang.srt.layers.attention.nsa import cp_shared_kv_runtime as runtime
|
||||
|
||||
envs.SGLANG_CP_SHARED_KV_MLA_PREFETCH_MIN_PREFIX_PAGES.clear()
|
||||
default_tokens = envs.SGLANG_CP_SHARED_KV_MLA_PREFETCH_MIN_PREFIX_TOKENS.get()
|
||||
self.assertEqual(runtime._MLA_PREFETCH_DEFAULT_MIN_PREFIX_TOKENS, default_tokens)
|
||||
self.assertEqual(
|
||||
runtime._MLA_PREFETCH_DEFAULT_MIN_PREFIX_TOKENS, default_tokens
|
||||
)
|
||||
expected_pages = (default_tokens + 63) // 64
|
||||
self.assertEqual(
|
||||
runtime.cp_shared_kv_mla_prefetch_min_prefix_pages(8, page_size=64),
|
||||
@@ -1844,9 +1949,7 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
|
||||
with patch.object(
|
||||
runtime, "cp_shared_kv_tai_fused_mla_store_enabled", return_value=False
|
||||
), patch.object(
|
||||
runtime, "_load_tai_fused_mla_store_kernel"
|
||||
) as load_kernel:
|
||||
), patch.object(runtime, "_load_tai_fused_mla_store_kernel") as load_kernel:
|
||||
used = runtime.try_tai_fused_mla_store(
|
||||
token_to_kv_pool=FakePool(),
|
||||
layer=SimpleNamespace(layer_id=0),
|
||||
@@ -1962,7 +2065,9 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
self.inverse_calls = []
|
||||
self.remap_calls = []
|
||||
|
||||
def build_slot_page_inverse(self, slot_logical_pages, logical_page_capacity):
|
||||
def build_slot_page_inverse(
|
||||
self, slot_logical_pages, logical_page_capacity
|
||||
):
|
||||
self.inverse_calls.append((slot_logical_pages, logical_page_capacity))
|
||||
return torch.tensor([0, 1, 2, -1], dtype=torch.long)
|
||||
|
||||
@@ -2056,7 +2161,9 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
|
||||
with patch.object(
|
||||
runtime, "cp_shared_kv_debug_enabled", return_value=True
|
||||
), patch.object(runtime, "_all_reduce_materialized_buffer", _identity_all_reduce):
|
||||
), patch.object(
|
||||
runtime, "_all_reduce_materialized_buffer", _identity_all_reduce
|
||||
):
|
||||
with self.assertRaisesRegex(
|
||||
RuntimeError,
|
||||
"CP shared KV materialize got logical token locs outside the physical pool",
|
||||
@@ -2068,7 +2175,9 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
page_size=4,
|
||||
)
|
||||
|
||||
def test_materialize_token_kv_skips_physical_pool_validation_when_debug_disabled(self):
|
||||
def test_materialize_token_kv_skips_physical_pool_validation_when_debug_disabled(
|
||||
self,
|
||||
):
|
||||
from sglang.srt.layers.attention.nsa import cp_shared_kv_runtime as runtime
|
||||
from sglang.srt.mem_cache.cp_shared_kv_layout import CpSharedKVLayout
|
||||
|
||||
@@ -2081,7 +2190,9 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
|
||||
with patch.object(
|
||||
runtime, "cp_shared_kv_debug_enabled", return_value=False
|
||||
), patch.object(runtime, "_all_reduce_materialized_buffer", _identity_all_reduce):
|
||||
), patch.object(
|
||||
runtime, "_all_reduce_materialized_buffer", _identity_all_reduce
|
||||
):
|
||||
_, dense_locs = runtime.materialize_shared_token_kv_buffer(
|
||||
kv_cache=kv_cache,
|
||||
logical_locs=logical_locs,
|
||||
@@ -2100,7 +2211,9 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
logical_locs = torch.tensor([4, -1, 8], dtype=torch.int64)
|
||||
|
||||
with patch.object(runtime, "cp_shared_kv_debug_enabled", return_value=True):
|
||||
with patch.object(runtime, "_all_reduce_materialized_buffer", _identity_all_reduce):
|
||||
with patch.object(
|
||||
runtime, "_all_reduce_materialized_buffer", _identity_all_reduce
|
||||
):
|
||||
_, dense_locs = runtime.materialize_shared_token_kv_buffer(
|
||||
kv_cache=kv_cache,
|
||||
logical_locs=logical_locs,
|
||||
@@ -2172,7 +2285,9 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
logical_locs = torch.tensor([8, 20, -1], dtype=torch.int64)
|
||||
remap_source_locs = torch.tensor([4, 8, 12, 16, 20], dtype=torch.int64)
|
||||
|
||||
with patch.object(runtime, "_all_reduce_materialized_buffer", _identity_all_reduce):
|
||||
with patch.object(
|
||||
runtime, "_all_reduce_materialized_buffer", _identity_all_reduce
|
||||
):
|
||||
dense_kv, dense_locs = runtime.materialize_shared_token_kv_buffer(
|
||||
kv_cache=kv_cache,
|
||||
logical_locs=logical_locs,
|
||||
@@ -2223,7 +2338,9 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
kv_cache = torch.arange(0, 32, dtype=torch.float32).view(32, 1, 1)
|
||||
remap_source_locs = torch.tensor([4, 8, 12, 16, 20], dtype=torch.int64)
|
||||
|
||||
with patch.object(runtime, "_all_reduce_materialized_buffer", _identity_all_reduce):
|
||||
with patch.object(
|
||||
runtime, "_all_reduce_materialized_buffer", _identity_all_reduce
|
||||
):
|
||||
dense_kv_a, dense_locs_a = runtime.materialize_shared_token_kv_buffer(
|
||||
kv_cache=kv_cache,
|
||||
logical_locs=torch.tensor([4, 20], dtype=torch.int64),
|
||||
@@ -2254,7 +2371,9 @@ class TestCpSharedKVRuntimeHelpers(unittest.TestCase):
|
||||
|
||||
with patch.object(
|
||||
runtime, "cp_shared_kv_debug_enabled", return_value=True
|
||||
), patch.object(runtime, "_all_reduce_materialized_buffer", _identity_all_reduce):
|
||||
), patch.object(
|
||||
runtime, "_all_reduce_materialized_buffer", _identity_all_reduce
|
||||
):
|
||||
with self.assertRaisesRegex(
|
||||
RuntimeError,
|
||||
"CP shared KV materialize got logical pages outside the physical page buffer",
|
||||
@@ -2401,7 +2520,9 @@ class TestCpSharedKVLazyDebugLogging(unittest.TestCase):
|
||||
self.assertEqual(k_to_write.shape[0], 2)
|
||||
self.assertEqual(k_rope_to_write.shape[0], 2)
|
||||
|
||||
def test_index_write_filter_does_not_build_debug_summaries_when_debug_disabled(self):
|
||||
def test_index_write_filter_does_not_build_debug_summaries_when_debug_disabled(
|
||||
self,
|
||||
):
|
||||
from sglang.srt.layers.attention.nsa import nsa_indexer
|
||||
from sglang.srt.mem_cache.cp_shared_kv_layout import CpSharedKVLayout
|
||||
|
||||
@@ -2422,10 +2543,12 @@ class TestCpSharedKVLazyDebugLogging(unittest.TestCase):
|
||||
"sglang.srt.environ.envs.SGLANG_DEBUG_CP_SHARED_KV.get",
|
||||
return_value=False,
|
||||
):
|
||||
physical_locs, key_to_write = nsa_indexer.Indexer._filter_shared_index_write(
|
||||
None,
|
||||
forward_batch,
|
||||
key,
|
||||
physical_locs, key_to_write = (
|
||||
nsa_indexer.Indexer._filter_shared_index_write(
|
||||
None,
|
||||
forward_batch,
|
||||
key,
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(physical_locs.tolist(), [4, 8])
|
||||
@@ -2493,8 +2616,12 @@ class TestCpSharedKVTaiMaterializeIntegration(unittest.TestCase):
|
||||
self.remap_calls = []
|
||||
self.token_calls = []
|
||||
|
||||
def build_slot_page_inverse(self, slot_logical_pages, logical_page_capacity):
|
||||
self.page_inverse_calls.append((slot_logical_pages, logical_page_capacity))
|
||||
def build_slot_page_inverse(
|
||||
self, slot_logical_pages, logical_page_capacity
|
||||
):
|
||||
self.page_inverse_calls.append(
|
||||
(slot_logical_pages, logical_page_capacity)
|
||||
)
|
||||
return torch.tensor([0, 1, 2, -1, 3], dtype=torch.long)
|
||||
|
||||
def remap_logical_locs_to_slot_dense_locs(
|
||||
@@ -2567,7 +2694,9 @@ class TestCpSharedKVTaiMaterializeIntegration(unittest.TestCase):
|
||||
from sglang.srt.mem_cache.cp_shared_kv_layout import CpSharedKVLayout
|
||||
|
||||
class FakeTaiKernels:
|
||||
def build_slot_page_inverse(self, slot_logical_pages, logical_page_capacity):
|
||||
def build_slot_page_inverse(
|
||||
self, slot_logical_pages, logical_page_capacity
|
||||
):
|
||||
return torch.tensor([0, 1, 2, -1, 3], dtype=torch.long)
|
||||
|
||||
def remap_logical_locs_to_slot_dense_locs(
|
||||
|
||||
Reference in New Issue
Block a user