[None][chore] Remove one-warp-per-token policy from MoE A2A kernels#14550
Conversation
89b3f22 to
7839c5b
Compare
📝 WalkthroughWalkthroughThis PR removes the ChangesMoE A2A Threading Policy Removal
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
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)
cpp/tensorrt_llm/common/envUtils.cpp (1)
549-558:⚠️ Potential issue | 🟠 Major | ⚡ Quick winTreat malformed block-size env vars as invalid instead of throwing.
getIntEnv()usesstd::stoi, so a value likeTLLM_MOE_A2A_DISPATCH_BLOCK_SIZE=foothrows beforesanitizeBlockSize()runs. That breaks the new “default 256 if unset or invalid” contract and turns a bad debug knob into a hard failure.Proposed fix
+namespace +{ + +int getSanitizedBlockSize(char const* name) +{ + try + { + return sanitizeBlockSize(getIntEnv(name)); + } + catch (std::exception const&) + { + TLLM_LOG_WARNING("Invalid value for %s. Falling back to 256.", name); + return sanitizeBlockSize(std::nullopt); + } +} + +} // namespace + int getEnvMoeA2ADispatchBlockSize() { - static int const kBlock = sanitizeBlockSize(getIntEnv("TLLM_MOE_A2A_DISPATCH_BLOCK_SIZE")); + static int const kBlock = getSanitizedBlockSize("TLLM_MOE_A2A_DISPATCH_BLOCK_SIZE"); return kBlock; } int getEnvMoeA2ACombineBlockSize() { - static int const kBlock = sanitizeBlockSize(getIntEnv("TLLM_MOE_A2A_COMBINE_BLOCK_SIZE")); + static int const kBlock = getSanitizedBlockSize("TLLM_MOE_A2A_COMBINE_BLOCK_SIZE"); return kBlock; }🤖 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 `@cpp/tensorrt_llm/common/envUtils.cpp` around lines 549 - 558, The getEnvMoeA2ADispatchBlockSize and getEnvMoeA2ACombineBlockSize rely on getIntEnv which calls std::stoi and will throw for malformed values (e.g. "foo"); change these accessors to treat parse errors as "no value" so sanitizeBlockSize can apply the default. Concretely, wrap the integer parsing used by getIntEnv (or add a safe wrapper) to catch std::invalid_argument/std::out_of_range and return an indicator of "unset/invalid" (e.g., optional/negative sentinel) instead of letting the exception propagate, then call sanitizeBlockSize with that safe result in both getEnvMoeA2ADispatchBlockSize and getEnvMoeA2ACombineBlockSize so malformed env vars fall back to the default 256 behavior. Ensure you reference getIntEnv, sanitizeBlockSize, getEnvMoeA2ADispatchBlockSize, and getEnvMoeA2ACombineBlockSize when making the change.
🤖 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 `@cpp/tensorrt_llm/kernels/communicationKernels/moeAlltoAllKernels.cu`:
- Around line 625-630: The launch block containing SWITCH_BOOL(...,
SWITCH_TOP_K(..., { ... launchWithPdlWhenEnabled("moeA2ADispatchKernel",
kernel_fn, ... ) }) is failing pre-commit formatting; run clang-format (or your
repo's formatter) on this region so the SWITCH_BOOL / SWITCH_TOP_K nesting, the
auto kernel_fn = moeA2ADispatchKernel<BlockPolicy, TOP_K, EPLB_STATS>; line, and
the launchWithPdlWhenEnabled(...) call are reformatted to match project style
and fix pre-commit checks.
---
Outside diff comments:
In `@cpp/tensorrt_llm/common/envUtils.cpp`:
- Around line 549-558: The getEnvMoeA2ADispatchBlockSize and
getEnvMoeA2ACombineBlockSize rely on getIntEnv which calls std::stoi and will
throw for malformed values (e.g. "foo"); change these accessors to treat parse
errors as "no value" so sanitizeBlockSize can apply the default. Concretely,
wrap the integer parsing used by getIntEnv (or add a safe wrapper) to catch
std::invalid_argument/std::out_of_range and return an indicator of
"unset/invalid" (e.g., optional/negative sentinel) instead of letting the
exception propagate, then call sanitizeBlockSize with that safe result in both
getEnvMoeA2ADispatchBlockSize and getEnvMoeA2ACombineBlockSize so malformed env
vars fall back to the default 256 behavior. Ensure you reference getIntEnv,
sanitizeBlockSize, getEnvMoeA2ADispatchBlockSize, and
getEnvMoeA2ACombineBlockSize when making the change.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 80651b15-7e08-4e09-bdf0-9b7dffc84353
📒 Files selected for processing (5)
cpp/tensorrt_llm/common/envUtils.cppcpp/tensorrt_llm/common/envUtils.hcpp/tensorrt_llm/kernels/communicationKernels/moeAlltoAllKernels.cucpp/tensorrt_llm/kernels/communicationKernels/moeAlltoAllKernels.hcpp/tensorrt_llm/thop/moeAlltoAllOp.cpp
7839c5b to
8e0dd17
Compare
8e0dd17 to
ec26ba0
Compare
|
Addressed CodeRabbit feedback in
|
BlockPolicy (one-block-per-token) is the right default for modern MoE
inference. WarpPolicy was kept for the case where each token has very
little work, but production models have hidden sizes well above that
threshold. Removing the unused path simplifies launch logic and cuts
~100 lines.
Microbenchmark on B300x8 (blog18 repro) for context:
- At hidden ~ 4096+ (any quant) block wins across the full batch sweep,
e.g. at h=4096, b=4096 block is ~5% faster than warp.
- Warp only catches up in a narrow corner: small hidden (e.g. ~1024) +
aggressive quant (NVFP4/MXFP4) + large batch (b>=2048). That regime
is not representative of current models.
- The warp combine kernel is also notably slower than block at
small/medium batches due to grid sizing.
The block path was already the default; no behavior change for users
not overriding TLLM_MOE_A2A_ONE_BLOCK_PER_TOKEN.
Removed: WarpPolicy struct, SWITCH_POLICY macro, grid_size_warp paths
in dispatch / prepare-combine / combine launches, one_block_per_token
field from MoeA2A{Dispatch,Combine}Params, getEnvMoeA2AOneBlockPerToken
and the env knob.
Signed-off-by: Bo Li <22713281+bobboli@users.noreply.github.com>
|
/bot run |
|
PR_Github #50289 [ run ] triggered by Bot. Commit: |
|
PR_Github #50289 [ run ] completed with state
|
|
/bot run |
|
PR_Github #50409 [ run ] triggered by Bot. Commit: |
|
PR_Github #50409 [ run ] completed with state
|
|
/bot run |
|
PR_Github #50447 [ run ] triggered by Bot. Commit: |
|
PR_Github #50447 [ run ] completed with state
|
|
/bot run |
|
PR_Github #50503 [ run ] triggered by Bot. Commit: |
|
PR_Github #50503 [ run ] completed with state |
…VIDIA#14550) Signed-off-by: Bo Li <22713281+bobboli@users.noreply.github.com>
#3371) … this option as it is never beneficial <!-- .github/pull_request_template.md --> ## 📌 Description <!-- What does this PR do? Briefly describe the changes and why they’re needed. --> See TRT-LLM corresponding PR NVIDIA/TensorRT-LLM#14550 ## 🔍 Related Issues <!-- Link any related issues here --> ## 🚀 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 - [x] I have installed `pre-commit` by running `pip install pre-commit` (or used your preferred method). - [x] I have installed the hooks with `pre-commit install`. - [x] 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](https://pre-commit.com/). ## 🧪 Tests - [x] Tests have been added or updated as needed. - [x] All tests are passing (`unittest`, etc.). ## Reviewer Notes <!-- Optional: anything you'd like reviewers to focus on, concerns, etc. --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * MoE all-to-all now always uses one-block-per-token scheduling across the system. * Attempts to disable this mode via configuration are ignored and will emit a warning informing users the legacy option is no longer supported. * Selecting the legacy (warp-level) scheduling now produces an explicit error instead of silently falling back. * Documentation and comments updated to reflect the always-on behavior. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/flashinfer-ai/flashinfer/pull/3371?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary
Drop the
WarpPolicy(one-warp-per-token) code path from MoE A2A dispatch and combine kernels, keeping onlyBlockPolicy(one-block-per-token).Motivation
BlockPolicywas already the default.WarpPolicyis only beneficial when each token has very little work — i.e. very small hidden sizes — which is not representative of modern MoE models. The "many CTAs" concern that motivatesWarpPolicyonly triggers at batch sizes well above production. Keeping a code path that wins only outside the target regime — and silently regresses small/medium batches via the combine kernel — is not worth the maintenance cost.Supporting data
B300x8, EP=8, NVLink one-sided, blog18 repro (
tests/microbenchmarks/bench_moe_comm.py,--perfect_router, median dispatch+combine µs across ranks).Modern hidden sizes —
BlockPolicywins across the full batch sweep:WarpPolicyonly catches up in a narrow corner — small hidden + aggressive quant + large batch:Combine-side
WarpPolicyis multiple × slower thanBlockPolicyat small/medium batches due to grid sizing (e.g. h=7168 FP8 b=1: 23 µs block vs 208 µs warp; h=4096 FP8 b=64: 23 µs vs 149 µs). This drags total latency far below block until b≈1024 across all configs.What changes
WarpPolicystruct,SWITCH_POLICYmacro, and allgrid_size_warppaths in dispatch / prepare-combine / combine launches.one_block_per_tokenfield fromMoeA2ADispatchParamsandMoeA2ACombineParams.getEnvMoeA2AOneBlockPerToken()and theTLLM_MOE_A2A_ONE_BLOCK_PER_TOKENenv knob.No behavior change for users not overriding the env var.