[None][feat] Add TriAttention KV-cache compression method - #16957
Conversation
Signed-off-by: tianruih <tianruih@nvidia.com>
Signed-off-by: tianruih <tianruih@nvidia.com>
…hannel Eager eviction pipeline (the standalone compression CUDA graph was removed), optimized compaction kernels, and draft KV co-compression: one-model speculation applies the target union keep set to the draft cache and protects the unconfirmed draft tail; modes whose draft KV cannot join the unified eviction fail fast at admission. Signed-off-by: tianruih <tianruih@nvidia.com>
Signed-off-by: tianruih <tianruih@nvidia.com>
Signed-off-by: tianruih <tianruih@nvidia.com>
…l site Signed-off-by: tianruih <tianruih@nvidia.com>
Signed-off-by: tianruih <tianruih@nvidia.com>
# Conflicts: # tensorrt_llm/_torch/pyexecutor/_util.py
- stage layered KV compaction vectors in registers (D64/D128 half-precision) - single-pass eviction cohort bookkeeping - drop the unprepared pack-compaction wrapper - shared keep-set selector base for union and per-head modes - adopt KvCacheCompressionMode and the call-site speculative gate Signed-off-by: tianruih <tianruih@nvidia.com>
Signed-off-by: tianruih <tianruih@nvidia.com>
Signed-off-by: tianruih <tianruih@nvidia.com>
…fig docstring Signed-off-by: tianruih <tianruih@nvidia.com>
Signed-off-by: tianruih <tianruih@nvidia.com>
# Conflicts: # tensorrt_llm/_torch/pyexecutor/_util.py
Signed-off-by: tianruih <tianruih@nvidia.com>
update_resources declared attn_metadata/kv_cache_dtype_byte_size but the executor dispatches those extras to the KV cache manager slot only, and the method body never read them; drop the dead parameters and the docstring sentence that claimed a transparent pass-through. Also document that on_generation_step_begin fires on context-only iterations too, and that it should be split into context/generation-step hooks once an algorithm needs the distinction. Signed-off-by: tianruih <tianruih@nvidia.com>
- Dispatch the config union on the algorithm tag (discriminated union, like sparse attention and speculative configs) and drop the abstract base from the union: a mistyped algorithm now fails config validation with the list of valid tags instead of silently validating as the base class. The factory hard-cast that guarded against base instances is gone with it. - Rename the base class to BaseKvCacheCompressionConfig and give the plain KvCacheCompressionConfig name to the user-facing union alias, matching the sparse/speculative naming convention. - Raise on a config whose algorithm has no registered manager instead of warning and silently running without compression. - Require model_path and calibration_path at config validation time; both are consumed at manager construction and previously failed deep in executor setup (or worse, fell back to an unrelated calibration). - Drop the dead window_size field (nothing reads it; it also occupied a telemetry manifest entry) and its README row, and fix the README rows that still described a removed eviction mode. - Add gt=0 to top_B/beta and collect the manager constructor kwargs in KvCacheCompressionConfig.to_manager_kwargs(). Signed-off-by: tianruih <tianruih@nvidia.com>
The dropped window_size field leaves the manifest; no other entries change. Signed-off-by: tianruih <tianruih@nvidia.com>
Adjacent programs now walk consecutive K pages of one (request, layer, head) and reuse its calibration/phase rows in L2. Median score-kernel time drops 1.8-2.0% across two model geometries and both sequential and shuffled page layouts, bit-exact against the segment-major order. Segments move to the y grid axis, which CUDA caps at 65535; both launch sites validate the request*layer count against that limit so the unbounded x axis stays with the token tiles of long sequences. Signed-off-by: tianruih <tianruih@nvidia.com>
- Promote the prepared Triton launch helper to its own module with a public name (it also backs the score, stats, and union selection launches) and validate the constexpr ordering against the kernel declaration at build time instead of by comment. - Fail fast on combinations that previously degraded silently: selection tensors on the wrong device, swa_window without SWA layers, draft pools without draft layers, and (in the C++ op) flat source indices combined with per-layer source indices, with a unit test for the rejected op combination. - Name the pack kernel launch-shape constants, split combined error messages, rename the pack launch keep_count to decode_keep_count, drop the grouping parameter that never affected grouping, and document the constructor staging-snapshot inputs. - Deduplicate the block-offset encoder into the test conftest, reword generic C++ comments that named one consumer, and document the V2 2*page+plane offset decode in the updater kernel. Signed-off-by: tianruih <tianruih@nvidia.com>
Conflicts: tensorrt_llm/llmapi/__init__.py tensorrt_llm/usage/llm_args_golden_manifest.json
…in merge The merge resolved the manifest to the main side; regenerating restores the KV-cache compression entries alongside the fields main added. Signed-off-by: tianruih <tianruih@nvidia.com>
…pec gate Upstream replaced acceptance_window/acceptance_length_threshold with use_rejection_sampling (base config) and use_relaxed_acceptance_for_thinking (MTP only); the compression spec gate now rejects those, with the same fail-fast intent: eviction is only validated with greedy acceptance. Signed-off-by: tianruih <tianruih@nvidia.com>
Eviction cohorts were grouped by (prompt_len, keep_count) because the batched pipeline treated the pinned prompt length as scalar geometry: the selection rectangle carried a materialized prompt prefix, the score kernel baked TOKEN_START as a compile-time constant, and the C++ compact launch took one destination base. Real batches mix prompt lengths, so a 32-request round split into up to 15 sub-rounds; a profiled step with 13 sub-rounds spent 39.8 ms in update_resources against 2.3 ms for a single round. Prompt lengths are now per-request runtime metadata end to end: - the score kernel reads each request's decode-window origin from a staged token-starts row instead of a constexpr; - selection rectangles are decode-only ([request(, rows), top_B]) with the per-row prompt offset rebasing emitted ordinals to absolute positions; - the pack kernel drops its prompt constants (moves never touch the prompt); - the compact op takes per-request destination bases (contiguous CUDA int32 [batch]), and SWA landing positions rebase per request each round; - the cohort key is gone: one due round launches once, chunked only by the staging memory bound. A cohort mixing prompt lengths is asserted byte-identical to per-request compactions, and the op gains a mixed-bases unit test. Signed-off-by: tianruih <tianruih@nvidia.com>
The explicit instantiations still declared the scalar destination base; match the per-request destinationBases pointer. Signed-off-by: tianruih <tianruih@nvidia.com>
Torch schemas reject a non-default positional parameter after a defaulted one; stub generation aborted on import. Signed-off-by: tianruih <tianruih@nvidia.com>
…buffer set The eviction path kept LRU caches of score staging, keep-set selectors, and batched compaction launches keyed by exact cohort shapes, and split large due cohorts into fixed 32-request chunks. Every new shape paid an allocation storm next to a nearly full KV pool, and the caches were only correct while their keys stayed exact. Now one buffer set is built at first eviction and stays resident: the request capacity follows the executor max batch size, the decode width follows the eviction bound (top_B plus two eviction periods plus draft tokens), and the page-table plane follows max_seq_len plus the protected tail capacity. Buffers rebuild only when the V2 pool views change or a round outgrows them. One generation batch is one eviction round; padding rows carry zero widths and move nothing. Protected tails become per-round state: BatchedKVCacheCompaction sizes its move buffers by a tail capacity and set_protected_tails() loads each cohort per-request tails into the move offsets consumed by the pack kernel and the C++ compact launches. Signed-off-by: tianruih <tianruih@nvidia.com>
|
/bot run --disable-fail-fast |
|
PR_Github #63291 [ run ] triggered by Bot. Commit: |
|
PR_Github #63291 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #63318 [ run ] triggered by Bot. Commit: |
|
PR_Github #63318 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #63352 [ run ] triggered by Bot. Commit: |
|
PR_Github #63352 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #63386 [ run ] triggered by Bot. Commit: |
yihwang-nv
left a comment
There was a problem hiding this comment.
LGTM! The changes to the attention modules are very straightforward.
Signed-off-by: Tianrui 'Hudayday' Hu <32944717+Hudayday@users.noreply.github.com>
|
/bot run --disable-fail-fast |
|
PR_Github #63395 [ run ] triggered by Bot. Commit: |
|
PR_Github #63386 [ run ] completed with state |
|
PR_Github #63395 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #63456 [ run ] triggered by Bot. Commit: |
|
/bot run --disable-fail-fast |
|
PR_Github #63493 [ run ] triggered by Bot. Commit: |
|
PR_Github #63456 [ run ] completed with state |
|
PR_Github #63493 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #63552 [ run ] triggered by Bot. Commit: |
|
PR_Github #63552 [ run ] completed with state |
Summary
betaconfirmed generation tokens, it scores the evictable decode region using offline per-head query calibration, keepsbudgetimportant tokens, compacts their K/V data in place, and releases unused tail pages.KVCacheManagerV2; decode continues to use the model's standard attention backend.union,per_head, andper_layer_perheadeviction modes.unionmode.Performance
On Qwen3-8B, TriAttention (B=2048, β=2048) delivers up to 1.61× the throughput of the Dense baseline at the same batch size (BS=32: 4,930.6 vs. 3,057.5 output tok/s per GPU; 154.1 vs. 95.5 tok/s per user), while its verified capacity frontier reaches 2.63× the Dense baseline’s maximum aggregate throughput (8,053.0 vs. 3,057.5 output tok/s per GPU).

Main Files
_torch/kv_cache_compression/triattention/triattention.pytriattention_cute_score_fused.pytriattention_cute_selection.pytriattention_kernels.pybatch_manager/kvCacheManagerV2Utils.{h,cpp}llmapi/llm_args.pyTriAttentionKvCacheCompressionConfigand KV-compression config dispatchexamples/triattention/README.mdKey Design Decisions
py_num_compressed_tokensmaintains the logical sequence length after the physical cache becomes shorter.Known Limitations
KVCacheManagerV2, and B200/SM100 only.Test Plan
Dev Engineer Review
IndexMapper.gatherKBlockOffsetsbindings.KVCacheManagerV2, and SM100/B200. Limitations include disabled block reuse, unsupported sliding-eviction layouts, attention DP, disaggregated serving, and TP configurations beyond TP1.QA Engineer Review
unittest/_torch/kv_cache_compressionintests/integration/test_lists/test-db/l0_b200.yml.