Repository navigation
Conversation
With the FlashInfer Mamba SSU backend and Mamba cache stochastic rounding, every Mamba-2 layer launches torch.randint(0, 2**32, (1,)) for its seed right before the SSU kernel: a small kernel on the critical path of every Mamba layer (~40 per forward on Nemotron-H). Add an opt-in path (VLLM_MAMBA_SR_SEED_PREFETCH=1, default off): the first SSU call of a forward pass forks a dedicated side stream (event record / wait) and issues the same N randint calls there (N = number of Mamba-2 layers in the KV cache config), recording an event after each. The k-th SSU call waits on event k and uses seed k. The generator is advanced on the host in the same order as stock, so every seed has the stock value. Ordering is by CUDA events only (CUDA-graph-capture safe, race-free by construction). Forward passes are told apart by their ForwardContext; calls beyond N in one forward, calls outside a forward context and DBO micro-batches draw inline as stock. Disabled with ReplaySSM and for models with Mamba-1 layers. Add GPU identity tests (eager and CUDA graph replay, 40 layers). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Opt-in (
VLLM_MAMBA_SR_SEED_PREFETCH=1): with the FlashInfer Mamba SSU backend and Mamba cache stochastic rounding, draw a forward pass's per-layer stochastic-rounding seeds up front on a side CUDA stream; each SSU call waits on an event for its seed. Seed values are identical to stock.One of five independent opt-in Nemotron-H / MTP decode changes (#1–#5 in this fork).
Claims
--enable-mamba-cache-stochastic-rounding.Validation
GPU validation of this source port (4x B200, vLLM v0.30.0 image with the branch files overlaid):
python -m pytest tests/kernels/mamba/test_sr_seed_prefetch.py -v, 1x B200: 4 passed — eager (with and without extra calls beyond N), CUDA-graph capture + 3 replays (identical to stock, fresh per replay), fallback outside a forward context.Prefetching Mamba stochastic-rounding seeds for 40 layers per forward on a side stream.(40 = the model's Mamba-2 layers).End-to-end, #1–#5 combined (all five env vars, plus the drafter flag
--speculative_config.moe_backend flashinfer_trtllm, a CLI flag that is not part of these PRs) vs. stock, same node and image, fresh server per arm, 2 back-to-back pairs. 4x B200, TP4, Nemotron-H NVFP4 with MTP (7 draft tokens), FP8 KV cache; aiperf BS1 streaming chat, 10 requests with ~10k-token prompts, temperature 1, top_p 0.95:Absolute numbers omitted. Acceptance length at temperature 1 varies by a few percent between runs, and tokens/s/user scales with it. Model eval was not run for these fork drafts.
Server command (both arms)
vllm serve <Nemotron-H NVFP4 checkpoint with MTP head> --tensor-parallel-size 4 --language-model-only --speculative_config.method mtp --speculative_config.num_speculative_tokens 7 --kv-cache-dtype fp8 --mamba-backend flashinfer --mamba-ssm-cache-dtype float16 --enable-mamba-cache-stochastic-rounding --mamba-cache-philox-rounds 5 --mamba-cache-mode align --enable-prefix-caching --async-scheduling --max-model-len 262144 --max-num-batched-tokens 10240Details
Stock
FlashInferSSUBackend.__call__launchestorch.randint(0, 2**32, (1,))before every SSU kernel. That is a non-PDL kernel of about 2.5 us between conv1d and the SSU kernel, on the critical path of every Mamba layer. With about 40 Mamba-2 layers this adds up to roughly 100 us per decode step.Limitations:
Open questions for review:
ForwardContextidentity; an alternative is an explicit per-forward reset hook from the model runner.Duplicate check: searched open upstream PRs (
gh pr list --repo vllm-project/vllm --state open --search ...) for "stochastic rounding seed" (SSM-cache / ReplaySSM work (vllm-project#52962, vllm-project#40012, vllm-project#54993, ...), none moves the seed draw); "mamba stochastic rounding" (same set, none related); "ssu seed prefetch" (no results). No open PR implements this change.AI assistance: Claude Code was used to port the plugin, write the tests, run the GPU validation and draft this description. A human must review every changed line before anything goes upstream.
Design, race-freedom argument, gating, plugin-level evidence (from the original description)
Design
StochasticRoundingSeedPrefetcher(inssu_dispatch.py), N = number of Mamba-2 layers in the KV cache config._fork_eventon the current stream and makes a dedicated side stream wait on it. It then issues the same Ntorch.randint(0, 2**32, (1,), device=...)calls (same shape, dtype, device and order) on the side stream, recording_events[k]after the k-th._events[k]and passes seed k to the unchanged FlashInfer SSU kernel.ForwardContext(held through a weakref). This is robust where a plain call counter could drift. The prefetcher returnsNone, and the caller draws inline exactly as stock, for:initialize_mamba_ssu_backendattaches the prefetcher to the FlashInfer backend only when all of these hold:FlashInferSSUBackend.__call__only changes whererand_seedcomes from.Why it is race-free
_events[k]is recorded on the side stream after seed k is written. The current stream waits on it before enqueuing the SSU kernel that reads seed k.record_streamwould):_fork_event. The current stream records that event after every consumer of the previous seeds was enqueued.randintcall, in call order. No other generator user runs between the Mamba layers of a forward. So the k-th pre-drawn seed equals the stock k-th draw, eagerly and under graph replay. Extra calls beyond N draw inline after the N pre-drawn seeds, which is again the stock order.Gating
VLLM_MAMBA_SR_SEED_PREFETCH(bool, default0) enables the prefetch. It is a normalvllm/envs.pyentry and part of the compile cache key.--enable-mamba-cache-stochastic-rounding.Nonecheck.Plugin-level correctness evidence
Identity test on 1x B200, 40 layers, other work interleaved on the main stream between uses. The pre-drawn seeds equal stock's per-layer draws eagerly and over 3 CUDA graph replays, and the seeds differ across replays as in stock. All checks passed. This PR ports that test:
tests/kernels/mamba/test_sr_seed_prefetch.py(eager, eager with extra calls beyond N, CUDA graph replay, fallback outside a forward context).Plugin-level performance
Model: Nemotron-H (hybrid Mamba-2 / latent-MoE, NVFP4) with MTP, TP4 on 4x B200, vLLM v0.30.0, FlashInfer Mamba backend, fp16 SSM cache with stochastic rounding, prefix caching, async scheduling. Metric: median ITL, i.e. time per decode step, or per verify iteration with MTP. This metric does not depend on acceptance.
For comparison, the router-gate overlap alone measured -4.5 / -4.7 / -3.5 / -1.4 % per MTP verify iteration in a separate run at temperature 0. A BS1 streaming chat benchmark with both items (1 rep, temperature 1) gave +4.9 % and +8.7 % TPS/user p50 on two prompt sets. No isolated measurement of this item with MTP was taken.
Port notes
Deviations from the plugin:
MambaMixer2modules of the target model; both are 40 for this model.ForwardContextidentity instead of a modular call counter, with a stock fallback for extra calls, calls outside a context and DBO.Seed values and stream/event structure are unchanged in the validated configuration.
🤖 Generated with Claude Code
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. (See open questions.)
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. (Pending human review; full pre-commit / mypy not run.)
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.
🤖 Generated with Claude Code