Skip to content

[None][feat] Batched physical KV-cache compaction for KV cache compression#16836

Open
Hudayday wants to merge 5 commits into
NVIDIA:mainfrom
Hudayday:feat/compaction-for-kv-cache-compression
Open

[None][feat] Batched physical KV-cache compaction for KV cache compression#16836
Hudayday wants to merge 5 commits into
NVIDIA:mainfrom
Hudayday:feat/compaction-for-kv-cache-compression

Conversation

@Hudayday

@Hudayday Hudayday commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Description

First PR of the TriAttention KV-cache compression series (compaction primitive → eviction algorithm).

This adds an algorithm-neutral, batched physical compaction primitive for
KVCacheManagerV2 paged KV pools: given per-request keep decisions (kept token
ordinals plus per-request move offsets), it packs the move sources and compacts
the pools in place, so a KV cache compression method can physically drop evicted
tokens instead of masking them.

CUDA / C++

  • unfusedAttentionKernels_2_template.h: batched in-place compaction kernels —
    one launch covers a uniform group of layer pools; per request and KV head the
    moves are ascending and never overtake their sources, which makes the forward
    tiled in-place copy safe.
  • thop/sparseKvCacheCompactOp.cpp: trtllm::sparse_kv_cache_compact_layers,
    taking device pointer arrays so one call compacts a whole pool group.

Python host API (tensorrt_llm/_torch/kv_cache_compression/compaction.py)

  • build_compaction_params(layout, ...) -> CompactionParams: called once per
    cache geometry; pre-binds every launch argument (a Triton pack kernel plus the
    native compact calls). Supports dense and sliding-window layer families, and
    an optional draft cache co-compacted under the target's keep decision.
  • compact(params, request_count): the per-round entry — pure pre-bound
    launches, no host-side construction on the generation path.

Framework

  • Rename BaseKVCacheCompressionManagerKVCacheCompressionManager.
  • The steady-generation fast path takes the full prepare path when
    kv_compression_manages_history is set (the cache shrinks mid-generation).

Supported surface: BF16 paged pools in the native [pages, K/V, heads, tokens, dim] layout; kernels target SM100 (Blackwell).

Test Coverage

  • tests/unittest/_torch/kv_cache_compression/test_compaction.py — byte-exact
    oracles against torch references: dense keep set + protected tail, SWA window
    rebase, and draft co-compaction broadcast over the draft's own heads/tables.
  • tests/unittest/_torch/thop/serial/test_sparse_kv_cache_compact.py — native
    op contract: supported geometries, argument validation, and CUDA-graph
    capture safety.
  • tests/unittest/_torch/executor/test_kv_cache_compression_manager.py
    manager rename covered by the existing framework tests.

Dev Engineer Review

  • Implemented algorithm-neutral, batched physical compaction for KVCacheManagerV2 paged KV pools (dense + masked sliding-window/SWA), with optional draft-cache co-compaction.
  • Added CUDA/C++ native support:
    • New native op sparse_kv_cache_compact_layers with runtime validation and BF16-only dispatch.
    • New SM100 BF16 pipelined compaction kernel path using cp.async (and explicit rejection for unsupported head_dim / tokens_per_block geometry).
    • Batch/group-layer invocation wiring in the kernels interface.
  • Added Python/Triton orchestration:
    • New compaction parameter builder (build_compaction_params) and per-round launcher (compact) that packs keep decisions and prepares dense move offsets (plus optional SWA/draft move sources/bases).
  • Updated generation handling so steady-generation “fast path” cache recording is skipped when the active KV cache manager indicates kv_compression_manages_history=True.
  • Renamed the compression manager base class from BaseKVCacheCompressionManager to KVCacheCompressionManager, updating typing imports and the corresponding unit tests.
  • Config/test-list scope: no changes detected under tests/integration/test_lists/ in this PR’s diff.

QA Engineer Review

