Skip to content

[None][fix] Correct RocketKV KT cache byte accounting for FP8 KV cache#16225

Open
eopXD wants to merge 1 commit into
NVIDIA:mainfrom
eopXD:fix/rocketkv-kt-cache-accounting
Open

[None][fix] Correct RocketKV KT cache byte accounting for FP8 KV cache#16225
eopXD wants to merge 1 commit into
NVIDIA:mainfrom
eopXD:fix/rocketkv-kt-cache-accounting

Conversation

@eopXD

@eopXD eopXD commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Description

The RocketKV KT (key-landmark) cache is a separate pool physically allocated at
kt_cache_dtype (see RocketKVCacheManager.__init__:
torch.empty((num_blocks, kt_tokens_per_block, num_kv_heads, head_dim * 2), dtype=kt_cache_dtype)),
independent of the main KV cache dtype. Two accounting methods sized the KT term by the
main KV dtype byte width and folded the (min, max) factor-of-2 into a dtype-dependent
kt_factor:

  • RocketKVCacheManager.get_cache_size_per_token — the pre-allocation memory estimate
    (KV-cache budget path in _util.py).
  • RocketKVCacheManager.get_cache_bytes_per_token — used by calculate_max_num_blocks
    (max_tokens = free_mem_fraction * free_mem / bytes_per_token).

This was numerically correct only when the main KV cache is bf16. With an FP8 KV cache
the KT pool was under-counted by 2×, which over-estimates the block count and over-subscribes
GPU memory (OOM risk), since the KT pool is allocated with the same block count as the primary
pool.

This PR sizes the KT contribution at its own dtype's byte width with an explicit factor of 2,
matching the physically allocated pool regardless of the main KV dtype. The bf16 main-KV path
(the RocketKV default) is numerically unchanged.

Test Coverage

tests/unittest/_torch/attention/sparse/rocketkv/test_rocketkv.py::test_rocketkv_kt_cache_sized_by_kt_dtype_not_kv_dtype

Constructs a RocketKVCacheManager with an FP8 main KV cache + bfloat16 KT cache (so the two
dtypes differ) and asserts get_cache_bytes_per_token() matches the physically allocated
kt_cache_pool_per_layer bytes. It fails on the old code (KT sized at the 1-byte main dtype) and
passes with the fix. The test runs in the L0 pre-merge B200 stage via the existing
unittest/_torch/attention test-db entry (SM100-gated; getSMVersion() < 100 is skipped).

PR Checklist

Please review the following before submitting your PR:

  • PR description clearly explains what and why.

  • 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-compatible or api-breaking. (N/A — internal cache-accounting only, no public API change.)

  • Any new dependencies have been scanned for license and vulnerabilities (N/A — no new dependencies).

  • CODEOWNERS updated if ownership changes (N/A).

  • Documentation updated as needed (N/A — no behavior change to documented interfaces).

  • Update tava architecture diagram if there is a significant design change in PR (N/A).

  • 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.

Summary by CodeRabbit

  • Bug Fixes

    • Improved RocketKV cache memory estimation for FP8 and other KV-cache data types.
    • Corrected key-landmark cache sizing to use its configured data type independently from the main KV cache.
    • Ensured reported cache bytes per token more accurately reflect allocated memory.
  • Tests

    • Added coverage validating key-landmark cache sizing across supported configurations.

The RocketKV KT (key-landmark) cache is a separate pool physically
allocated at kt_cache_dtype, independent of the main KV cache dtype.
Both get_cache_size_per_token (the pre-allocation estimate) and
get_cache_bytes_per_token (used by calculate_max_num_blocks) sized the
KT term by the main KV dtype byte width and folded the (min, max)
factor-of-2 into a dtype-dependent kt_factor. This was correct only when
the main KV cache was bf16; with an FP8 KV cache it under-counted the KT
pool by 2x, over-estimating the block count
(max_tokens = budget / bytes_per_token) and over-subscribing GPU memory.

Size the KT contribution at its own dtype's byte width with an explicit
factor of 2, matching the pool allocated in RocketKVCacheManager.__init__
regardless of the main KV dtype.

Add a unit test that builds a RocketKVCacheManager with an FP8 main KV
cache and a bfloat16 KT cache and asserts get_cache_bytes_per_token()
matches the physically allocated KT pool (fails without the fix).

