Repository navigation
feat: add FlashInfer attention backend for SM120 decode - #112
yanbao1217 wants to merge 4 commits into
Conversation
Register FlashInfer (flashinfer-python >= 0.7.0, XQA kernels) as a paged decode backend through the attention contract layer: - explicit "flashinfer" selection plus an auto slot between FlashAttention-2 and Triton; the SM gate keeps auto away from it on SM8/9/10, so it is only reached where every FlashAttention generation is rejected (SM 12.x) - capabilities declare CUDA graphs and async scheduling; packed prefill stays FA4-only because the adapter leaves the kernel without a prefill entry point - validation rejects unsupported setups explicitly (float16 unvalidated on SM120, page sizes outside the compiled XQA variants, head_dim not divisible by 16); the workspace allocates lazily on first execution so backend selection performs no device allocations - empty batches return early because the kernel host-dispatch SIGFPEs on batch 0; padded block-table columns are clamped non-negative and the kernel bounds reads by seq_lens, so -1/zero/stale padding stays invisible - requires CUDA_HOME with nvcc >= 12.9 and that toolkit's lib directory on LD_LIBRARY_PATH for the just-in-time compiled modules
The run subcommand accepts --attention-backend (torch/triton/flashinfer, default triton), records it in the run metadata, and passes it through Generator to the engine instead of the hardcoded Triton selection.
Document installation and the two runtime requirements (CUDA_HOME with nvcc >= 12.9 for JIT kernels, the toolkit lib directory on LD_LIBRARY_PATH), scope and explicit rejections, backend selection guidance, and the GSM8K-87 greedy variation measured on RTX 5090.
021eca8 to
a224349
Compare
|
Matched throughput results for the FlashInfer vs Triton decode path (RTX 5090, Ouro-1.4B BF16, Protocol follows the PR #30 methodology scaled to a 32 GB device: 512-token random-token inputs, 128 output tokens, 2x concurrency requests with closed-loop replacement, three trials per condition (medians below); timing covers prefill and drain and excludes loading, warmup, and tokenization; both backends run identical feature stacks (
Notes:
🤖 Generated with Claude Code |
Document the --attention-backend flag on the native run command, the RTX 5090 Triton/FlashInfer scores on the frozen 87-question case, and the expected single-pass greedy variation between BF16 kernels.
0z5a
left a comment
There was a problem hiding this comment.
Thanks for adding FlashInfer through the existing attention backend contract and for the C1/C8/C32 measurements on RTX 5090. Reviewed 1a24e52; I have one selection concern before merging and several follow-up suggestions.
1. [P2] Restrict automatic selection to validated architectures.
auto places FlashInfer before Triton, and the constructor accepts SM90/SM100 with only a warning. A CPU selection probe using the original constructors with hardware/import boundaries mocked reproduces this on SM90: BF16, head dimension 128, page size 16, FA4/FA3 unavailable and FA2 rejecting the page size selects Triton at the base revision and FlashInfer at this head. SM100 has an analogous fallback change.
Could we gate automatic FlashInfer selection to the validated SM120 target for now, retain explicit opt-in on H100, and add fallback regression tests? The PR description's automatic-selection restriction is currently stronger than the code implements.
2. Backend capability reuse.
The kernel's self.capabilities duplicates the wrapper's _FLASHINFER_CAPABILITIES. Please use the existing backend contract as the single source of truth and exercise that contract in selection tests.
3. Metadata and workspace validation.
Please profile the per-invocation block_tables.clamp_min(0) and context_lengths.to(torch.uint32) overhead at larger batches before considering preparation once per KV batch. Preserve padding and graph-buffer update semantics if these tensors are reused.
The instance-owned 128 MiB workspace is a useful ownership choice. The runner currently serializes attention on its core stream; I have not established a workspace race. Please reuse the existing CUDA Graph test matrix for FlashInfer and cover replay, eager fallback, cancellation and request reuse to verify the workspace lifetime and ordering contract.
4. High-concurrency E2E coverage.
For follow-up validation, C64/C128 with dynamic arrivals, mixed prompt lengths and recurrence depths, cancellation/reuse, and both supported KV layouts would be useful. Please report latency percentiles, graph replay/fallback counts, KV reclamation and output/exit-depth correctness alongside output tok/s. Account for the reported BF16/GSM8K divergence explicitly; matching token counts alone does not establish generation equivalence.
I can help run the H100 side of this validation. Please ping me @0z5a if useful.
| } | ||
| _AUTO_PRIORITY = ("flash_attn_4", "flash_attn_3", "flash_attn_2", "triton", "torch") | ||
| _FLASHINFER_CAPABILITIES = BackendCapabilities(cuda_graphs=True, async_scheduling=True) | ||
| _AUTO_PRIORITY = ("flash_attn_4", "flash_attn_3", "flash_attn_2", "flashinfer", "triton", "torch") |
There was a problem hiding this comment.
[P2] Gate the automatic FlashInfer candidate to validated architectures. Putting FlashInfer before Triton changes the fallback on SM90/SM100 because its constructor accepts those architectures with only a warning. Using the pinned original selection/constructor functions with mocked hardware/import boundaries, SM90 BF16, head dimension 128 and page size 16 selects Triton at the base revision when FA4/FA3 are unavailable and FA2 rejects the page size, but selects FlashInfer here. This exceeds the stated SM120 validation scope. Please keep explicit SM90/SM100 opt-in available while restricting the auto candidate to validated targets, and add fallback tests for missing FlashAttention candidates.
|
Thanks @0z5a — acknowledged. Plan: gate the automatic candidate to SM120 while keeping explicit opt-in elsewhere, make the contract layer the single source for the capability declaration, profile the per-call clamp/cast conversions, and extend the graph-matrix coverage (replay, eager fallback, cancellation, request reuse) for FlashInfer. The C64/C128 dynamic-arrival validation sounds right as a separate follow-up; I'd gladly take you up on the H100 half once these land. |
Adds
flashinferas a selectable paged-decode attention backend (FlashInfer XQA kernels,flashinfer-python >= 0.7.0), giving RTX 50-series (SM120) a second attention path alongside Triton. FlashAttention 2/3/4 reject SM120 for paged KV, so Triton is currently the only option there. Refs #69.Rebased onto the merged attention contract layer (
2534e24+3defab4): FlashInfer registers throughvllm_rlt.attentionwith explicit selection and an auto slot between FlashAttention-2 and Triton, declaringBackendCapabilities(cuda_graphs, async_scheduling). The SM gate keeps auto away from FlashInfer on SM8/9/10, so auto only reaches it where every FlashAttention generation is rejected.Scope
Design notes
block_tablesclamped non-negative so -1/zero/stale graph-replay padding stays invisible,seq_lenscast to uint32, explicitkv_layout="NHD".Validation (RTX 5090, Ouro-1.4B BF16, block_size=16, four-loop decode)
test_scheduler_selection.pyfailures on current main:OuroConfig.tinyis missing); ruff clean.Environment requirements (docs/flashinfer.md)
pip install -e ".[flashinfer]", plus a CUDA toolkit with nvcc >= 12.9 reachable via CUDA_HOME (the kernels JIT-compile for compute_120f) and that toolkit's lib directory on LD_LIBRARY_PATH.Follow-ups
generation == 4gate sites now that capabilities are declared.xqa.pyasserts output dtype matches query), and 0.7.0.post1 → 0.7.1rc2 contains zero XQA changes, so no reduction-precision knob exists today; the 1-ulp difference is inherent to the different accumulation order. Remaining option: logit-gap forensics on the three flipped GSM8K answers.🤖 Generated with Claude Code