Skip to content

enable batch-M trtllm-gen MoE; refactor trtllm_fused_moe_kernel_launcher - #4281

Open
IwakuraRein wants to merge 10 commits into
flashinfer-ai:mainfrom
IwakuraRein:siyuanf/batch-m-3xfp4-moe
Open

IwakuraRein wants to merge 10 commits into
flashinfer-ai:mainfrom
IwakuraRein:siyuanf/batch-m-3xfp4-moe

Conversation

@IwakuraRein

@IwakuraRein IwakuraRein commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

📌 Description

Refactor csrc/trtllm_batched_gemm_runner.cu; construct batched gemm data according to mTransposeMmaOutput.

🔍 Related Issues

🚀 Pull Request Checklist

Thank you for contributing to FlashInfer! Before we review your pull request, please make sure the following items are complete.

✅ Pre-commit Checks

  • I have installed pre-commit by running pip install pre-commit (or used your preferred method).
  • I have installed the hooks with pre-commit install.
  • I have run the hooks manually with pre-commit run --all-files and fixed any reported issues.

If you are unsure about how to set up pre-commit, see the pre-commit documentation.

🧪 Tests

  • Tests have been added or updated as needed.
  • All tests are passing (unittest, etc.).

Reviewer Notes

Summary by CodeRabbit

  • Performance

    • Improved batched GEMM kernel selection across data types, tensor layouts, tile sizes, and GPU architectures.
    • Workspace sizing and execution now better reflect the selected kernel configuration.
  • Bug Fixes

    • Improved dtype handling for fused MoE operations.
    • Enhanced diagnostics for unsupported kernel configurations.
    • Updated the bundled batched GEMM artifact to a validated build.
  • API Updates

    • Simplified batched GEMM runner options by using activation and weight dtypes directly.
    • Removed the obsolete output-transpose configuration option.

@coderabbitai

coderabbitai Bot commented Jul 30, 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 94434b6e-9c2a-40d0-96e5-1008ce871ef5

📥 Commits

Reviewing files that changed from the base of the PR and between fb5a69a and e85337e.

📒 Files selected for processing (4)
  • csrc/trtllm_batched_gemm_runner.cu
  • csrc/trtllm_fused_moe_runner.cu
  • flashinfer/artifacts.py
  • include/flashinfer/trtllm/batched_gemm/KernelRunner.h
🚧 Files skipped from review as they are similar to previous changes (4)
  • flashinfer/artifacts.py
  • include/flashinfer/trtllm/batched_gemm/KernelRunner.h
  • csrc/trtllm_fused_moe_runner.cu
  • csrc/trtllm_batched_gemm_runner.cu

📝 Walkthrough

Walkthrough

The PR updates TRT-LLM batched GEMM options to use explicit activation and weight dtypes. Config matching, ranking, validation, workspace sizing, and execution now derive orientation and dimensions from candidate or selected configurations. The artifact pin and checksum are updated.

Changes

TRT-LLM GEMM configuration

Layer / File(s) Summary
GEMM option contract and MoE wiring
include/flashinfer/trtllm/batched_gemm/KernelRunner.h, csrc/trtllm_fused_moe_runner.cu
Runner options now expose dtypeAct and dtypeWeights. Fused MoE paths pass activation and weight dtypes directly and remove forced output transposition.
Orientation-aware config selection
csrc/trtllm_batched_gemm_runner.cu
Config matching, filtering, ranking, and validation use candidate transpose orientation, tile dimensions, operand layouts, dtypes, architecture constraints, and per-candidate GEMM problem data.
Selected-config execution and artifact update
csrc/trtllm_batched_gemm_runner.cu, flashinfer/artifacts.py
Workspace sizing, execution, diagnostics, and validation use the selected configuration. The batched GEMM artifact path and checksum are updated.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Runner
  participant CandidateConfig
  participant ConfigValidator
  participant Kernel
  Runner->>CandidateConfig: derive orientation and tile dimensions
  CandidateConfig->>ConfigValidator: build candidate GEMM problem
  ConfigValidator-->>Runner: return selected config
  Runner->>Kernel: size workspace and execute selected configuration
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% 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 identifies the batch-M TRTLLM-gen MoE enablement and fused MoE launcher refactor.
Description check ✅ Passed The description uses the required sections, explains the main changes, and marks pre-commit and test checks as complete.
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 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

