[None][perf] Allocate DSA indexer k-cache only for layers that own an indexer#16558
[None][perf] Allocate DSA indexer k-cache only for layers that own an indexer#16558Tabrizian wants to merge 4 commits into
Conversation
bd467f8 to
3bc287d
Compare
|
/bot run --disable-fail-fast |
3bc287d to
d10f1ce
Compare
|
/bot run --disable-fail-fast --add-multi-gpu-test |
2 similar comments
|
/bot run --disable-fail-fast --add-multi-gpu-test |
|
/bot run --disable-fail-fast --add-multi-gpu-test |
|
PR_Github #61444 [ run ] triggered by Bot. Commit: |
|
PR_Github #61427 [ run ] completed with state |
|
PR_Github #61444 [ run ] completed with state
|
|
/bot run --disable-fail-fast --add-multi-gpu-test |
|
PR_Github #61472 [ run ] triggered by Bot. Commit: |
|
PR_Github #61472 [ run ] completed with state
|
|
/bot run --disable-fail-fast --add-multi-gpu-test |
|
PR_Github #61600 [ run ] triggered by Bot. Commit: |
|
PR_Github #61600 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #61650 [ run ] triggered by Bot. Commit: |
|
PR_Github #61650 [ run ] completed with state
|
…gs/5838199) The full cacheTransceiverTest binary hangs under 8-process UCX due to a pre-existing cumulative resource issue in the transceiver test suite, independent of this PR: on an H100 node the same binary hangs at a non-indexer base case on both this branch and main (09e5d0c). This mirrors the already-waived sibling variant test_cache_transceiver[8proc-mooncake_kvcache-90] and is tracked by the same NVBug. Signed-off-by: Iman Tabrizian <10105175+tabrizian@users.noreply.github.com>
|
/bot run --disable-fail-fast |
|
PR_Github #61660 [ run ] triggered by Bot. Commit: |
|
PR_Github #61660 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #61676 [ run ] triggered by Bot. Commit: |
|
PR_Github #61676 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
Dev Engineer Review
indexerLayerNumPerPP/indexerKCacheLayerMaskparameters across C++ cache state, KV cache manager (pool creation + mapping), andCacheTransceiver.targetIRanksForIndexerKCache) and buffer offset-ratio handling forBufferKind::kKV_INDEXER.kv_cache::CacheStateserialization/deserialization withindexerLayerNumPerPP.indexer_k_cache_layer_maskand expose layer→pool-row mapping with masking enforcement; Python NIXL path rejects masked pools (per objective).QA Engineer Review
Test-code changes (files outside
tests/integration/test_lists/)cpp/tests/unit_tests/batch_manager/kvCacheManagerTest.cppindexerKCacheLayerMask(usesstd::nullopt).cpp/tests/unit_tests/executor/serializeUtilsTest.cppSerializeUtilsTest.CacheStateIndexerKCacheto includeindexerKCacheUseFp4andindexerLayerNumPerPP, and validate serialization round-trip equality.cpp/tests/unit_tests/multi_gpu/cacheTransceiverTest.cppAsymmetricalCacheTestWithIndexerLayerMaskand updated setup/block-data logic to use indexer-layer counts when testing Indexer-K transceiver send/receive.Coverage in
tests/integration/test_lists/: these unit tests are not directly represented as list entries (they run via unit test binaries).Verdict (unit tests): sufficient.
Test-list / integration changes (files under
tests/integration/test_lists/)tests/integration/defs/accuracy/test_disaggregated_serving.pyTestGLM52NVFP4.test_nvfp4_nixl_python→TestGLM52NVFP4.test_nvfp4_nixl.tests/integration/test_lists/qa/llm_function_core.txtcache_mgr_v1to usetest_nvfp4_nixl[...]instead oftest_nvfp4_nixl_python[...].tests/integration/test_lists/test-db/l0_dgx_b200.ymlcache_mgr_v1to usetest_nvfp4_nixl[...]instead oftest_nvfp4_nixl_python[...](timeout unchanged).tests/integration/test_lists/waives.txtcpp/test_multi_gpu.py::test_cache_transceiverwith8proc-ucx_kvcache-90(NVBUG 5838199 referenced).Verdict (integration lists): needs follow-up (CI failures reported for specific commits in the PR context; additionally, CBTS coverage status for new/updated entries is not provided here).
Overall QA verdict
needs follow-up due to the reported L0 pipeline failures (commits listed in PR context) and to confirm the updated masked Indexer-K paths are stable end-to-end on all targeted configurations.
Description
GLM 5.2 (
glm_moe_dsa, served via the DeepSeek-V3 path) uses DeepSeek Sparse Attention with cross-layer indexer sharing: only 21 of 78 layers own an indexer ("full" layers); the remaining 57 "shared" layers reuse the previous full layer's top-k indices and never touch the indexer k-cache. The V1KVCacheManagerallocated the indexer k-cache stride for every layer, so the shared layers' indexer pools were dead memory — 13.6% of the whole KV cache footprint (55,224 B/token instead of 47,700 B/token, i.e. +15.8% effective KV token capacity per rank once removed). On long-context agentic workloads with block reuse, KV capacity directly drives cache hit rate and prefill throughput.Commit 1 — per-layer masked indexer k-cache pool (KVCacheManager V1):
indexerKCacheLayerMaskthrough theKVCacheManager/BlockManager/WindowBlockManagerctors;createIndexerKCachePoolsnow allocates one pool row per masked-in layer (rows follow the KV pool's layer order) and records the layer → pool-row map (getIndexerKCachePoolLayerIdx).indexer_k_cache_layer_maskctor kwarg;get_indexer_k_cache_pool_datatranslates local layer → pool row and rejects masked-out layers.DSACacheManagerderives the mask fromto_sparse_params(pretrained_config, layer_idx).is_full_indexer_layer— the exact source of truth MLA uses to decide whether a layer constructs anIndexermodule (trailing spec/MTP layers always resolve to full). Shared layers getNonepool entries and assert if asked for indexer buffers.get_cache_size_per_token/get_cache_bytes_per_token) charge indexer bytes for full-indexer layers only, PP-sliced consistently with the pool.kv_cache_manager_v2.pyis untouched.NotImplementedError(its FLAT pool-view contract assumes one row per layer);TestGLM52NVFP4::test_nvfp4_nixl_pythonis switched to the C++ NIXL transceiver and renamedtest_nvfp4_nixl(CI list entries updated).Commit 2 — C++ cache transceiver support for the masked pool:
CacheStatecarries per-PP indexer layer counts (indexerLayerNumPerPP; empty = dense fallback to the attention counts), wired through the ctors,operator==,toString, and serialization.targetIRanksForIndexerKCachekeeps the attention pass's rank topology (same connection set) but recomputes per-peer layer counts in indexer layer space (interval intersections of the per-PP indexer prefix sums).splitKVCache/concatKVCacheuse it — plus the self indexer count as the kernel layer count — for the indexer pass.MLACacheFormattersizes indexer-pass buffers with the indexer counts;inquireSupportvalidates indexer layout equality and equal totals, and rejects PP partitions that would produce zero-sized indexer exchanges (a rank or layer overlap without a full-indexer layer).CacheTransceivertakesindexerLayerNumPerPP, validates it against the local pool row count; the Python transceiver gathers it over PP from the manager's indexer layer mask.CacheTransBufferManagersizes the indexer transfer buffer from the pool's actual (masked) layer count.Expected GLM 5.2 server-start accounting:
kv size per token is 47700 bytes/token(was 55,224) and ~+15.8%max tokens in paged KV cacheat the samekv_cache_free_gpu_memory_fraction. Shared layers never used the pools, so model outputs are bitwise-identical.Test Coverage
New tests (all passing on H100):
cpp/tests/unit_tests/batch_manager/kvCacheManagerTest.cpp—IndexerKCachePoolLayerMaskTest(masked pool shape, row mapping, block size) andIndexerKCachePoolDenseDefaultTest(dense layout unchanged without a mask).cpp/tests/unit_tests/executor/serializeUtilsTest.cpp—CacheStateround-trip includingindexerLayerNumPerPP.cpp/tests/unit_tests/multi_gpu/cacheTransceiverTest.cpp— a newAsymmetricalCacheTestWithIndexerLayerMaskend-to-end masked-indexer transfer with ctx/gen PP resharding (also fixes a positional off-by-one in the existingCacheStateconstruction whereisIndexerKCachelanded onenablePartialReuse).Regression: full
kvCacheManagerTestandserializeUtilsTestsuites pass; existing DSA indexer scatter/roundtrip GPU tests pass (dense pool → identity mapping). End-to-end guard:TestGLM52::test_nvfp4(GSM8K) exercises the masked pool implicitly;TestDeepSeekV32covers the dense path.PR Checklist
Please review the following before submitting your PR:
PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.
PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.
Test cases are provided for new code paths (see test instructions)
If PR introduces API changes, an appropriate PR label is added - either
api-compatibleorapi-breaking. Forapi-breaking, includeBREAKINGin the PR title.Any new dependencies have been scanned for license and vulnerabilities
CODEOWNERS updated if ownership changes
Documentation updated as needed
Update tava architecture diagram if there is a significant design change in PR.
The reviewers assigned automatically/manually are appropriate for the PR.
Please check this after reviewing the above items as appropriate for this PR.
GitHub Bot Help
To see a list of available CI bot commands, please comment
/bot help.