Skip to content

[None][fix] Tolerate ADP pad-dummy surplus instead of asserting - #17278

Open
lingjiew wants to merge 1 commit into
NVIDIA:mainfrom
lingjiew:user/lingjiew/fix-adp-pad-dummy-assert
Open

[None][fix] Tolerate ADP pad-dummy surplus instead of asserting#17278
lingjiew wants to merge 1 commit into
NVIDIA:mainfrom
lingjiew:user/lingjiew/fix-adp-pad-dummy-assert

Conversation

@lingjiew

@lingjiew lingjiew commented Aug 5, 2026

Copy link
Copy Markdown

Description

Every disaggregated attention-DP generation cell of Qwen3.5-397B dies on

py_executor.py  _pad_attention_dp_dummy_request
    assert self.expected_num_active_requests >= len(self.active_requests)

Several ranks lose their event loop simultaneously and the survivors HangDetector-abort ~300 s later. Attention DP is required to reproduce — the method returns early when it is off, and 54 TEP cells never hit it while 6 of 7 ADP cells did.

Why the invariant breaks

AttentionDpRouter._expected_num_active_requests computes

min(max(ceil(multiplier * fair_share), max(per_rank_loads)), max_num_active_requests)

The per-rank-load floor normally keeps the value at or above this rank's own load — but the hard cap is applied last, so any rank holding max_num_active_requests + 1 requests breaks the relation.

An attention-DP pad dummy does exactly that when it survives an iteration that was skipped fleet-wide: can_queue == False skips both _forward_step and _update_request_states, _update_request_states_tp is the only place the dummy is removed, and the next gather_all_rank_states counts the survivor.

Measured signature

Across 13 cells (dep8 / dep16 / dep32, max_batch_size 4–64), 1,132 occurrences:

value
len(active_requests) - expected_num_active_requests exactly 1, every single time
expected_num_active_requests always exactly max_batch_size

Both follow from the formula above. A random over-subscription would not produce a surplus that is always exactly one, on every topology, at every batch size.

Changes

  1. py_executor.py — replace the bare assert with a warning. Inside this method the expectation is consumed only by the idle-rank test, and a rank holding surplus requests needs no dummy. The tolerated value is clamped into a local so downstream consumers still observe the router's number.

    Returning early instead would be wrong: _count_schedulable_active_requests excludes requests still in KV transfer, so a rank with many active requests can still have none schedulable and legitimately need a dummy. There is a test for that.

  2. _util.py — add qwen3_5_moe to should_enable_dsv4_adp_dummy_fixes. Those branches all sit after the assert, so widening the gate alone does not stop the crash (measured: the run still died on the same line with the widened gate in place), but the model does need them.

    should_enable_dsv4_overlap_headroom is deliberately pinned to deepseek_v4 rather than reusing the widened gate — it doubles max_num_sequences and changes the memory envelope. A test covers that it does not leak.

Relationship to prior work

Happy to fold a reap back in instead of tolerating if reviewers prefer that shape; the warning is deliberately per-occurrence (not warning_once) so a persistent leak stays visible, which was the original review concern.

Test Coverage

  • tests/unittest/_torch/executor/test_py_executor.py
    • test_pad_dummy_tolerates_surplus_over_expected_on_busy_rank — surplus tolerated, no dummy, router value not mutated
    • test_pad_dummy_still_added_when_surplus_requests_are_unschedulable — tolerating must not short-circuit padding
  • tests/unittest/_torch/executor/test_seq_slot_sizing.py
    • test_dsv4_adp_dummy_fix_gateqwen3_5_moe on, PP off, llama unaffected
    • test_dsv4_overlap_headroom_gate — widened gate does not leak into the headroom gate

Silicon validation

GB300 disaggregated serving, Qwen3.5-397B-A17B-NVFP4-V2, 9 ADP cells, 900–3600 s each: tolerance fires 10–273 times per cell, 0 AssertionError, 66,352 decode iterations on a cell that was previously fatal within minutes. Before: 6 of 7 ADP cells died.

