Skip to content

feat: MNNVL Allreduce quant fusion and performance optimization - #3385

Merged
aleozlx merged 15 commits into
flashinfer-ai:mainfrom
timlee0212:shili/mnnvl-allreduce-opts
May 26, 2026
Merged

aleozlx merged 15 commits into
flashinfer-ai:mainfrom
timlee0212:shili/mnnvl-allreduce-opts

Conversation

@timlee0212

@timlee0212 timlee0212 commented May 21, 2026

Copy link
Copy Markdown
Contributor

📌 Description

  • Use named barrier and cluster barrier instead of a sync.
  • Avoid loading local buffer again in oneshot, use template-based fash path for world size <= 8.
  • Adjust grid dispatch policy to use more SMs at the cost of single SM occupancy for small batch sizes.
  • Extended allreduce_fusion so MNNVL supports standard FP8/NVFP4 quant patterns while keeping MoE and packed-group quant paths TRTLLM-only. (replace feat: Add FP8/NVFP4 quant fusion for MNNVL Allreduce #2263 )
  • Added Hopper/Blackwell-only JIT arch gating.
  • Added focused correctness coverage for quant fusion across dtype, strategy, layout, shape, and norm-output variants, plus NVFP4 validation for padded swizzled scale buffers.

Performance Change Dashboard: report.html

For M <= 8, fused oneshot is 6.24% faster latency-weighted and ar_only oneshot is 4.26% faster. The main benefit is from avoiding loading the local buffer in lamport polling.
Fused two-shot gets benefit for relatively larger batch size. The main benefit is from reducing CTA sync overhead by using named barrier instead of syncthread.

🔍 Related Issues

None

🚀 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

  • New Features

    • FP8 and NVFP4 quantized AllReduce + residual-add + RMSNorm fusion with optional quant outputs, scale outputs, and configurable scale layouts; expanded fusion patterns and execution strategies (oneshot/twoshot).
  • Behavior / Validation

    • Stricter shape/dtype/layout checks, default swizzled layout, explicit errors for unsupported quant/layout/CUDA combos, and enforced coupling of quantization with RMSNorm and scale tensors.
  • Documentation

    • Updated API docs and examples describing quantization patterns, layouts, and strategy/reduction-order behavior.
  • Tests

    • End-to-end FP8/NVFP4 tests added, including negative tests validating invalid NVFP4/scale cases.

Review Change Stack

Shiyu Li and others added 12 commits May 20, 2026 11:22
Brings non-quant latency-communication optimizations from the latcomm reference impl into FlashInfer's trtllm_mnnvl_allreduce kernels:

- add typed kernel params and raw-bit Lamport dirty polling

- keep OOB threads in CTA arrival and dirty-buffer clearing

- skip local-rank polling and sanitize polled Lamport payloads

- fuse twoshot allreduce with residual add and RMSNorm

- stage fused RMSNorm inputs with SM90+ TMA/mbarrier helpers
Keep the local-rank Lamport poll skip, but store the local shard and remote payloads in rank-indexed slots so oneshot and twoshot reductions accumulate ranks in the same 0..world_size-1 order everywhere.
@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0c6e5a15-ce10-480d-8756-4f6ddc39264b

📥 Commits

Reviewing files that changed from the base of the PR and between a30023f and 6a384bf.

📒 Files selected for processing (1)
  • include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh

📝 Walkthrough

Walkthrough

Adds FP8/NVFP4 quantized-output support to MNNVL AllReduce fusion: new quant enums/params, unified kernel-params struct, Lamport synchronization hardening, FP8/FP4 quant helpers and emission, expanded dispatch/validation, Python/C++ API extensions, JIT flag, docs entry, and distributed tests.

Changes

MNNVL AllReduce FP8/FP4 Quantization Support

Layer / File(s) Summary
API documentation
docs/api/comm.rst
Adds trtllm_mnnvl_fused_allreduce_add_rmsnorm_quant to the autosummary.
Unified AllReduce dispatch (Python)
flashinfer/comm/allreduce.py
Imports MNNVL quant enums/backends, updates docstring, selects strategy from use_oneshot, validates pattern allowlist including quant patterns, handles layout_code, allocates/wires norm/residual/quant outputs, and passes output_scale/layout_code into MNNVL backend calls.
C++ wrapper validation & param wiring
csrc/trtllm_mnnvl_allreduce.cu
Updates trtllm_mnnvl_allreduce_fusion to accept optional quant inputs, derive/validate quant_type and sf_layout, enforce quantization/RMSNorm coupling and per-quant-type tensor contracts, and wire AllReduceFusionParams with quant/scaling/layout pointers.
Header: types, params, Lamport helpers
include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh
Adds QuantType enum, extends AllReduceFusionParams with quant/scale/layout/stream, introduces AllReduceKernelParams<T>, updates LamportFlags template, and adds sanitize/volatile-load and dirty-sentinel helpers.
Grid config & runtime validation
include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh
Rewrites adjustGridConfig(..., useCluster), adds cluster-aware tuning, and validates quant/RMSNorm coupling and FP4 preconditions for oneshot/twoshot dispatch.
Quant helpers & kernel refactor
include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh
Adds quant_fp8 and quant_nvfp4 helpers; refactors oneshot/twoshot/RMSNorm kernels to accept AllReduceKernelParams<T>, use improved lamport/volatile-load flow, perform cluster-aware reductions, and emit FP8/FP4 outputs based on quant type.
Oneshot & Twoshot dispatch plumbing
include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh
Constructs AllReduceKernelParams<T>, adds dispatch macros selecting kernel instantiations by rmsNormFusion/quantType/CGA, and launches kernels with cudaLaunchKernelEx using cluster-aware grid sizing.
Python wrapper & exported quant API
flashinfer/comm/trtllm_mnnvl_ar.py
Adds MNNVLQuantType, updates the Python wrapper to accept and forward quant params, extends custom-op registration, and adds trtllm_mnnvl_fused_allreduce_add_rmsnorm_quant which validates/allocates quant outputs, normalizes output_scale, calls the extended kernel, and returns quant/result tensors.
JIT compilation flags
flashinfer/jit/comm.py
Computes NVCC flags for supported majors and forwards them into the trtllm_mnnvl_comm JIT module via extra_cuda_cflags; documents target/support and deterministic oneshot reduction intent.
Distributed quantization tests & helpers
tests/comm/test_trtllm_mnnvl_allreduce.py
Adds fp8_quant, dequant, NVFP4 support gating, _prepare_quant_test_data, _assert_quant_close, MNNVL_QUANT_TEST_CASES, test_mnnvl_allreduce_quant_unified, and negative tests verifying FP32/NVFP4 rejection and undersized scale_out buffer errors.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant PythonAPI as flashinfer.comm.allreduce
  participant PyWrapper as trtllm_mnnvl_allreduce_fusion (py)
  participant CppEntry as trtllm_mnnvl_allreduce_fusion (c++)
  participant Kernel
  User->>PythonAPI: call allreduce_fusion(..., pattern, quant_type, output_scale, layout_code)
  PythonAPI->>PyWrapper: prepare args, allocate quant_out/scale_out (if needed)
  PyWrapper->>CppEntry: forward extended args (quant_type, quant_out, sf_out, output_scale, layout_code)
  CppEntry->>Kernel: launch with AllReduceKernelParams (quant/scaling/layout)
  Kernel-->>CppEntry: writes quant_out, scaling_out, residual_out, output
  CppEntry-->>PyWrapper: returns kernel outputs
  PyWrapper-->>PythonAPI: returns (quant_out, scale_out, residual_out, output)
  PythonAPI-->>User: deliver tensors
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related issues

Possibly related PRs

Suggested labels

op: norm

Suggested reviewers

  • yzh119
  • aleozlx
  • bkryu
  • nv-yunzheq
  • jimmyzho
  • cyx-6
  • nvmbreughe

Poem

🐇 I munched on bytes beneath the moon,
FP8 and FP4 hummed a tune.
Lamport guards and kernels tight,
Quantized hops take wing tonight.
Small carrots, big model delight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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 specifically describes the main changes: adding quantization fusion support and performance optimization to MNNVL AllReduce.
Description check ✅ Passed The description covers all key changes, includes performance metrics, checklists are complete, and technical details about optimizations are provided.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 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 and usage tips.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request implements FP8 and NVFP4 quantization fusion for the MNNVL all-reduce backend, extending the unified allreduce_fusion API and adding a specialized Python wrapper. The CUDA kernels were refactored to handle quantization outputs and scaling factors, alongside JIT compilation updates for SM90/SM100 targets. Review feedback highlights potential race conditions due to premature Programmatic Dependent Launch (PDL) triggers, suggests enforcing scalar constraints on quantization scales in Python, and recommends utilizing the sanitizeLamportPayload utility for better code consistency.

Comment thread include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh
Comment thread include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh
Comment thread flashinfer/comm/trtllm_mnnvl_ar.py
Comment thread include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh Outdated
Comment thread include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh Outdated

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

Caution

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

⚠️ Outside diff range comments (1)
include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh (1)

845-895: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Reject partial tails in the oneshot path.

oneshotAllreduceFusionKernel does full-width PackedType loads/stores for input, residual, gamma, and output, but this dispatch path never checks that tokenDim is divisible by sizeof(float4) / sizeof(T). On a tail row, the last live thread will read and write past the token boundary. twoshotAllreduceFusionDispatch already has this guard; oneshot needs the same protection.

🛡️ Proposed guard
 template <typename T>
 cudaError_t oneshotAllreduceFusionDispatch(AllReduceFusionParams const& params) {
   int const numTokens = params.numTokens;
   int const tokenDim = params.tokenDim;
   int const eltsPerThread = sizeof(float4) / sizeof(T);
+
+  FLASHINFER_CHECK(
+      tokenDim % eltsPerThread == 0,
+      "[MNNVL AllReduceOneShot] token_dim must be divisible by %d",
+      eltsPerThread);
 
   auto [blockSize, clusterSize, loadsPerThread] =
       adjustGridConfig(numTokens, tokenDim, eltsPerThread, true);
🤖 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 `@include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh` around lines 845 - 895,
oneshotAllreduceFusionDispatch currently launches oneshotAllreduceFusionKernel
which performs full-width PackedType (float4) loads/stores, but it never rejects
tails so a non-divisible tokenDim will read/write out of bounds; add the same
divisibility guard used in twoshotAllreduceFusionDispatch: compute eltsPerThread
(sizeof(float4)/sizeof(T)) and check tokenDim % eltsPerThread == 0 (or
equivalent ceil_div check) before launching the kernel and return
cudaErrorInvalidValue with a clear FLASHINFER_ERROR/FLASHINFER_CHECK message
referencing oneshotAllreduceFusionKernel, PackedType/float4 and
trtllm_allreduce_fusion::details::CVT_FP4_SF_VEC_SIZE if relevant so that
non-multiple tokenDim values are rejected rather than causing out-of-bounds
accesses.
🤖 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_mnnvl_allreduce.cu`:
- Around line 49-51: The code currently assigns sf_layout from layout_code
allowing any integer except SWIZZLED_8x4 to propagate; instead whitelist
supported QuantizationSFLayout values by checking layout_code.value() and only
accepting QuantizationSFLayout::LINEAR or QuantizationSFLayout::SWIZZLED_128x4
(for both places where sf_layout is computed, e.g., the first occurrence
producing sf_layout and the later occurrence at 79-81), and handle any other
value by setting a safe default or returning/logging an error before assigning
to params.sfLayout so invalid layout codes cannot slip through.

In `@flashinfer/comm/allreduce.py`:
- Around line 696-698: In the TRTLLM MoE reduction branch in allreduce.py the
scale_factor argument is being replaced with 1.0 for any non-float/int, which
drops valid 0-D or 1-element torch.Tensor scalars; update the logic that sets
scale_factor so that if scale_factor is an int/float you keep it, if it's a
torch.Tensor with numel() == 1 you preserve the tensor (do not coerce to 1.0),
otherwise fall back to 1.0; reference the scale_factor variable used in the
TRTLLM MoE reduction path and ensure torch is used to detect tensor types and
numel when implementing the fix.

In `@flashinfer/comm/trtllm_mnnvl_ar.py`:
- Around line 657-780: The helper is missing device checks for caller-provided
tensors and may pass CPU/other-GPU pointers to
module.trtllm_mnnvl_allreduce_fusion; before the native call, validate that
residual_in, gamma, output, residual_out, quant_out, and scale_out (if not None)
are on input.device and either move them with .to(device=input.device,
dtype=their_expected_dtype) or raise a clear ValueError; implement these
checks/implicit moves just before the module.trtllm_mnnvl_allreduce_fusion
invocation so the native kernel always receives tensors on input.device.

In `@flashinfer/jit/comm.py`:
- Around line 40-42: The call to current_compilation_context.get_nvcc_flags_list
in comm.py limits supported_major_versions to [9, 10]; update this invocation to
include 11 and 12 so it becomes [9, 10, 11, 12] (i.e., change the
supported_major_versions argument passed to get_nvcc_flags_list where nvcc_flags
is assigned) to align with the JIT architecture guideline.

In `@include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh`:
- Around line 782-788: The kernel always writes the pre-norm tensor via
params.prenormedPtr (e.g., inside the RMSNormFusion path where
PackedVec<PackedType,T> residualIn, packedAccum and the write
"*reinterpret_cast<PackedType*>(&params.prenormedPtr[threadOffset]) =
packedAccum.packed" occur), which can dereference nullptr when callers omit
residual_out; guard these writes by checking prenormedPtr for non-null before
performing the reinterpret_cast write (same pattern used for optional
outputPtr), and apply the same null-check fix to the other occurrence around
lines 1188-1195 so both fused paths only write prenormedPtr when
params.prenormedPtr != nullptr.

In `@tests/comm/test_trtllm_mnnvl_allreduce.py`:
- Around line 31-40: The functions fp8_quant and dequant are shadowing the
built-in name `input`; rename that parameter (e.g., to `x` or `tensor`) in both
fp8_quant and dequant signatures and all internal references, update associated
type hints and any callers within the test file to use the new parameter name,
and ensure the behavior remains identical (fp8_quant still computes qinput using
the new param and dequant still multiplies by scale and casts to dtype).
- Around line 826-827: Replace the local per-rank check in
test_mnnvl_allreduce_quant_unified that uses torch.cuda.get_device_capability()
with a centralized helper that uses flashinfer.utils.get_compute_capability(...)
to determine major>=10 and then performs a cross-rank agreement (e.g., gather a
boolean support flag via torch.distributed.all_gather_object or similar) so all
ranks decide the same thing; call that helper at the start of the test and skip
the entire test on all ranks if NVFP4/FP4 is unsupported, ensuring the decision
happens before entering any dist.barrier() or loop to avoid hangs (update the
test to reference the helper instead of the inline torch.cuda check and ensure
the skip is executed consistently across ranks).

---

Outside diff comments:
In `@include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh`:
- Around line 845-895: oneshotAllreduceFusionDispatch currently launches
oneshotAllreduceFusionKernel which performs full-width PackedType (float4)
loads/stores, but it never rejects tails so a non-divisible tokenDim will
read/write out of bounds; add the same divisibility guard used in
twoshotAllreduceFusionDispatch: compute eltsPerThread (sizeof(float4)/sizeof(T))
and check tokenDim % eltsPerThread == 0 (or equivalent ceil_div check) before
launching the kernel and return cudaErrorInvalidValue with a clear
FLASHINFER_ERROR/FLASHINFER_CHECK message referencing
oneshotAllreduceFusionKernel, PackedType/float4 and
trtllm_allreduce_fusion::details::CVT_FP4_SF_VEC_SIZE if relevant so that
non-multiple tokenDim values are rejected rather than causing out-of-bounds
accesses.
🪄 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

Run ID: 2ba39c8e-d9cc-441f-b511-7e453710de3f

📥 Commits

Reviewing files that changed from the base of the PR and between 18f4534 and c9eed29.

📒 Files selected for processing (7)
  • csrc/trtllm_mnnvl_allreduce.cu
  • docs/api/comm.rst
  • flashinfer/comm/allreduce.py
  • flashinfer/comm/trtllm_mnnvl_ar.py
  • flashinfer/jit/comm.py
  • include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh
  • tests/comm/test_trtllm_mnnvl_allreduce.py

Comment thread csrc/trtllm_mnnvl_allreduce.cu Outdated
Comment thread flashinfer/comm/allreduce.py
Comment thread flashinfer/comm/trtllm_mnnvl_ar.py
Comment thread flashinfer/jit/comm.py
Comment thread include/flashinfer/comm/trtllm_mnnvl_allreduce.cuh
Comment thread tests/comm/test_trtllm_mnnvl_allreduce.py Outdated
Comment thread tests/comm/test_trtllm_mnnvl_allreduce.py Outdated
@aleozlx aleozlx added the run-ci label May 21, 2026
@aleozlx

aleozlx commented May 21, 2026

Copy link
Copy Markdown
Member

/bot run

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

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

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

[FAILED] Pipeline #52146554: 10/20 passed

@aleozlx

aleozlx commented May 26, 2026

Copy link
Copy Markdown
Member

re-running failed T4 job

@aleozlx
aleozlx enabled auto-merge (squash) May 26, 2026 16:56
@aleozlx
aleozlx merged commit d53f106 into flashinfer-ai:main May 26, 2026
51 of 54 checks 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.

3 participants