Co-Authored-By: Yueh-Ting Chen <yueh.ting.chen@gmail.com>
Signed-off-by: Yueh-Ting Chen <yuehtingc@nvidia.com>
@eopXD eopXD requested a review from a team as a code owner July 10, 2026 07:21
@eopXD eopXD requested a review from QiJune July 10, 2026 07:21
@eopXD

eopXD commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator Author

/bot run

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

RocketKV cache byte estimation now separates main KV-cache dtype sizing from KT-cache dtype sizing. A new SM100-gated test validates mixed FP8 KV and bfloat16 KT cache accounting.

Changes

RocketKV cache sizing

Layer / File(s) Summary
Separate KV and KT byte calculations
tensorrt_llm/_torch/attention_backend/sparse/rocket.py
Main KV memory uses the configured KV dtype, while KT memory uses sparse_params.kt_cache_dtype and landmark-slot calculations.
KT dtype sizing regression test
tests/unittest/_torch/attention/sparse/rocketkv/test_rocketkv.py
Adds an SM100-gated test that compares combined cache bytes against separately computed KV and KT allocations.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: jiaganc, yizhang-nv

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the required ticket/type/summary format and accurately describes the RocketKV KT cache accounting fix.
Description check ✅ Passed The PR description includes the required Description, Test Coverage, and PR Checklist sections and clearly explains the fix and test.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

🧹 Nitpick comments (2)
tests/unittest/_torch/attention/sparse/rocketkv/test_rocketkv.py (2)

711-711: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Annotate the new test return type.

Use -> None for this test function.

Proposed fix
-def test_rocketkv_kt_cache_sized_by_kt_dtype_not_kv_dtype():
+def test_rocketkv_kt_cache_sized_by_kt_dtype_not_kv_dtype() -> None:
🤖 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/attention/sparse/rocketkv/test_rocketkv.py` at line
711, Annotate the test function test_rocketkv_kt_cache_sized_by_kt_dtype with
the return type -> None.

Source: Coding guidelines


710-751: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the changed static estimator too.

This regression test covers get_cache_bytes_per_token(), but not the separately modified RocketKVCacheManager.get_cache_size_per_token(). Coverage is insufficient unless another test already exercises that path; add a companion case in tests/unittest/_torch/attention/sparse/rocketkv/test_rocketkv.py or track it as 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/attention/sparse/rocketkv/test_rocketkv.py` around
lines 710 - 751, Add a companion regression test for
RocketKVCacheManager.get_cache_size_per_token() using differing main KV and KT
dtypes, such as FP8 main KV with bfloat16 KT, and assert the KT contribution is
sized from the KT pool dtype rather than the main KV dtype. Reuse the setup and
cleanup pattern from test_rocketkv_kt_cache_sized_by_kt_dtype_not_kv_dtype, or
explicitly track coverage as a follow-up if the static estimator cannot be
exercised here.

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.

Nitpick comments:
In `@tests/unittest/_torch/attention/sparse/rocketkv/test_rocketkv.py`:
- Line 711: Annotate the test function test_rocketkv_kt_cache_sized_by_kt_dtype
with the return type -> None.
- Around line 710-751: Add a companion regression test for
RocketKVCacheManager.get_cache_size_per_token() using differing main KV and KT
dtypes, such as FP8 main KV with bfloat16 KT, and assert the KT contribution is
sized from the KT pool dtype rather than the main KV dtype. Reuse the setup and
cleanup pattern from test_rocketkv_kt_cache_sized_by_kt_dtype_not_kv_dtype, or
explicitly track coverage as a follow-up if the static estimator cannot be
exercised here.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 371e25d8-915b-4a9a-a61b-89694ce5feeb

📥 Commits

Reviewing files that changed from the base of the PR and between e2ce7a6 and bfeaabf.

📒 Files selected for processing (2)
  • tensorrt_llm/_torch/attention_backend/sparse/rocket.py
  • tests/unittest/_torch/attention/sparse/rocketkv/test_rocketkv.py

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58633 [ run ] triggered by Bot. Commit: bfeaabf Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58633 [ run ] completed with state FAILURE. Commit: bfeaabf
/LLM/main/L0_MergeRequest_PR pipeline #47222 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

@eopXD

eopXD commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58667 [ run ] triggered by Bot. Commit: bfeaabf Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58667 [ run ] completed with state SUCCESS. Commit: bfeaabf
/LLM/main/L0_MergeRequest_PR pipeline #47253 completed with status: 'SUCCESS'

CI Report

Link to invocation

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.

2 participants