PR Checklist

  • PR title has the correct format
  • Test cases added

Dev Engineer Review

  • Replaced the assertion in _pad_attention_dp_dummy_request with warning-based local clamping.
  • Tolerates the observed one-request surplus without terminating the executor.
  • Preserves dummy padding for unschedulable requests.
  • Enables ADP dummy fixes for qwen3_5_moe.
  • Restricts overlap headroom to the validated deepseek_v4 path.
  • Preserves pipeline-parallel gating.
  • No public API, configuration, or test-list changes were introduced.

QA Engineer Review

Added tests:

  • test_pad_dummy_tolerates_surplus_over_expected_on_busy_rank
  • test_pad_dummy_still_added_when_surplus_requests_are_unschedulable

Added qwen3_5_moe gating coverage for single-stage and multi-stage pipelines. The tests also retain coverage for DeepSeek-V4 overlap headroom behavior.

No test-db/ or qa/ entries were added. Reported GB300 validation covered nine Qwen3.5 ADP cells without an AssertionError.

Verdict: sufficient

@lingjiew
lingjiew marked this pull request as ready for review August 5, 2026 04:42
@lingjiew
lingjiew requested review from a team as code owners August 5, 2026 04:42
@lingjiew

lingjiew commented Aug 5, 2026

Copy link
Copy Markdown
Author

@lancelly please review.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The change adds model-specific ADP dummy-fix gates, keeps overlap headroom limited to DeepSeek-V4, and replaces a fatal surplus-request assertion with warning-based normalization. Regression tests cover model gates and schedulable or unschedulable surplus requests.

Changes

ADP dummy handling

Layer / File(s) Summary
Model-specific ADP gates
tensorrt_llm/_torch/pyexecutor/_util.py, tests/unittest/_torch/executor/test_seq_slot_sizing.py
ADP dummy fixes support deepseek_v4 and qwen3_5_moe without pipeline parallelism. DSv4 overlap headroom remains limited to the validated DeepSeek-V4 path. Tests cover single-stage and multi-stage configurations.
Surplus request padding
tensorrt_llm/_torch/pyexecutor/py_executor.py, tests/unittest/_torch/executor/test_py_executor.py
Busy ranks with more active requests than expected now log a warning and normalize the expected count. Tests verify dummy behavior for schedulable and unschedulable surplus requests.

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

Suggested reviewers: tabrizian

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title follows the required format and clearly describes the primary fix for ADP pad-dummy surplus assertions.
Description check ✅ Passed The description explains the issue, root cause, implementation, tests, validation results, and relevant checklist items.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 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 (1)
tests/unittest/_torch/executor/test_py_executor.py (1)

1492-1492: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add return annotations to the new test functions.

Add -> None to both test function definitions. The coding guidelines require annotations on every function.

Also applies to: 1512-1512

