Skip to content

[None][feat] Support the masked DSA indexer k-cache pool in the Python cache transceiver - #17283

Merged
SimengLiu-nv merged 7 commits into
NVIDIA:mainfrom
Tabrizian:feat/glm52-python-masked-indexer
Aug 12, 2026
Merged

[None][feat] Support the masked DSA indexer k-cache pool in the Python cache transceiver#17283
SimengLiu-nv merged 7 commits into
NVIDIA:mainfrom
Tabrizian:feat/glm52-python-masked-indexer

Conversation

@Tabrizian

@Tabrizian Tabrizian commented Aug 5, 2026

Copy link
Copy Markdown
Member

Description

The Python (v2) KV-cache transceiver previously raised NotImplementedError for the per-layer masked DSA indexer k-cache pool (cross-layer indexer sharing, e.g. GLM 5.2), so those checkpoints were forced onto the C++ transceiver — #16558 added a GlmMoeDsaForCausalLM -> CPP preference as a stop-gap while the Python path lacked this support.

This PR teaches the Python transceiver to handle the masked layout, mirroring the C++ support added in #16558:

  • build_page_table (tensorrt_llm/_torch/disaggregation/resource/kv_extractor.py): the indexer REPLICATED pool view now covers only the indexer-owning layers — one buffer_entries row per owning layer, each mapped to its packed pool row via impl.get_indexer_k_cache_pool_layer_idx(lid) — and skips the indexer pool entirely for a layer group with no owning layers (which would otherwise hit the null-pool getter). The dense/unmasked layout is byte-for-byte unchanged.
  • No transfer-machinery changes are needed: it already matches peers per-pool by pool_role + global_layer_id overlap, so a masked subset transfers correctly, including under PP resharding (the generic analogue of the C++ indexerLayerNumPerPP / targetIRanksForIndexerKCache interval logic).
  • With Python support in place, GlmMoeDsaForCausalLM prefers the Python transceiver again like the other DeepSeek-family checkpoints, reverting the CPP override that [None][perf] Allocate DSA indexer k-cache only for layers that own an indexer #16558 added only because Python lacked masked-pool support.

Test Coverage

  • tests/unittest/disaggregated/test_extractor.py::test_v1_dsa_masked_indexer_page_table_covers_owning_layers (new) — builds a V1 KVCacheManager with a per-layer indexer mask ([True, False, True, False]) and asserts the indexer view is REPLICATED, covers exactly the two owning layers, and maps them to the correct packed pool rows/offsets.
  • test_extractor.py::test_v1_dsa_indexer_page_table_is_replicated_with_per_layer_entries and ::test_v1_dsa_indexer_replicated_transfer_across_pp (existing) — continue to guard the dense layout and the end-to-end replicated transfer path.
  • tests/unittest/llmapi/test_llm_args.py::TestDeepseekTransceiverPreference::test_preference_per_architecture — updated to expect PYTHON for glm_moe_dsa again.

Perf

Metric C++/NIXL 2870334 Python no-bounce 2633578 Ratio
Server output throughput 17,051.58 17,561.15 tok/s 102.99%
Server total throughput 2,639,873.42 2,851,155.13 tok/s 108.00%
Client output throughput 15,341.17 15,799.97 tok/s 102.99%
TTFT p50/p95/p99 0.720/1.519/2.422 s 0.668/1.401/2.190 s Lower
E2E p50/p95/p99 1.331/5.206/15.365 s 1.236/4.666/13.711 s Lower

PR Checklist

  • PR description clearly explains what and why.
  • PR follows TRT-LLM coding guidelines.
  • Test cases are provided for new code paths.
  • No API changes (the affected get_preferred_transceiver_runtime is an internal preference hook).

GitHub Bot Help

To see a list of available CI bot commands, please comment /bot help.

