Skip to content

[https://nvbugs/6432948][fix] Exclude TRTLLM-Gen small tileN (8/16) for all FP8 block-scale MoE tactic selection - #16205

Closed
trtllm-agent wants to merge 1 commit into
NVIDIA:mainfrom
tensorrt-cicd:repair-bot-bug6432948
Closed

[https://nvbugs/6432948][fix] Exclude TRTLLM-Gen small tileN (8/16) for all FP8 block-scale MoE tactic selection#16205
trtllm-agent wants to merge 1 commit into
NVIDIA:mainfrom
tensorrt-cicd:repair-bot-bug6432948

Conversation

@trtllm-agent

@trtllm-agent trtllm-agent commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Description

The small-tile (tileN 8/16) dynB TRTLLM-Gen batched-GEMM cubins flakily hit an illegal memory access
(garbage TMA-descriptor pointer, MMU fault in the gemm2 K-loop). tileN >= 32 is unaffected
(10/10 clean vs. minutes-to-crash baseline on B300 TP=4).

The existing workaround excluded those tiles only when shared experts were fused into the grouped GEMM
(num_fused_shared_experts > 0). That scoping was wrong: the defect is in the shared small-tile cubins
and is not caused by expert fusion. DeepSeek-R1 FP8 TP=8 (unfused) faults identically during warmup,
where the 1/2/8-token shapes are the only ones that can select tileN 8/16 (12288 tokens gets tileN
64/128 and always passes). The same was already observed in #15297, where the IMA reproduced with
num_fused_shared_experts=0 and cuda-gdb pointed at a tileN-8 dynB_sm100f cubin faulting on
UTMALDG.4D.

Changes:

  • Hoist the threshold into a single moeMinTileN() accessor built on common::getIntEnv, replacing two
    independently parsed function-local statics that both used unchecked std::atoi (an unparseable value
    silently disabled the WAR). The knob is renamed to TLLM_MOE_MIN_TILEN, with
    TLLM_MOE_FUSED_MIN_TILEN kept as a deprecated alias since the exclusion is no longer scoped to the
    fused path.
  • Precompute mEligibleTileN in the ctor and drive both tactic selection and the tileN heuristic from
    it. Running computeSelectedTileN on the eligible list rather than on mSupportedTileN keeps the
    excluded tiles from consuming the returned neighbourhood: a shape whose heuristic tile is 8 now gets
    {32, 64, 128} instead of being left with 32 as its only candidate.
  • Reject a threshold that excludes every supported tile at construction time instead of silently
    returning an empty tactic list.
  • Include the problem dimensions in the fused fallback's no-valid-config error so a report from an
    unchecked model is actionable without a repro.

The unfused fallback keeps getDefaultValidConfigIndex. An earlier revision of this PR routed it
through getValidConfigIndices(...).front() as well; that was reverted because the two differ in
ordering, not in validation -- getDefaultValidConfigIndex returns the first entry of the list sorted
by the perf heuristic in KernelRunner.cpp:540-598, whereas getValidConfigIndices(...).front() takes
the first valid pair in raw cartesian order. Switching it would have changed the selected kernel config
for all default-path traffic, which is unrelated to this fix. This PR is now scoped to widening the
tileN exclusion only.

This is a runtime-side workaround; it can be reverted once the kernel-side fix lands.

Test Coverage

No new tests -- this changes tactic selection only and is covered by the existing FP8 block-scale MoE
tests (test_trtllm_fp8_block_scales* in tests/unittest/_torch/modules/moe/test_moe_backend.py, on
l0_b200 / l0_b300).

Crash-freedom:

  • DeepSeek-R1 FP8 TP=8 (unfused): previously faulted during warmup, now passes.
  • B300 TP=4 with fused shared experts: 10/10 clean runs (unchanged from the previous WAR).

Cost of the exclusion, measured op-level on B200 with DeepSeek-R1 FP8 EP=8 shapes
(hidden=7168, intermediate=2048, num_experts=256, local_experts=32, top_k=8). Each (num_tokens, tileN)
combination runs in its own process; the number reported is the best config for that tile, i.e. what the
autotuner would converge to.

num_tokens best {8,16} best {32,64,128} delta
1 34.8 us 34.7 us -0.18%
2 34.3 us 34.8 us +1.56%
4 35.4 us 36.4 us +2.93%
8 38.1 us 39.1 us +2.62%
16 47.7 us 50.2 us +5.29%
32 50.5 us 50.7 us +0.34%
64 54.9 us 54.5 us -0.77%

Worst case is +5.3% at 16 tokens, with every other point within +/-3% and two points slightly faster.
Note that the small tiles did not fault during this sweep -- the IMA is flaky and reproduces with
cascaded runs over real captured token_ids -- so these numbers bound the cost of the WAR but say
nothing about its necessity.

TLLM_MOE_MIN_TILEN=0 restores the previous behaviour for A/B experiments.

PR Checklist

Please review the following before submitting your PR:

  • PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.

  • 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. For api-breaking, include BREAKING in the PR title.

  • Any new dependencies have been scanned for license and vulnerabilities

  • CODEOWNERS updated if ownership changes

  • Documentation updated as needed

  • Update tava architecture diagram if there is a significant design change in PR.

  • The reviewers assigned automatically/manually are appropriate for the PR.

  • Please check this after reviewing the above items as appropriate for this PR.

Links

GitHub Bot Help

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

@coderabbitai

coderabbitai Bot commented Jul 9, 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

FP8 block-scale MoE tactic selection now excludes undersized tiles for fused and unfused workloads. Fallback selection validates configurations, skips undersized tiles, prioritizes the heuristic tile, and errors when no valid configuration exists.

Changes

FP8 MoE tactic selection

Layer / File(s) Summary
Universal tile filtering and fallback validation
cpp/tensorrt_llm/thop/fp8BlockScaleMoe.cpp
The minimum tile-size filter now applies to fused and unfused workloads. Fallback selection uses validated configurations, skips undersized tiles, prioritizes the heuristic tile, and reports an error when no valid configuration exists.

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

Suggested reviewers: barry-delaney

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The stated objectives describe an unrelated FMHA JIT warmup flag, while the changes implement FP8 MoE tile exclusion. Align the PR objectives with the implemented FP8 block-scale MoE workaround, or change the code and description to implement the stated warmup fix.
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title clearly describes the FP8 block-scale MoE tileN exclusion and includes the valid bug reference and fix type.
Description check ✅ Passed The description explains the defect, scope, implementation, testing, performance impact, fallback behavior, and checklist status.
Linked Issues check ✅ Passed The PR references NVBugs 6432948 in both the title and the Links section.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6432948 branch 3 times, most recently from 98dcf31 to 39b1dd5 Compare July 15, 2026 01:53
@trtllm-agent
trtllm-agent requested review from a team as code owners July 15, 2026 01:53
Comment thread tests/integration/test_lists/waives.txt Outdated
@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6432948 branch from 39b1dd5 to 2995242 Compare July 16, 2026 00:19
@yufeiwu-nv
yufeiwu-nv removed their request for review July 16, 2026 05:39
@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6432948 branch from 2995242 to 4cb6611 Compare July 18, 2026 08:36
@mikeiovine
mikeiovine removed the request for review from Tabrizian July 20, 2026 15:44
@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6432948 branch from 4cb6611 to acb9a9d Compare August 6, 2026 16:54
@trtllm-agent
trtllm-agent requested a review from a team as a code owner August 6, 2026 16:54
@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6432948 branch 22 times, most recently from 298e6ec to 94ec436 Compare August 19, 2026 12:07
@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6432948 branch 3 times, most recently from 95a8a46 to b98332e Compare August 20, 2026 12:26
…FP8 block-scale MoE

The small-tile (tileN 8/16) dynB TRTLLM-Gen batched-GEMM cubins flakily hit an
illegal memory access (garbage TMA-descriptor pointer, MMU fault in the gemm2
K-loop). tileN >= 32 is unaffected (10/10 clean vs minutes-to-crash baseline on
B300 TP=4).

The existing workaround excluded those tiles only when shared experts were fused
into the grouped GEMM (num_fused_shared_experts > 0). That scoping was wrong: the
defect is in the shared small-tile cubins and is not caused by expert fusion.
DeepSeek-R1 FP8 TP=8 (unfused) faults identically during warmup, where the
1/2/8-token shapes are the only ones that can select tileN 8/16 (12288 tokens
gets tileN 64/128 and always passes). The same was already observed in NVIDIA#15297,
where the IMA reproduced with num_fused_shared_experts=0.

Changes:

- Hoist the threshold into a single moeMinTileN() accessor built on
  common::getIntEnv, replacing two independently parsed function-local statics
  that both used unchecked std::atoi. Rename the knob to TLLM_MOE_MIN_TILEN and
  keep TLLM_MOE_FUSED_MIN_TILEN as a deprecated alias, since the exclusion is no
  longer scoped to the fused path.
- Precompute mEligibleTileN in the ctor and drive both tactic selection and the
  tileN heuristic from it. Running computeSelectedTileN on the eligible list
  rather than on mSupportedTileN keeps the excluded tiles from consuming the
  returned neighbourhood: a shape whose heuristic tile is 8 now gets
  {32, 64, 128} instead of being left with 32 as its only candidate.
- Reject a threshold that excludes every supported tile at construction time
  instead of silently returning an empty tactic list.
- Include the problem dimensions in the fused fallback's no-valid-config error
  so a report from an unchecked model is actionable without a repro.

The unfused fallback keeps getDefaultValidConfigIndex. An earlier revision of
this change routed it through getValidConfigIndices(...).front() as well, but
that helper returns the first pair in raw cartesian order, whereas
getDefaultValidConfigIndex returns the first entry of the list sorted by the
perf heuristic in KernelRunner.cpp. Switching it would have changed the selected
kernel config for all default-path traffic, which is unrelated to this fix.

Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
@zhaoyangwang-nvidia

Copy link
Copy Markdown
Collaborator

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #68644 [ run ] triggered by Bot. Commit: 47e9b5e Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #68644 [ run ] completed with state FAILURE. Commit: 47e9b5e
/LLM/main/L0_MergeRequest_PR pipeline #56048 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

@zhaoyangwang-nvidia

Copy link
Copy Markdown
Collaborator

The PR fix was not the root case, #18133 fix it, closed this PR.

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.

9 participants