🤖 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/executor/test_py_executor.py` at line 1492, Add the
required `-> None` return annotation to both new test functions, including
`test_pad_dummy_tolerates_surplus_over_expected_on_busy_rank` and the additional
test identified by the review range.

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 `@tests/unittest/_torch/executor/test_py_executor.py`:
- Line 1492: Add the required `-> None` return annotation to both new test
functions, including
`test_pad_dummy_tolerates_surplus_over_expected_on_busy_rank` and the additional
test identified by the review range.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 1a5a7dff-c104-43ff-9e51-d407098c848c

📥 Commits

Reviewing files that changed from the base of the PR and between 91fb443 and 7fa1eda.

📒 Files selected for processing (4)
  • tensorrt_llm/_torch/pyexecutor/_util.py
  • tensorrt_llm/_torch/pyexecutor/py_executor.py
  • tests/unittest/_torch/executor/test_py_executor.py
  • tests/unittest/_torch/executor/test_seq_slot_sizing.py

Every disaggregated attention-DP generation cell of Qwen3.5-397B dies on

    py_executor.py  _pad_attention_dp_dummy_request
        assert self.expected_num_active_requests >= len(self.active_requests)

Several ranks lose their event loop at once and the survivors
HangDetector-abort ~300 s later. Attention DP is required to reproduce: the
method returns early when it is off, and 54 TEP cells never hit it while 6
of 7 ADP cells did.

The router derives the expectation as

    min(max(ceil(multiplier * fair_share), max(per_rank_loads)),
        max_num_active_requests)

(AttentionDpRouter._expected_num_active_requests). The per-rank-load floor
normally keeps the value at or above this rank's own load, but the hard cap
is applied last, so any rank holding max_num_active_requests + 1 requests
breaks the relation. An attention-DP pad dummy does exactly that when it
survives an iteration that was skipped fleet-wide: can_queue False skips
both _forward_step and _update_request_states, _update_request_states_tp is
the only place the dummy is removed, and the next gather_all_rank_states
counts the survivor.

The measured signature matches that derivation. Across 13 cells (dep8,
dep16, dep32; max_batch_size 4 to 64), 1132 occurrences:
len(active_requests) - expected_num_active_requests is exactly 1 every
single time, and expected_num_active_requests always equals max_batch_size.

Inside this method the expectation is consumed only by the idle-rank test,
and a rank holding surplus requests needs no dummy, so tolerate the surplus
and warn instead of asserting. The tolerated value is clamped into a local
so downstream consumers still observe the router's number. Returning early
would be wrong: _count_schedulable_active_requests excludes requests still
in KV transfer, so a rank with many active requests can still have none
schedulable and legitimately need a dummy.

Also add qwen3_5_moe to the gate that scopes the existing ADP dummy fixes.
Those branches all sit after the assert, so widening the gate alone does
not stop the crash - measured, the run still died on the same line with the
widened gate in place - but the model does need them.
should_enable_dsv4_overlap_headroom is deliberately pinned to deepseek_v4
rather than reusing the widened gate, because it doubles max_num_sequences
and changes the memory envelope.

Validated on GB300 disaggregated serving (Qwen3.5-397B-A17B-NVFP4-V2, 9 ADP
cells, 900 to 3600 s each): the tolerance fires 10 to 273 times per cell,
0 AssertionError, and 66352 decode iterations on a previously fatal cell.

Signed-off-by: Lingjie Wu <lingjiew@nvidia.com>
@lingjiew
lingjiew force-pushed the user/lingjiew/fix-adp-pad-dummy-assert branch from 7fa1eda to e671221 Compare August 5, 2026 04:55
@coderabbitai

coderabbitai Bot commented Aug 5, 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.

@lancelly lancelly 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.

LGTM. @chienchunhung please take a look, thanks~

@lancelly

lancelly commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63950 [ run ] triggered by Bot. Commit: e671221 Link to invocation

@JunyiXu-nv JunyiXu-nv 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.

Approve to unblock.

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63950 [ run ] completed with state SUCCESS. Commit: e671221
/LLM/main/L0_MergeRequest_PR pipeline #51885 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

@longlee0622

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64029 [ run ] triggered by Bot. Commit: e671221 Link to invocation

@longlee0622
longlee0622 enabled auto-merge (squash) August 5, 2026 10:58

@longlee0622 longlee0622 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.

approve to unblock build generation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64029 [ run ] completed with state SUCCESS. Commit: e671221
/LLM/main/L0_MergeRequest_PR pipeline #51959 completed with status: 'FAILURE'

CI Report

⚠️ Multi-GPU Label Required:
Multi-GPU tests require the ci: full pre-merge approved label on this PR. Ask a member of NVIDIA/trt-llm-ci-approvers to add the label, then re-trigger CI with the same bot command (no rebase needed).

⚠️ 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

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.

5 participants