Test files changed/added:

  • tests/unittest/_torch/executor/test_kv_cache_compression_manager.py
    • Added/verified tests:
      • test_inherits_base_resource_manager
      • test_four_hooks_default_noop
      • test_hooks_accept_extra_kwargs
      • test_resource_counts_are_zero
      • test_length_adjustment_marks_target_and_draft_v2
      • test_rejects_non_v2_ownership
      • test_request_field_defaults_to_zero
      • test_target_update_receives_metadata_before_final_compression
      • test_real_v2_target_receives_relocation_metadata
      • test_prepare_fires_init_on_first_chunk_only
      • test_update_fires_context_end_on_last_chunk
      • test_step_end_fires_once_per_iteration
      • test_free_fires_finish
      • test_returns_none_when_no_algorithm_registered
      • test_warns_for_unregistered_algorithm
      • test_factory_accepts_independent_draft_manager
      • test_eviction_method_predicate_defaults_false
      • test_spec_gate_only_restricts_eviction_methods
      • test_names_importable_from_canonical_modules
      • test_names_not_in_sparse_module
      • test_raises_when_reuse_on
      • test_ok_when_reuse_off
    • Coverage in tests/integration/test_lists/: not found/referenced.
  • tests/unittest/_torch/kv_cache_compression/conftest.py
    • Added test helpers for building/encoding compaction inputs, optional SWA/draft tail setup, and running native compaction.
    • Coverage in tests/integration/test_lists/: not applicable (helpers only); no references found.
  • tests/unittest/_torch/kv_cache_compression/test_compaction.py
    • Added tests:
      • test_eager_compaction_preserves_exact_selected_bytes_and_tail
      • test_eager_compaction_rebases_masked_swa_window_and_tail
      • test_draft_moves_and_pack_match_keep_broadcast_and_tail_oracle
    • Coverage in tests/integration/test_lists/: not found/referenced.
  • tests/unittest/_torch/thop/serial/test_sparse_kv_cache_compact.py
    • Added tests:
      • test_sparse_kv_cache_compact_layers
      • test_sparse_kv_cache_compact_layers_cuda_graph_replay
      • test_sparse_kv_cache_compact_layers_fast_geometry
      • test_sparse_kv_cache_compact_layers_rejects_invalid_launch
    • Coverage in tests/integration/test_lists/: not found/referenced.

Verdict: needs follow-up — confirm/add CI/manual test-list registration for these new/updated unittests (no entries detected under tests/integration/test_lists/).

Hudayday added 3 commits July 24, 2026 01:57
…ssion

Signed-off-by: tianruih <tianruih@nvidia.com>
Signed-off-by: tianruih <tianruih@nvidia.com>
@Hudayday

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #61550 [ run ] triggered by Bot. Commit: 788ff96 Link to invocation

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 097020ea-1b5d-4299-b94f-8296e71e1057

📥 Commits

Reviewing files that changed from the base of the PR and between 63a513d and a5d8ebe.

📒 Files selected for processing (2)
  • tensorrt_llm/_torch/kv_cache_compression/compaction.py
  • tensorrt_llm/_torch/pyexecutor/model_engine.py
💤 Files with no reviewable changes (1)
  • tensorrt_llm/_torch/pyexecutor/model_engine.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tensorrt_llm/_torch/kv_cache_compression/compaction.py

Walkthrough

Adds BF16 sparse KV-cache compaction through a CUDA kernel, Torch operator, Python/Triton orchestration, and tests. Also renames the KV compression manager abstraction and guards the executor fast path when compression manages history.

Changes

Sparse KV cache compaction

