Repository navigation
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
|
Hi @ruoqianguo, since you introduced the SM90 MXFP4 backend and safe quantizer in #4843, could you take a look at this staging optimization when you have time? It writes the existing safe quantizer outputs directly into symmetric buffers and fuses routing staging, preserving the quantization arithmetic and EP protocol. Correctness checks and four-rank H20 complete-MoE benchmark results are included in the description. I would appreciate your feedback on whether this fits the backend design. Thanks! |
Thanks @xijiaat , this is a clean, well-scoped change and the write-up is very thorough. I checked it against the #4843 design and it fits. The four-lane Before merge, could you double-check that the backend's 4-GPU suite still passes on the PR head ( A non-blocking suggestion: Possible follow-up, not for this PR: the remaining Torch cast/abs/amax are exact for finite inputs. Reading BF16 directly and reducing amax in-kernel would therefore stay bit-identical while removing three more launches and the FP32 |
|
Thanks @ruoqianguo — confirmed on the current PR head bash tests/moe_ep/run_tests.sh mega_sm90_mxfp4The official suite exited 0, with 33 passed on each of the four ranks: 33 unique cases / 132 rank-case executions, no failures, errors, or skips. In particular:
I also ran the staging regression separately on one GPU: python -m pytest tests/moe_ep/test_sm90_mxfp4_fused_staging.py -v -raResult: 4 passed, exit 0, covering changed-input graph replay, workspace guards/reuse, and the strided-workspace fallback. Environment: PyTorch 2.13.0+cu130, CUDA 13.0, driver 595.71.05, CuTe DSL 4.7.1, NVSHMEM 3.8.0, nvshmem4py 0.4.1, Python 3.12.3. All 10,266 tracked source files matched the frozen PR head before and after testing. No test, kernel, numerical threshold, or safe-quantization setting was changed. I rechecked the GitHub head before posting; it still matches the tested commit. Official four-rank log excerpts — all four pytest summariesSupplementary staging regression log excerptsAn earlier cold-JIT attempt encountered a host-memory cgroup OOM and subsequently timed out. For the successful run, I prebuilt/loaded the standard JIT module in a separate process, used Thanks also for the API-cleanup and BF16/amax-fusion suggestions. Those will be evaluated separately; this report validates the existing PR head without adding either change. |
|
Hi @ruoqianguo, thank you again for your time and helpful feedback. I've added the four-GPU test results above. Whenever you have a chance, please let me know if there's anything else I could clarify or add. I'd be happy to follow up. Thanks! |
|
Thanks for running the four-GPU suite and sharing the results. I have no further blocking comments. The API cleanup and BF16/amax fusion can remain follow-ups. |
|
Hi @jiahanc, when you have a chance, could you please advise whether any additional tests or validation would help with reviewing this PR? I have posted the four-GPU SM90 suite and targeted staging regression results above. I would be happy to add coverage for any specific shapes, edge cases, or configurations you think are missing. Thank you for your time! |
📌 Description
For contiguous BF16 inputs to the SM90 MXFP4 pull backend, safe quantization currently produces temporary FP8/scales and then stages them and the routing metadata into symmetric buffers. Write the existing safe quantizer's results directly to those buffers, copy routing in the same kernel, and clear inactive route IDs on every replay.
The change reuses the existing quantization arithmetic, including tiny-value handling and rounding. It keeps the Torch FP32 cast/abs/amax, weight representation, wire format, public API, and expert-parallel protocol. Other dtypes/layouts, prequantized input, and empty input retain the existing paths. The new H/top-k/device cache is warmed by the existing full-forward warmup before graph capture.
This is a fixed-overhead optimization: complete-MoE gains are largest for small batches and diminish as GEMM/communication dominate. It does not establish an end-to-end model speedup.
🔍 Related Issues
Builds on #4843 (Hopper MXFP4 MegaMoE and safe quantizer, by @ruoqianguo and contributors). #6465 tunes GEMM geometry; this change only fuses safe post-amax staging. #4449 concerns a different backend/staging path. Targeted open/merged PR searches found no equivalent change to this SM90 MXFP4 safe staging path.
🚀 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
pre-commitby runningpip install pre-commit(or used your preferred method).pre-commit install.pre-commit run --all-filesand fixed any reported issues.🧪 Tests
Tests have been added or updated as needed.
All tests are passing (
unittest, etc.). Full suite not run; targeted results below.Final PR source:
pytest -q tests/moe_ep/test_sm90_mxfp4_fused_staging.py— 4 passed on H20-3e. Tests compare exact payload/scale/routing bytes, guard regions, shrinking and empty batches, changed/restored graph inputs, and the fallback path.Additional qualification: 20 shapes / 128 exact staging checks; 30 nonempty staging timing cases, all retained. Hidden sizes 4096/5120/7168, M=1/4/16/128/1024, varying capacity and top-k. Staging latency reduction 4.75–41.11%; this is not the complete-MoE improvement.
Four-rank complete MoE: all 7 cases on both geometries passed exact finite-output comparison for original/changed/restored inputs, with 3 graph replays per phase. Includes skewed routing and an empty rank.
Three rounds of 20 AB/BA pairs per case. Each timing graph contains an unmeasured NCCL alignment gate followed by CUDA events around five complete forward calls; all actual MoE communication is timed. Reported samples use the maximum rank latency. Compilation, validation and warmup are untimed. Both arms share weights, workspace and the same fixed upstream K128 qualification tactic; this is not a best-autotuned backend comparison.
A/A control on H4096/E64/K4: apparent round gains ranged from -0.031% to +0.238%. The +0.122% large-M result below is small and should not be interpreted as a meaningful improvement without further noise controls.
Separate NCU capture at M16/H5120/top-k6/capacity48: compute kernels 6→4, with four intermediate copy operations also removed. Quantizer/fused kernel both use 22 registers/thread; achieved occupancy 43.62%→43.64%. NCU replay times are not benchmark times. The main MoE kernel was not profiled, so no compute/HBM saturation claim is made.
Targeted pre-commit hooks passed for all three changed files, including Ruff and mypy. The full repository test suite and
pre-commit --all-fileswere not run.Environment: 4×H20-3e, SM90; torch 2.13.0+cu130; CuTe DSL 4.7.1; NVSHMEM 3.8.0 / Python 0.4.1. GPU benchmark checkout was
11f41575e13e53f89afd39a5e017577be68ed46e; the two modified files are byte-identical at PR base8256ac5d070268e03a4dfa4a44ededcf041e291a. Both arms also used the already-existing native cleanup fix from #6517. Final PR source and benchmark prototype have identical ASTs (formatting only).Both geometries use I=2048, EP4, capacity=1056, canonical packed E2M1 weights and K32 E8M0 scales. All 60 samples per arm/case are retained; the table uses their combined median, and includes every round's result. These are generic synthetic layer inputs, not V4.1 model-quality or model-throughput measurements.
All-sample ranges
🔬 Experimental Track
flashinfer/experimental/and/or an@flashinfer_experimental_api. Tracking issue: #tests/experimental/and were validated on the intended hardware; a runnable example is included.flashinfer/aot.py, and no experimental backend is reachable frombackend="auto"withoutFLASHINFER_ALLOW_EXPERIMENTAL_AUTO_BACKENDS=1. (Calling an@flashinfer_experimental_apior naming a backend explicitly is itself the opt-in and needs no environment variable.)Reviewer Notes
The H4096 A/B run completed all measurements and correctness checks, then hung during graph/workspace teardown and was stopped by its bounded controller. Its cleanup verified all four GPUs idle. The standalone reproducer explicitly resets captured graphs before destroying the layer; the A/A control and H7168 A/B used this cleanup correction and exited normally. Computation and timing are unchanged.
No extra weight representation is allocated. Quantitative whole-layer peak-memory savings were not isolated, so none are claimed. Timing is warm-cache and uses the same tactic in both arms; it does not prove an advantage over Humming, another backend, or a fully tuned model. At H7168/E384/M1024 the gain is only 0.122%, so this PR should be assessed primarily as a small-batch overhead reduction.
AI assistance (Codex) was used for implementation, validation, and this report.
Standalone complete-MoE reproducer (writes every rank/sample)
Summary by CodeRabbit
-1.