Signed-off-by: Siyuan Fu <siyuanf@nvidia.com>
Signed-off-by: Siyuan Fu <siyuanf@nvidia.com>
@IwakuraRein
IwakuraRein force-pushed the siyuanf/batch-m-3xfp4-moe branch from 0097931 to 64567d5 Compare August 3, 2026 20:58
@IwakuraRein

Copy link
Copy Markdown
Collaborator Author

/bot run tests/moe

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

GitLab MR !1121 has been created, and the CI pipeline #60920011 is currently running. I'll report back once the pipeline job completes.

@IwakuraRein
IwakuraRein marked this pull request as ready for review August 3, 2026 23:22
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@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

🤖 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 `@csrc/trtllm_batched_gemm_runner.cu`:
- Around line 367-368: Remove the unconditional selected-config printf near
transposeMmaOutput in csrc/trtllm_batched_gemm_runner.cu:367-368, and remove the
multiprocessor-count printf at csrc/trtllm_batched_gemm_runner.cu:401-407 while
preserving the computed multiprocessor value passed to bmm.run. Do not alter
GEMM execution behavior or add diagnostics unless routed through an explicit
debug facility.
- Around line 401-402: Check the return value of cudaDeviceGetAttribute in the
code initializing multiProcessorCount, using the repository’s established CUDA
error-checking macro. Ensure bmm.run is reached only after successful attribute
retrieval so multiProcessorCount is initialized.
- Around line 482-494: Update cmpFunc to build BatchedGemmData for both idx0 and
idx1 via buildGemmData, then compute each candidate’s rank using its own CTA
estimate before comparing optionsA and optionsB. Ensure the comparator remains
symmetric when mTransposeMmaOutput differs, and apply a deterministic
tie-breaker when the candidate ranks are equal.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 10afd789-3ca9-4866-a2dc-7e6bff12add4

📥 Commits

Reviewing files that changed from the base of the PR and between da42be0 and 64567d5.

📒 Files selected for processing (4)
  • csrc/trtllm_batched_gemm_runner.cu
  • csrc/trtllm_fused_moe_runner.cu
  • flashinfer/artifacts.py
  • include/flashinfer/trtllm/batched_gemm/KernelRunner.h

Comment thread csrc/trtllm_batched_gemm_runner.cu Outdated
Comment on lines 401 to 402
int32_t multiProcessorCount;
cudaDeviceGetAttribute(&multiProcessorCount, cudaDevAttrMultiProcessorCount, device);

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 2 '\bcudaDeviceGetAttribute\s*\(' csrc include
rg -n -C 2 '\bCUDACHECK\s*\(' csrc include

Repository: flashinfer-ai/flashinfer

Length of output: 49636


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Inspect the target function and nearby error-check macros before making a final claim.
wc -l csrc/trtllm_batched_gemm_runner.cu
sed -n '360,430p' csrc/trtllm_batched_gemm_runner.cu
sed -n '1,80p' include/flashinfer/trtllm/common.h

Repository: flashinfer-ai/flashinfer

Length of output: 7168


Check the cudaDeviceGetAttribute result.

If cudaDeviceGetAttribute fails, multiProcessorCount is written only on success, so bmm.run can receive an undefined processor count. Use the repository CUDA error-checking macro.

🤖 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 `@csrc/trtllm_batched_gemm_runner.cu` around lines 401 - 402, Check the return
value of cudaDeviceGetAttribute in the code initializing multiProcessorCount,
using the repository’s established CUDA error-checking macro. Ensure bmm.run is
reached only after successful attribute retrieval so multiProcessorCount is
initialized.

Comment on lines +482 to +494
auto buildGemmData = [&](int64_t configIndex) {
BatchedGemmData data{};
bool const transposeMmaOutput = configs[configIndex].mOptions.mTransposeMmaOutput;
fillGemmProblemDimensions(data, transposeMmaOutput, m, n, k, batchedTokens, numTokens,
numBatches, maxNumCtasInBatchDim);
return data;
};

