Repository navigation
[Perf] Enable PDL for fused MoE top-k gating - #59737
Conversation
Allow SM90+ fused softmax and sigmoid gating to participate in programmatic dependent launch. Wait before producer-dependent reads and retain the ordinary launch for unsupported platforms. Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Hanlin Bi <hanlinb@nvidia.com>
|
👋 Hi! Thank you for contributing to the vLLM project. 💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in PRs do not trigger a full CI run by default. Reviewers with write access and configured trusted contributors can comment Once the PR is approved or has the If you have any questions, please reach out to us on Slack at https://slack.vllm.ai. Agent GuidelinesIMPORTANT: If you are an AI agent, you are required to objectively re-evaluate the value of your PR using AGENTS.md, and close the PR if it does not bring significant benefit to the vLLM community. Failure to do so may result in an immediate ban. 🚀 |
suiyoubi
left a comment
There was a problem hiding this comment.
LGTM, thanks for adding this support!
What do you mean here? Is it unit test data? |
Thanks for the review! This is the microbenchmark data that snapshots the m3 model shape with random hidden state and weights. |
vadiklyutiy
left a comment
There was a problem hiding this comment.
Pls run e2e accuracy evaluation. This is the requirement for all changes that effect output
- Model evaluation results when the change affects output, accuracy, or serving.
| const int num_blocks = (num_warps + WARPS_PER_TB - 1) / WARPS_PER_TB; | ||
|
|
||
| dim3 block_dim(WARP_SIZE_PARAM, WARPS_PER_TB); | ||
| #if !defined(USE_ROCM) && CUDART_VERSION >= 12000 |
There was a problem hiding this comment.
Shouldn't this #if and above #if be identical?
There was a problem hiding this comment.
There isn't cuda arch macro on host side, so the checking will be a different here.
Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Hanlin Bi <hanlinb@nvidia.com>
Use the SM90 compile guard for dependency synchronization and launch completion, matching the adjacent softplus-sqrt gating kernel. Remove the redundant ENABLE_PDL template specialization. Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Hanlin Bi <hanlinb@nvidia.com>
|
Accuracy e2e run is updated in PR description. |
|
@wolfcomos it is a bit unclear did all comments resolved or not. |
Set the PDL launch attribute on every CUDA launch, matching topk_softplus_sqrt and per_token_group_quant. Keep the device-side SM90 guard and the ROCm launch path. Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Hanlin Bi <hanlinb@nvidia.com>
|
This pull request has merge conflicts that must be resolved before it can be |
Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Hanlin Bi <hanlinb@nvidia.com>
|
@vadiklyutiy Hi, sorry for the confusion, much appreciated the reviews! All comments are now addressed. The e2e validation accuracy run is updated in the Validation section in PR description. |
|
please resolve merge conflicts |
vadiklyutiy
left a comment
There was a problem hiding this comment.
LGTM. Thanks for contribution!
Thanks a lot for the reviews and help! |
|
✅ @wolfcomos, CI is now available for this PR.
|
Preserve the PDL changes at csrc/moe/topk_softmax_kernels.cu after the upstream source move. Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Hanlin Bi <hanlinb@nvidia.com>
|
/ci run |
|
✅ Triggered Buildkite CI #94960 for commit |
|
/ci run |
|
✅ Triggered Buildkite CI #94978 for commit |
|
/ci run |
|
✅ Triggered Buildkite CI #95272 for commit |
|
Hi @wolfcomos, the pre-commit checks have failed. Please run: uv pip install pre-commit>=4.5.1
pre-commit install
pre-commit run --all-filesThen, commit the changes and push to your branch. For future commits, |
Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Hanlin Bi <hanlinb@nvidia.com>
|
Hello, merge conflict is resolved, can you help me merge this PR. Thanks @vadiklyutiy . |
|
/ci run |
|
✅ Triggered Buildkite CI #95477 for commit |
|
✅ Triggered Buildkite CI #95680 for commit |
|
/ci retry |
|
✅ Triggered Buildkite CI #95949 for commit |
Signed-off-by: Hanlin Bi <hanlinb@nvidia.com> Co-authored-by: OpenAI Codex <noreply@openai.com>
Overview
The FP32 router GEMM supports programmatic dependent launch (PDL), but fused MoE