Dev Engineer Review

  • build_page_table supports masked indexer K-cache ownership.
  • Masked layers and fully masked groups are omitted.
  • Packed pool-row counts are validated.
  • GlmMoeDsaForCausalLM now prefers the Python transceiver.
  • Bounce transport supports nullable block sizes and distinct physical-pool sizing.
  • No configuration or test-list files changed.
  • The L0_MergeRequest_PR pipeline failed. Another CI run is required after the failures are fixed.

QA Engineer Review

Modified test code covers:

  • Masked, fully masked, dense, and cross-pipeline page-table transfers in tests/unittest/disaggregated/test_extractor.py.
  • Bounce fan-in safety and physical-pool sizing in tests/unittest/disaggregated/test_bounce.py.
  • Python transceiver preference and GLM architecture registration in tests/unittest/llmapi/test_llm_args.py.
  • Masked DSA indexer transfers across asymmetric pipeline parallelism in tests/unittest/disaggregated/test_cache_transceiver_single_process.py.

No corresponding test-db/ or qa/ entries were modified. CI coverage data is unavailable.

Verdict: needs follow-up.

@Tabrizian

Copy link
Copy Markdown
Member Author

/bot run --disable-fail-fast

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

V1 DSA page-table construction now supports masked indexer K-cache layers and omits fully masked pools. GLM DSA models now default to the Python transceiver. Bounce transport sizing counts distinct physical pools, and fan-in validation checks replicated views on both endpoints.

Changes

Masked DSA cache handling

Layer / File(s) Summary
Masked indexer page-table construction
tensorrt_llm/_torch/disaggregation/resource/kv_extractor.py, tests/unittest/disaggregated/test_extractor.py
The extractor filters indexer entries by owning layers, uses packed offsets, omits fully masked groups, validates pool-row counts, and tests dense, masked, replicated, and transfer layouts.
DSA runtime selection
tensorrt_llm/_torch/models/modeling_deepseekv3.py, tests/unittest/llmapi/test_llm_args.py
DeepSeek V3, DeepSeek V3.2, and GLM DSA configurations use "PYTHON". GLM DSA resolves to an independent subclass of the DeepSeek V3 implementation.
Masked cache-manager transfer validation
tests/unittest/disaggregated/test_cache_transceiver_single_process.py
Cache-manager setup, pool initialization, ownership verification, and asymmetric pipeline-parallel transfer tests propagate indexer layer masks.

Bounce transport safety and sizing

Layer / File(s) Summary
Physical pool byte sizing
tensorrt_llm/_torch/disaggregation/native/bounce/impl.py, tests/unittest/disaggregated/test_bounce.py
Bounce transport metadata accepts nullable block sizes. Attention-group sizing sums each distinct physical pool once.
Replicated-view fan-in validation
tensorrt_llm/_torch/disaggregation/native/transfer.py, tests/unittest/disaggregated/test_bounce.py
Fan-in bounce validation checks replicated pool views in both peer and receiver page tables before dispatch.

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

Sequence Diagram(s)

sequenceDiagram
  participant KVCacheManager
  participant KVCacheExtractor
  participant Receiver
  participant PeerPageTable
  participant ReceiverPageTable
  KVCacheManager->>KVCacheExtractor: provide masked layers and packed indices
  KVCacheExtractor->>ReceiverPageTable: build owning-layer views
  Receiver->>PeerPageTable: inspect replicated pool views
  Receiver->>ReceiverPageTable: inspect replicated pool views
  Receiver-->>Receiver: allow or reject fan-in bounce
Loading

Possibly related PRs

Suggested labels: api-compatible

Suggested reviewers: qijune, bowenfu, cascade812

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.50% 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 clearly and concisely identifies the masked DSA indexer pool support added to the Python cache transceiver.
Description check ✅ Passed The description explains the problem, implementation, test coverage, performance results, and checklist status using the required sections.
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/disaggregated/test_extractor.py (1)

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

Annotate indexer_k_cache_layer_mask.