auto cmpFunc = [&configs, &gemmData, &bmm, &multiProcessorCount](int64_t idx0, int64_t idx1) {
auto cmpFunc = [&configs, &bmm, &multiProcessorCount, &buildGemmData](int64_t idx0,
int64_t idx1) {
auto const& optionsA = configs[idx0].mOptions;
auto const& optionsB = configs[idx1].mOptions;
auto const gemmData = buildGemmData(idx0);

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make cmpFunc symmetric across candidate configurations.

Line 494 builds gemmData only for idx0. Lines 529-535 then use that data to choose between optionsA and optionsB. If the candidates use different mTransposeMmaOutput values, reversing the comparator inputs can change the CTA estimate and make both comparison directions return true.

Build and evaluate problem data for both candidates. Rank each candidate with its own CTA estimate before applying a deterministic tie-breaker.

Proposed comparator fix
-    auto const gemmData = buildGemmData(idx0);
-    int32_t sizeK = gemmData.mProblemDimensions.mK;
+    auto const gemmDataA = buildGemmData(idx0);
+    auto const gemmDataB = buildGemmData(idx1);
+    int32_t sizeK = gemmDataA.mProblemDimensions.mK;
...
     if (optionsA.mTileScheduler != optionsB.mTileScheduler) {
-      auto options = bmm.getOptionsFromConfigAndData(configs[idx0], gemmData);
-      auto numCtas = bmm.getNumCtas(options, gemmData.mProblemDimensions.mMaxNumCtasInTokenDim);
-      if (numCtas > multiProcessorCount) {
-        return optionsA.mTileScheduler == batchedGemm::gemm::TileScheduler::Persistent;
-      } else {
-        return optionsB.mTileScheduler == batchedGemm::gemm::TileScheduler::Persistent;
-      }
+      auto const bmmOptionsA = bmm.getOptionsFromConfigAndData(configs[idx0], gemmDataA);
+      auto const bmmOptionsB = bmm.getOptionsFromConfigAndData(configs[idx1], gemmDataB);
+      auto const numCtasA =
+          bmm.getNumCtas(bmmOptionsA, gemmDataA.mProblemDimensions.mMaxNumCtasInTokenDim);
+      auto const numCtasB =
+          bmm.getNumCtas(bmmOptionsB, gemmDataB.mProblemDimensions.mMaxNumCtasInTokenDim);
+      auto const preferredA =
+          (numCtasA > multiProcessorCount) ==
+          (optionsA.mTileScheduler == batchedGemm::gemm::TileScheduler::Persistent);
+      auto const preferredB =
+          (numCtasB > multiProcessorCount) ==
+          (optionsB.mTileScheduler == batchedGemm::gemm::TileScheduler::Persistent);
+      if (preferredA != preferredB) return preferredA;
+      return optionsA.mTileScheduler == batchedGemm::gemm::TileScheduler::Persistent;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
auto buildGemmData = [&](int64_t configIndex) {
BatchedGemmData data{};
bool const transposeMmaOutput = configs[configIndex].mOptions.mTransposeMmaOutput;
fillGemmProblemDimensions(data, transposeMmaOutput, m, n, k, batchedTokens, numTokens,
numBatches, maxNumCtasInBatchDim);
return data;
};
auto cmpFunc = [&configs, &gemmData, &bmm, &multiProcessorCount](int64_t idx0, int64_t idx1) {
auto cmpFunc = [&configs, &bmm, &multiProcessorCount, &buildGemmData](int64_t idx0,
int64_t idx1) {
auto const& optionsA = configs[idx0].mOptions;
auto const& optionsB = configs[idx1].mOptions;
auto const gemmData = buildGemmData(idx0);
auto buildGemmData = [&](int64_t configIndex) {
BatchedGemmData data{};
bool const transposeMmaOutput = configs[configIndex].mOptions.mTransposeMmaOutput;
fillGemmProblemDimensions(data, transposeMmaOutput, m, n, k, batchedTokens, numTokens,
numBatches, maxNumCtasInBatchDim);
return data;
};
auto cmpFunc = [&configs, &bmm, &multiProcessorCount, &buildGemmData](int64_t idx0,
int64_t idx1) {
auto const& optionsA = configs[idx0].mOptions;
auto const& optionsB = configs[idx1].mOptions;
auto const gemmDataA = buildGemmData(idx0);
auto const gemmDataB = buildGemmData(idx1);
🤖 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 `@csrc/trtllm_batched_gemm_runner.cu` around lines 482 - 494, Update cmpFunc to
build BatchedGemmData for both idx0 and idx1 via buildGemmData, then compute
each candidate’s rank using its own CTA estimate before comparing optionsA and
optionsB. Ensure the comparator remains symmetric when mTransposeMmaOutput
differs, and apply a deterministic tie-breaker when the candidate ranks are
equal.

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

[SUCCESS] Pipeline #60920011: 18/18 executed test jobs passed

@coderabbitai

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

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

[SUCCESS] Pipeline #60920011: 18/18 executed test jobs passed

1 similar comment
@flashinfer-bot

Copy link
Copy Markdown
Collaborator

[SUCCESS] Pipeline #60920011: 18/18 executed test jobs passed

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.

2 participants