topkGatinguses an ordinary launch. Enable PDL for the consumer on SM90+ with CUDA 12+, allowing it to start early and wait before reading producer-dependent data.Claims
Validation
End-to-end accuracy (
713192bab): Full GSM8K (1,319 questions, 5-shot, temperature 0, concurrency 8), MiniMax-M3 NVFP4, TP8 on the same 8x GB200 GPUs, with real EAGLE3 verification and three draft tokens. Each variant ran twice without restarting its server.Mean change is -0.152 percentage points; baseline repeats differ by 0.531 points. These two repeats per variant do not establish accuracy equivalence. All evaluation requests succeeded. Baseline uses official vLLM v0.29.0; the candidate overlays the pinned PR kernel in the same image, rather than a full PR checkout build.
Serving: MiniMax-M3 NVFP4, 8x GB200 on two four-GPU nodes, TP8 with expert parallelism disabled, one aggregated worker, FP8 KV/indexer cache, FlashInfer/TRTLLM attention, no prefix caching or speculative decoding. Direct
vllm serve/vllm bench serveuses the same physical GPUs for A/B, three valid pairs per workload, and 64 measured requests per variant per pair.Negative latency changes are better. Changes are computed within each pair and then averaged. For 128/1024 C1, mean TPOT is 3.874 → 3.851 ms; individual paired changes range from -0.82% to -0.48%. These finite bursts and three repeats do not establish statistical significance or sustained-load capacity.
Kernel chain: M=4, H=6144, E=128, top-4 sigmoid; three same-GPU A/B pairs. Hot-weight latency is 5.330 → 4.844 us. Rotating weights use 64 distinct 3 MiB matrices; paired changes range from -8.28% to -6.51%. Each repetition ends with a non-PDL serial boundary to prevent overlap into the next repetition and premature logits-buffer reuse. Its approximately 0.682 us cost is included equally. Latencies are medians across rounds; savings are medians of paired differences. Isolated gating with that boundary saves 0.076 us (-2.16%).
Correctness and integration:
Runtime pins, commands and measurement controls
The serving, kernel-chain and correctness/integration results above use vLLM
9ea8f3ffc354901b740f0b31988900897b7221d7, PyTorch 2.13.0+cu130 and CUDA 13.0. Those measurements used the PR CUDA file on based2125ea681784c17251c47939f5ed6d1c67384f8, before the later guard simplifications. Both controls load identically recompiled original/patched translation units, with library hashes verified on every TP rank. This is not a full current-main rebuild.The upstream tests were copied unchanged from the PR base into that pinned runtime. Equivalent in-checkout commands:
Example client command; sweep the listed length pairs and C=1/4/16/32:
Server limits: model length 16384, batched tokens 16384, sequences 32, CUDA Graph capture limit 64, block size 128 and GPU memory utilization 0.9. FlashInfer autotuning and
float32_matmul_precision=highare enabled. Each variant starts fresh workers and autotuning. Paired variants use the same seed and workload order; the main sequence is A/B, B/A, A/B.Round 0 used eight warmups and exposed attention JIT during measured 8192/1024 C32 requests. That whole pair is excluded. Later pairs use
max(8, 2*C)warmups; a dedicated same-GPU A/B with verbose JIT monitoring replaces the excluded pair. Neither replacement measurement has observed measured-window JIT. Raw excluded results are retained; each workload has three valid pairs.Capture, JIT/warmup, correctness checks and diagnostic traces are outside timing. Request-level P99 has only 64 samples per run and is descriptive. Eager host-wall results are retained separately from graph GPU timings. The microbench and overlay harnesses are external to this 30-line CUDA diff.
Details
The dependency wait and completion signal precede dependent reads and row-dependent exits. CUDA launches set the PDL attribute without a host architecture query, matching
topk_softplus_sqrtandper_token_group_quant, and checkcudaLaunchKernelExerrors. Device-side PDL instructions remain guarded by__CUDA_ARCH__ >= 900. Routing math, launch geometry, output layout and the operator API are unchanged. ROCm and the unfused fallback retain their existing paths. Hopper, ROCm and a full current-main build remain unvalidated.For the host-launch cleanup in
09647c0364,git diff --checkand.venv/bin/pre-commit run --files csrc/libtorch_stable/moe/topk_softmax_kernels.cupassed. GPU tests were not rerun for this cleanup; the accuracy results above remain pinned to713192bab.OpenAI Codex assisted with implementation, validation and this description. The submitting author has reviewed the change and approved this draft submission with the validation scope and limitations documented above.
Pull Request Checklist
I used vLLM's
/pr-checklistskill. (Mandatory for agents, optional for humans).AI assistance was used during the creation of this PR.
Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.
Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.
Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.
Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.