Declare the new parameter as list[bool] | None. This preserves the helper contract and matches the documented global mask format.

As per coding guidelines, “Annotate every function” and “prefer built-in generic types and |.”

🤖 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/disaggregated/test_extractor.py` around lines 211 - 215,
Update the _make_v1_dsa_manager parameter annotation for
indexer_k_cache_layer_mask to list[bool] | None, preserving its existing default
and behavior.

Source: Coding guidelines

tensorrt_llm/_torch/disaggregation/resource/kv_extractor.py (1)

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

Use declared KVCacheManager attributes.

KVCacheManager.__init__ always sets enable_indexer_k_cache and indexer_k_cache_local_layer_mask. Replace both getattr calls with direct attribute access. This keeps the manager contract type-checkable and fails fast on an invalid manager.

As per coding guidelines, “Avoid reflection when ordinary explicit code is sufficient.”

🤖 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 `@tensorrt_llm/_torch/disaggregation/resource/kv_extractor.py` around lines 336
- 337, In the KV cache extraction logic, replace both getattr calls on
kv_cache_manager with direct access to its declared enable_indexer_k_cache and
indexer_k_cache_local_layer_mask attributes, preserving the existing conditional
behavior and allowing invalid managers to fail fast.

Source: Coding guidelines

🤖 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 `@tensorrt_llm/_torch/disaggregation/resource/kv_extractor.py`:
- Around line 336-337: In the KV cache extraction logic, replace both getattr
calls on kv_cache_manager with direct access to its declared
enable_indexer_k_cache and indexer_k_cache_local_layer_mask attributes,
preserving the existing conditional behavior and allowing invalid managers to
fail fast.

In `@tests/unittest/disaggregated/test_extractor.py`:
- Around line 211-215: Update the _make_v1_dsa_manager parameter annotation for
indexer_k_cache_layer_mask to list[bool] | None, preserving its existing default
and behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 37d069cf-5d7c-4823-a88e-1fc952bcb392

📥 Commits

Reviewing files that changed from the base of the PR and between 89bba4c and 83eb699.

📒 Files selected for processing (4)
  • tensorrt_llm/_torch/disaggregation/resource/kv_extractor.py
  • tensorrt_llm/_torch/models/modeling_deepseekv3.py
  • tests/unittest/disaggregated/test_extractor.py
  • tests/unittest/llmapi/test_llm_args.py

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63946 [ run ] triggered by Bot. Commit: 83eb699 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63946 [ run ] completed with state SUCCESS. Commit: 83eb699
/LLM/main/L0_MergeRequest_PR pipeline #51880 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

@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: 3

🧹 Nitpick comments (3)
tensorrt_llm/inputs/prefix_token_cache.py (1)

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

Add complete cache API contracts.

Add return types for _bucket_key() and _find_longest_prefix(). Type tokenizer and **kwargs in encode(), preferably with a tokenizer Protocol. Add docstrings for exported prefix_cache_enabled() and public encode().

As per coding guidelines, “Annotate every function” and “Use docstrings rather than comments for externally usable interfaces.”

Also applies to: 67-70, 96-96

🤖 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 `@tensorrt_llm/inputs/prefix_token_cache.py` at line 30, Complete the cache API
contracts in _bucket_key(), _find_longest_prefix(), encode(), and
prefix_cache_enabled(): add explicit return annotations, type encode()’s
tokenizer and **kwargs (prefer a tokenizer Protocol), and document the exported
prefix_cache_enabled() and public encode() APIs with docstrings.

Source: Coding guidelines

tensorrt_llm/_torch/pyexecutor/py_executor.py (1)

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

Remove the unreachable disabled implementations.

Both methods return before their former logic. Delete the unreachable code and remove now-unused admission helpers if no other caller needs them.

  • tensorrt_llm/_torch/pyexecutor/py_executor.py#L3422-L3427: remove the unreachable admission-controller branch.
  • tensorrt_llm/_torch/pyexecutor/py_executor.py#L3521-L3536: remove the unreachable idle-progress branch.
🤖 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 `@tensorrt_llm/_torch/pyexecutor/py_executor.py` around lines 3422 - 3427,
Remove the unreachable admission-controller branch at
tensorrt_llm/_torch/pyexecutor/py_executor.py:3422-3427 and the unreachable
idle-progress branch at tensorrt_llm/_torch/pyexecutor/py_executor.py:3521-3536
from their respective methods, preserving the active return behavior. Afterward,
remove any admission helpers left unused if no other callers depend on them.
tensorrt_llm/_torch/disaggregation/native/bounce/config.py (1)

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

Use Python 3.10 annotation syntax consistently.

Replace Optional[int] with int | None. Replace List[int] with list[int].

  • tensorrt_llm/_torch/disaggregation/native/bounce/config.py#L121-L123: use int | None for min_blocks and min_bytes.
  • tensorrt_llm/_torch/disaggregation/native/bounce/impl.py#L67-L72: use list[int] for block_bytes_per_group.
  • tensorrt_llm/_torch/disaggregation/native/bounce/impl.py#L102-L114: use list[int] and float | None style where applicable.
🤖 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 `@tensorrt_llm/_torch/disaggregation/native/bounce/config.py` around lines 121
- 123, Use Python 3.10 union and built-in generic annotation syntax
consistently: in config.py lines 121-123, update config_from_size parameters
min_blocks and min_bytes to int | None; in impl.py lines 67-72, change
block_bytes_per_group to list[int]; and in impl.py lines 102-114, replace
applicable List[int] and Optional[float] annotations with list[int] and float |
None.

Sources: Coding guidelines, Learnings

🤖 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 `@tensorrt_llm/inputs/prefix_token_cache.py`:
- Around line 42-53: Update the prefix-cache configuration flow around __init__
and the environment parsing at the referenced locations to safely parse invalid
numeric values with defaults before cache creation. Validate max_entries,
overlap, resync, min_chars, and bucket_chars constructor bounds before assigning
them, explicitly rejecting overlap <= 0, while preserving valid configured
values and preventing cache initialization from raising.
- Around line 96-151: Add direct PrefixTokenCache tests covering exact token
IDs, seam-resynchronization fallback, concurrent access, eviction, and invalid
settings. In PrefixTokenCache.encode, update the cache entry’s position in
_order whenever an existing entry is reused, moving its ID to the most-recent
end before _evict runs, so eviction follows LRU rather than FIFO.

In `@tensorrt_llm/inputs/registry.py`:
- Around line 141-147: Update the exception handling around
PrefixTokenCache.encode in the prefix-cache branch to catch only the dedicated
cache-fallback exception or explicitly enumerated recoverable exceptions.
Preserve the existing cache-disable fallback for those failures, while allowing
programming errors and unexpected tokenizer exceptions to propagate.

---

Nitpick comments:
In `@tensorrt_llm/_torch/disaggregation/native/bounce/config.py`:
- Around line 121-123: Use Python 3.10 union and built-in generic annotation
syntax consistently: in config.py lines 121-123, update config_from_size
parameters min_blocks and min_bytes to int | None; in impl.py lines 67-72,
change block_bytes_per_group to list[int]; and in impl.py lines 102-114, replace
applicable List[int] and Optional[float] annotations with list[int] and float |
None.

In `@tensorrt_llm/_torch/pyexecutor/py_executor.py`:
- Around line 3422-3427: Remove the unreachable admission-controller branch at
tensorrt_llm/_torch/pyexecutor/py_executor.py:3422-3427 and the unreachable
idle-progress branch at tensorrt_llm/_torch/pyexecutor/py_executor.py:3521-3536
from their respective methods, preserving the active return behavior. Afterward,
remove any admission helpers left unused if no other callers depend on them.

In `@tensorrt_llm/inputs/prefix_token_cache.py`:
- Line 30: Complete the cache API contracts in _bucket_key(),
_find_longest_prefix(), encode(), and prefix_cache_enabled(): add explicit
return annotations, type encode()’s tokenizer and **kwargs (prefer a tokenizer
Protocol), and document the exported prefix_cache_enabled() and public encode()
APIs with docstrings.
🪄 Autofix

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: 6c97242f-8dfe-4002-8997-496531318a02

📥 Commits

Reviewing files that changed from the base of the PR and between 83eb699 and 60a26e8.

📒 Files selected for processing (11)
  • tensorrt_llm/_torch/attention_backend/sparse/deepseek_v4/deepseek_v4.py
  • tensorrt_llm/_torch/attention_backend/sparse/dsa.py
  • tensorrt_llm/_torch/disaggregation/native/bounce/config.py
  • tensorrt_llm/_torch/disaggregation/native/bounce/impl.py
  • tensorrt_llm/_torch/pyexecutor/py_executor.py
  • tensorrt_llm/inputs/prefix_token_cache.py
  • tensorrt_llm/inputs/registry.py
  • tests/integration/defs/disaggregated/test_configs/disagg_config_overlap_transceiver_runtime_python_bounce.yaml
  • tests/integration/defs/disaggregated/test_disaggregated.py
  • tests/unittest/_torch/attention/sparse/dsa/test_dsa_indexer.py
  • tests/unittest/disaggregated/test_bounce.py

Comment thread tensorrt_llm/inputs/prefix_token_cache.py Outdated
Comment thread tensorrt_llm/inputs/prefix_token_cache.py Outdated
Comment thread tensorrt_llm/inputs/registry.py Outdated

@fredricz-20070104 fredricz-20070104 left a comment

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.

Review summary - CONCERNS

Verdict: Cannot merge as-is — mergeable_state is dirty (rebase needed), and the PR bundles several unrelated, untested behavioural changes on top of the masked-indexer feature. No proven crash, but the risk-without-test surface is large.

Concerns

  1. [MAJOR] tensorrt_llm/inputs/prefix_token_cache.py - new 177-line cache has no tests

    • What is wrong: encode()/_find_longest_prefix()/_evict() implement a thread-safe LRU + BPE-seam resync splice, but no test file for this module is in the diff.
    • How it fails: with TLLM_PREFIX_TOKEN_CACHE=1, a splice/resync edge case (e.g. len(pids)-reuse <= 0, non-contiguous seam offsets) would silently return wrong token IDs for any prompt ≥ min_chars, corrupting generation. Off-by-default limits blast radius but the path is unexercised.
    • Suggested fix: add unit tests (hit/miss, resync fallback, eviction, byte-identical vs. full tokenization). This module is also unrelated to the PR title — consider splitting it out.
  2. [MAJOR] tensorrt_llm/_torch/pyexecutor/py_executor.py:3422 & :3521 - disagg admission/idle collectives disabled, untested

    • What is wrong: _apply_disagg_transfer_admission now unconditionally returns (requests, False) and _check_disagg_transfer_progress_when_idle returns immediately, removing the in-flight-transfer bound and two rank-scoped collectives.
    • How it fails: correctness (rank-uniformity, completion reaped elsewhere) is asserted only in comments. If any rank ever still needed the status wait, dropping the WORLD/TP collective can hang/diverge disagg ranks; unbounded admission can pressure transfer buffers under load. No test covers this, and it is unrelated to the feature.
    • Suggested fix: cover with a disagg integration test or gate behind a flag; at minimum delete the now-unreachable code below each return.
  3. [MAJOR] tensorrt_llm/_torch/disaggregation/resource/kv_extractor.py:326 - masked transfer only tested at page-table level

    • What is wrong: the masked REPLICATED indexer view is validated by construction only; the PR's claim that the masked subset "transfers correctly, including under PP resharding" has no end-to-end test.
    • How it fails: a per-pool matching mismatch for the masked subset under PP resharding would misroute/drop indexer K-cache and go uncaught.
    • Suggested fix: add a masked-layout analogue of test_v1_dsa_indexer_replicated_transfer_across_pp.

Minor notes (non-blocking)

  • py_executor.py:3428 - remove the dead code after the early returns.
  • config.py:118 - default gate semantics change (min_blocks 96→1, new min_bytes=2 MiB); flag in release notes.
  • kv_extractor.py:336 - replace getattr on always-set manager attrs with direct access.
  • test_extractor.py - annotate indexer_k_cache_layer_mask as list[bool] | None.

QA view

  • Test coverage: partial - dsa.py MTP-draft rebuild and bounce byte-gate are well covered; prefix_token_cache.py and the py_executor disabling are uncovered; masked indexer is construction-only.
  • SM coverage: DSA/GLM-5.2 masked path targets Hopper (sm90) and Blackwell (sm100/fp8); new DSA tests run skip_pre_hopper + DeepGEMM (Hopper only), no explicit Blackwell run for the masked path.
  • Test code: masked page-table test asserts shape only; no prefix-cache test; helper param unannotated.
  • Test time: small - two Hopper-gated unit tests + CPU bounce/extractor cases; integration test only renamed an env var.
  • Needs /qa-verify: yes - disagg behavioural changes + preference flip (GLM 5.2 → PYTHON) + untested new module warrant a real GLM-5.2 disagg run (incl. PP resharding) before trusting.

Possible new issues

  • Unbounded disagg admission may exhaust transfer buffers under concurrency.
  • Removed status-vote collectives depend on rank-uniformity at every site; if violated, cross-rank hang.
  • Byte-gate default change flips which transfers take the coalesced-bounce path for existing models.

What I could not verify

  • Runtime safety of removing the disagg collectives (depends on invariants at other executor call sites not shown).
  • Whether get_indexer_k_cache_pool_layer_idx / local_layer_ids indexing holds under all PP configs.
  • End-to-end masked-indexer transfer correctness — only page-table construction is visible in the diff.

Automated review by NVCortex Lite, run by @fredricz-20070104.

@fredricz-20070104 fredricz-20070104 left a comment

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.

Review summary - Approve (non-blocking)

Approving so this is not blocked on me. The points raised in my review comment above are non-blocking — please read them and address what you agree with before merging.

Worth doing before this is relied on: Bundles disagg-serving behavioural changes (admission control + collective removal) and a masked-indexer transceiver path with no end-to-end disagg test, plus a preference flip (GLM 5.2 now PYTHON) and an untested new tokenization cache; a human QA should run the GLM-5.2 disagg path (incl. PP resharding) before trusting this.

Automated review by NVCortex Lite, run by @fredricz-20070104.

Comment thread tensorrt_llm/_torch/attention_backend/sparse/dsa.py Outdated
Comment thread tests/unittest/_torch/attention/sparse/dsa/test_dsa_indexer.py

@brnguyen2 brnguyen2 left a comment

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.

The core masked-DSA work here is solid — the kv_extractor.py rewrite is correct (I verified the mask is local-layer-keyed on both the Python manager and the C++ getIndexerKCachePoolLayerIdx binding, and the packed-row offset math checks out), and the new tests pin it well. But this PR is six logical commits under a title/description that covers exactly one of them:

  1. Masked DSA indexer support + GLM 5.2 preference revert (described)
  2. min_blocksmin_bytes bounce gate (60a26e8c3, undescribed)
  3. Multi-pool bounce reservation fix (40ff740b2, undescribed)
  4. Removal of the disagg transfer admission controller and per-iteration idle-progress collectives in py_executor.py (d693ae1dc, undescribed)
  5. DSA MTP token-to-request map rebuild fix (00b3b4aed, undescribed)
  6. A new prefix-tokenization cache feature: prefix_token_cache.py + registry hook (174778777, undescribed)

Items 4 and 6 are each PR-worthy on their own. Item 4 in particular changes disagg executor scheduling behavior for every model and deployment, and shipping it silently inside a "[feat] masked DSA indexer" PR means nobody bisecting a future disagg regression will find it from the PR title. Per the repo's own AGENTS.md ("one concern per PR"), please split this — at minimum pull out 4 and 6.

Other whole-PR items:

  • [None] ticket tag: a transceiver feature plus two perf changes and two bug fixes should carry a JIRA/NVBug reference.
  • Undocumented env vars: TLLM_PREFIX_TOKEN_CACHE (+ _ENTRIES/_OVERLAP/_RESYNC/_MIN_CHARS) and TRTLLM_KV_CACHE_BOUNCE_MIN_BYTES are user-visible knobs with no docs anywhere. The old MIN_BLOCKS default also changes semantics (96-block gate → vacuous 1), which alters which transfers bounce on existing deployments.
  • prefix_token_cache.py ships with zero tests — 177 lines of BPE-seam splicing, resync fallback, eviction, and locking, all pure Python and eminently unit-testable. The module docstring cites offline validation (192/192 matches), but nothing in-tree guards it against regression.

Comment thread tensorrt_llm/_torch/pyexecutor/py_executor.py Outdated
Comment thread tensorrt_llm/_torch/pyexecutor/py_executor.py Outdated
Comment thread tensorrt_llm/inputs/prefix_token_cache.py Outdated
Comment thread tensorrt_llm/inputs/prefix_token_cache.py Outdated
Comment thread tensorrt_llm/inputs/registry.py Outdated
Comment thread tests/unittest/disaggregated/test_extractor.py Outdated
@SimengLiu-nv
SimengLiu-nv force-pushed the feat/glm52-python-masked-indexer branch from 60a26e8 to 25b5f9b Compare August 10, 2026 19:03
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
tests/unittest/disaggregated/test_extractor.py (1)

277-421: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add -> None to test_v1_dsa_masked_indexer_page_table_covers_owning_layers.

Coverage is sufficient. The three changed tests are covered by tests/unittest/disaggregated/test_extractor.py, which is registered in l0_a10.yml and l0_h100.yml.

🤖 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/disaggregated/test_extractor.py` around lines 277 - 421, Add
the explicit -> None return annotation to
test_v1_dsa_masked_indexer_page_table_covers_owning_layers, matching the
annotations used by the other test functions. Leave the test behavior unchanged.

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/disaggregated/test_extractor.py`:
- Around line 277-284: Add the required -> None return type annotation to
test_v1_dsa_masked_indexer_page_table_covers_owning_layers, preserving the
test’s existing behavior and docstring.

---

Outside diff comments:
In `@tests/unittest/disaggregated/test_extractor.py`:
- Around line 277-421: Add the explicit -> None return annotation to
test_v1_dsa_masked_indexer_page_table_covers_owning_layers, matching the
annotations used by the other test functions. Leave the test behavior unchanged.
🪄 Autofix

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: ab0831d3-1c79-4405-97df-956d3c3a6d0c

📥 Commits

Reviewing files that changed from the base of the PR and between b582572 and 25b5f9b.

📒 Files selected for processing (6)
  • tensorrt_llm/_torch/disaggregation/native/bounce/impl.py
  • tensorrt_llm/_torch/disaggregation/resource/kv_extractor.py
  • tensorrt_llm/_torch/models/modeling_deepseekv3.py
  • tests/unittest/disaggregated/test_bounce.py
  • tests/unittest/disaggregated/test_extractor.py
  • tests/unittest/llmapi/test_llm_args.py
🚧 Files skipped from review as they are similar to previous changes (5)
  • tensorrt_llm/_torch/models/modeling_deepseekv3.py
  • tests/unittest/llmapi/test_llm_args.py
  • tensorrt_llm/_torch/disaggregation/resource/kv_extractor.py
  • tensorrt_llm/_torch/disaggregation/native/bounce/impl.py
  • tests/unittest/disaggregated/test_bounce.py

Comment thread tests/unittest/disaggregated/test_extractor.py Outdated

@brnguyen2 brnguyen2 left a comment

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.

Approving — the comments below are optional touch-ups, not blockers.

Approving — all prior-round items check out on the current branch, verified against the code rather than the thread:

  • The fan-in bounce gate hole is closed for real: _fanin_bounce_safe (transfer.py:1590) now takes the receiver's own page table and refuses equal-split fan-in when either endpoint advertises a REPLICATED view; the gate unit test covers the masked-representative case (NHD sender / REPLICATED receiver), and test_cache_transceiver_v1_masked_dsa_indexer_across_asymmetric_pp exercises the real KvCacheTransceiverV2 CTX PP2→GEN PP1 path with the metadata rank fully masked. It's registered in l0_h100.yml and the QA list.
  • The branch is still 6 on-theme commits; none of the previously-dropped unrelated changes (py_executor idle check, prefix_token_cache, registry swallow) have crept back.
  • I re-verified the GlmMoeDsaForCausalLM split: _arch_index.py:59 still maps the architecture to modeling_deepseekv3, so lazy registration resolves the new subclass, and the model_type == 'glm_moe_dsa' rewrite in DeepseekV3ForCausalLM.__init__ is inherited.

One non-blocking ask: the PR description is now stale. It still claims "no transfer-machinery changes are needed", but the branch changes transfer.py (the fan-in gate above) and bounce/impl.py — block_bytes_per_group now sums every distinct physical pool in a layer group instead of pool 0 only. That second change fixes a bug that exists on main independent of masking: with bounce enabled, a dense DSA-indexer receiver under-reserves its bounce region (KV pool only) while the sender's coalesced write also carries the indexer fragments, overrunning into the neighboring slot. Please add both to the description; the sizing fix is exactly what someone triaging a bounce corruption will search PR text for. An NVBug reference for that fix would be ideal given it corrects shipped behavior, though I won't block on it.

@SimengLiu-nv

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65393 [ run ] triggered by Bot. Commit: f56fcdc Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

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

@Tabrizian

Copy link
Copy Markdown
Member Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65496 [ run ] triggered by Bot. Commit: f56fcdc Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65496 [ run ] completed with state SUCCESS. Commit: f56fcdc
/LLM/main/L0_MergeRequest_PR pipeline #53240 completed with status: 'SUCCESS'
Pipeline passed with automatic retried tests. Check the rerun report for details.

CI Report

Link to invocation

Signed-off-by: Simeng Liu <109828133+SimengLiu-nv@users.noreply.github.com>
@SimengLiu-nv

Copy link
Copy Markdown
Collaborator

/bot skip --comment "The pipeline passed. Resolve conflict only."

@SimengLiu-nv
SimengLiu-nv enabled auto-merge (squash) August 12, 2026 15:24
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65599 [ skip ] triggered by Bot. Commit: 9bc1c8a Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65599 [ skip ] completed with state SUCCESS. Commit: 9bc1c8a
Skipping testing for commit 9bc1c8a

Link to invocation

@SimengLiu-nv
SimengLiu-nv merged commit d4c771c into NVIDIA:main Aug 12, 2026
8 checks passed
erictsai-nv added a commit to erictsai-nv/TensorRT-LLM that referenced this pull request Aug 13, 2026
…made it prefer the Python transceiver)

Signed-off-by: Eric Tsai <ertsai@nvidia.com>
erictsai-nv added a commit to erictsai-nv/TensorRT-LLM that referenced this pull request Aug 14, 2026
…made it prefer the Python transceiver)

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.