Layer / File(s) Summary
BF16 compaction kernel
cpp/tensorrt_llm/kernels/unfusedAttentionKernels*
Adds the compaction contract and BF16 cp.async-pipelined kernel for supported geometries.
Torch operator integration
cpp/tensorrt_llm/thop/*, tests/unittest/_torch/thop/serial/*
Registers, builds, validates, dispatches, and tests the sparse KV compaction operator.
Python compaction planning
tensorrt_llm/_torch/kv_cache_compression/compaction.py
Adds Triton move-source packing, grouped launch preparation, and native compaction execution.
Python compaction validation
tests/unittest/_torch/kv_cache_compression/*
Tests selected-token ordering, protected tails, SWA rebasing, draft pools, and move offsets.
Compression manager integration
tensorrt_llm/_torch/pyexecutor/*, tests/unittest/_torch/executor/*
Renames the compression manager, updates typing and tests, and excludes history-managed compression from the steady-generation fast path.

Estimated code review effort: 5 (Critical) | ~120 minutes

Suggested labels: api-breaking

Suggested reviewers: qijune, pcastongay, yuanjingx87, shixiaowei02, mikeiovine

Sequence Diagram(s)

sequenceDiagram
  participant PythonCompaction
  participant TritonPackKernel
  participant sparse_kv_cache_compact_layers
  participant BF16CompactionKernel
  PythonCompaction->>TritonPackKernel: pack keep decisions into move sources
  PythonCompaction->>sparse_kv_cache_compact_layers: submit grouped pool compaction
  sparse_kv_cache_compact_layers->>BF16CompactionKernel: launch validated BF16 geometry
  BF16CompactionKernel->>BF16CompactionKernel: copy selected K/V tiles into destination pages
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change and follows the required [None][feat] format.
Description check ✅ Passed The description covers the problem, solution, and test coverage, with only the optional checklist section omitted.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/unittest/_torch/kv_cache_compression/test_compaction.py (1)

1-325: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add the new compaction tests to CI/QA lists and guard the SM100-only cases.

  • Added test functions: test_eager_compaction_preserves_exact_selected_bytes_and_tail, test_eager_compaction_rebases_masked_swa_window_and_tail, test_draft_moves_and_pack_match_keep_broadcast_and_tail_oracle.
  • I don’t see entries for tests/unittest/_torch/kv_cache_compression/test_compaction.py in tests/integration/test_lists/test-db/ or qa/; add this file there.
  • Add @requires_sm100 to test_eager_compaction_preserves_exact_selected_bytes_and_tail and test_draft_moves_and_pack_match_keep_broadcast_and_tail_oracle; only the SWA test is currently guarded.

Coverage verdict: needs follow-up.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/_torch/kv_cache_compression/test_compaction.py` around lines 1
- 325, Add tests/unittest/_torch/kv_cache_compression/test_compaction.py to the
relevant CI/QA test lists under tests/integration/test_lists/test-db/ and qa/.
Apply the existing requires_sm100 marker to
test_eager_compaction_preserves_exact_selected_bytes_and_tail and
test_draft_moves_and_pack_match_keep_broadcast_and_tail_oracle, matching the
guard already used by test_eager_compaction_rebases_masked_swa_window_and_tail.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/unittest/_torch/kv_cache_compression/test_compaction.py`:
- Around line 30-31: Add the existing `@requires_sm100` decorator to
test_eager_compaction_preserves_exact_selected_bytes_and_tail and
test_draft_moves_and_pack_match_keep_broadcast_and_tail_oracle. Keep their
current parametrization and test bodies unchanged so both GPU-only tests skip on
non-SM100 or unavailable CUDA environments.

In `@tests/unittest/_torch/thop/serial/test_sparse_kv_cache_compact.py`:
- Around line 189-442: Add the four new test
functions—test_sparse_kv_cache_compact_layers,
test_sparse_kv_cache_compact_layers_cuda_graph_replay,
test_sparse_kv_cache_compact_layers_fast_geometry, and
test_sparse_kv_cache_compact_layers_rejects_invalid_launch—to the appropriate
integration test-list entries under the test-db and QA lists. Preserve the
existing list format and ensure each test is registered for CI/manual QA
execution.

---

Outside diff comments:
In `@tests/unittest/_torch/kv_cache_compression/test_compaction.py`:
- Around line 1-325: Add
tests/unittest/_torch/kv_cache_compression/test_compaction.py to the relevant
CI/QA test lists under tests/integration/test_lists/test-db/ and qa/. Apply the
existing requires_sm100 marker to
test_eager_compaction_preserves_exact_selected_bytes_and_tail and
test_draft_moves_and_pack_match_keep_broadcast_and_tail_oracle, matching the
guard already used by test_eager_compaction_rebases_masked_swa_window_and_tail.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: adf9b668-beac-434e-9638-815dd2f8713e

📥 Commits

Reviewing files that changed from the base of the PR and between 75b39d4 and 788ff96.

📒 Files selected for processing (12)
  • cpp/tensorrt_llm/kernels/unfusedAttentionKernels.h
  • cpp/tensorrt_llm/kernels/unfusedAttentionKernels/unfusedAttentionKernels_2_template.h
  • cpp/tensorrt_llm/thop/CMakeLists.txt
  • cpp/tensorrt_llm/thop/sparseKvCacheCompactOp.cpp
  • tensorrt_llm/_torch/kv_cache_compression/compaction.py
  • tensorrt_llm/_torch/pyexecutor/_util.py
  • tensorrt_llm/_torch/pyexecutor/model_engine.py
  • tensorrt_llm/_torch/pyexecutor/resource_manager.py
  • tests/unittest/_torch/executor/test_kv_cache_compression_manager.py
  • tests/unittest/_torch/kv_cache_compression/conftest.py
  • tests/unittest/_torch/kv_cache_compression/test_compaction.py
  • tests/unittest/_torch/thop/serial/test_sparse_kv_cache_compact.py

Comment thread tests/unittest/_torch/kv_cache_compression/test_compaction.py
Comment thread tests/unittest/_torch/thop/serial/test_sparse_kv_cache_compact.py
Signed-off-by: tianruih <tianruih@nvidia.com>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this compaction is used only for TriAttention, at least for now. It'd be better to create a TriAttention dir here and move this file to the dir.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. The current placement is intentional: compaction.py has no TriAttention concept in it. build_compaction_params() consumes only the V2 cache layout, block offset tables, and a generic "kept ordinals" decision, so any eviction based compression algorithm needs the same mover. That is why it sits at the kv_cache_compression framework level, so if you still prefer a TriAttention dir here, I am happy to move the file there.

*cache_params.pack_args, **cache_params.pack_constexprs
)
for args in cache_params.compact_args:
torch.ops.trtllm.sparse_kv_cache_compact_layers(*args)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed a nested for-loop here. Are we actually launching the kernel this many times?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loop bounds are small constants independent of batch size, layer count, and tokens. The outer loop runs once per cache (target, plus draft under speculative decoding), and the inner one runs once per uniform pool group, which is 1 for homogeneous dense models and 2 for dense plus SWA mixes like GPT-OSS. Each sparse_kv_cache_compact_layers call compacts every layer, request, and head of its pool group in one batched launch, so the worst production case is 2 pack plus 2 compact launches per eviction round.

I have tested it that using this loop is faster than treating SWA as a fake dense layer and evicting them in one kernel.



class BaseKVCacheCompressionManager(BaseResourceManager):
class KVCacheCompressionManager(BaseResourceManager):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this was renamed to KVCacheCompressionManager?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This aligns the name with the other manager classes like KV Cache Manager: the Base prefix is reserved for abstract bases like BaseResourceManager, and this one is a concrete class with no subclass. Pure rename, no behavior change.

and self._get_position_id_offset() == 0
# KV compression shrinks the cache mid-generation; take the full prepare path.
and not getattr(kv_cache_manager,
"kv_compression_manages_history", False)):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to skip this for the kv compression cases?
Nit: remove the comments above.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The steady generation fast path memoizes prepare_inputs for pure decode batches and advances the cached sequence lengths by one per step, which assumes the KV history only grows. Compression physically shrinks the cache mid generation, so the memoized lengths go stale and the model silently runs with wrong history lengths (I hit IMA issue from exactly this). Managers that manage history themselves opt out via this flag; the dense path keeps the fast path. Comment removed as suggested.

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #61550 [ run ] completed with state FAILURE. Commit: 788ff96
/LLM/main/L0_MergeRequest_PR pipeline #49763 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename this file to a more meaningful name, check others.

…drop stale comment

Signed-off-by: tianruih <tianruih@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants