flashinfer.sparse¶
Kernels for block sparse flashattention.
- class flashinfer.sparse.BlockSparseAttentionWrapper(float_workspace_buffer: Tensor, backend: str = 'auto')¶
Wrapper class for attention computation with a block-sparse matrix as attention mask. The definition of block sparse matrix can be found at bsr_matrix in SciPy.
This API supports any block size
(R, C).Example
>>> import torch >>> import flashinfer >>> num_qo_heads = 32 >>> num_kv_heads = 8 >>> head_dim = 128 >>> # allocate 128MB workspace buffer >>> workspace_buffer = torch.empty(128 * 1024 * 1024, dtype=torch.uint8, device="cuda:0") >>> bsr_wrapper = flashinfer.BlockSparseAttentionWrapper(workspace_buffer) >>> # sparse mask: [[0, 0, 1], [1, 0, 1], [0, 1, 1]] >>> M = 3 >>> N = 3 >>> indptr = torch.tensor([0, 1, 3, 5], dtype=torch.int32, device="cuda:0") >>> indices = torch.tensor([2, 0, 2, 1, 2], dtype=torch.int32, device="cuda:0") >>> bsr_wrapper.plan( ... indptr, ... indices, ... M, ... N, ... 1, # R(block_rows)=1 ... 1, # C(block_columns)=1 ... num_qo_heads, ... num_kv_heads, ... head_dim, ... ) >>> q = torch.randn((M, num_qo_heads, head_dim), dtype=torch.float16, device="cuda:0") >>> k = torch.randn((N, num_kv_heads, head_dim), dtype=torch.float16, device="cuda:0") >>> v = torch.randn((N, num_kv_heads, head_dim), dtype=torch.float16, device="cuda:0") >>> o = bsr_wrapper.run(q, k, v) >>> # use dense implementation with attention mask for comparison >>> mask = torch.tensor([[0, 0, 1], [1, 0, 1], [0, 1, 1]], dtype=torch.bool, device="cuda:0") >>> o_ref = flashinfer.single_prefill_with_kv_cache(q, k, v, custom_mask=mask) >>> torch.allclose(o, o_ref) True
- __init__(float_workspace_buffer: Tensor, backend: str = 'auto') None¶
Constructs of
BlockSparseAttentionWrapper.- Parameters:
float_workspace_buffer (torch.Tensor) – The user reserved float workspace buffer used to store intermediate attention results in the split-k algorithm. The recommended size is 128MB, the device of the workspace buffer should be the same as the device of the input tensors.
backend (str) – The implementation backend, could be
auto/fa2/fa3orcake. Defaults toauto. If set toauto, the function will automatically choose the backend based on the device architecture and kernel availability.
- plan(indptr: Tensor | None, indices: Tensor | None, M: int, N: int, R: int, C: int, num_qo_heads: int, num_kv_heads: int, head_dim: int, mask: Tensor | None = None, packed_mask: Tensor | None = None, causal: bool = False, pos_encoding_mode: str = 'NONE', use_fp16_qk_reduction: bool = False, logits_soft_cap: float | None = None, sm_scale: float | None = None, rope_scale: float | None = None, rope_theta: float | None = None, q_data_type: str | dtype = 'float16', kv_data_type: str | dtype | None = None, o_data_type: str | dtype = 'float16', non_blocking: bool = True, block_mask: Tensor | None = None, kv_block_lens: Tensor | None = None, q2k_indices: Tensor | None = None, q2k_num: Tensor | None = None, kv_splits: int | str | None = None, use_clc: bool | None = None, q_scale: Tensor | None = None, k_scale: Tensor | None = None, v_scale: Tensor | None = None) None¶
Create auxiliary data structures for block sparse attention.
- Parameters:
indptr (torch.Tensor, optional) – The block index pointer of the block-sparse matrix on row dimension, shape
(MB + 1,), whereMBis the number of blocks in the row dimension. Required for all backends exceptcake,vsa_sm100_blk128,vsa_sm100_blk64, andvsa_sm120_blk64whenblock_maskis provided.indices (torch.Tensor, optional) – The block indices of the block-sparse matrix on column dimension, shape
(nnz,), wherennzis the number of non-zero blocks. The elements inindicesarray should be less thenNB: the number of blocks in the column dimension. Required for all backends exceptcake,vsa_sm100_blk128,vsa_sm100_blk64, andvsa_sm120_blk64whenblock_maskis provided.M (int) – The number of rows of the block-sparse matrix,
MB = ceil_div(M, R).N (int) – The number of columns of the block-sparse matrix,
NB = N // C,Nshould be divisible byC.R (int) – The number of rows in each block.
C (int) – The number of columns in each block.
num_qo_heads (int) – The number of heads in the query/output tensor.
num_kv_heads (int) – The number of heads in the key/value tensor.
head_dim (int) – The dimension of each head.
mask (torch.Tensor, optional) – The mask tensor with shape
(nnz, R, C,), where nnz is the number of non-zero blocks. If every block is full, then we don’t need to provide the mask tensor.packed_mask (torch.Tensor, optional) – The 1D packed mask tensor, if provided, the
custom_maskwill be ignored. The packed mask tensor is generated byflashinfer.quantization.packbits().causal (bool) – Whether to apply causal mask to the attention matrix. This is only effective when
custom_maskis not provided inplan().pos_encoding_mode (str, optional) – The position encoding applied inside attention kernels, could be
NONE/ROPE_LLAMA(LLAMA style rotary embedding) /ALIBI. Default isNONE.use_fp16_qk_reduction (bool) – Whether to use f16 for qk reduction (faster at the cost of slight precision loss).
logits_soft_cap (Optional[float]) – The attention logits soft capping value (used in Gemini, Grok and Gemma-2, etc.), if not provided, will be set to
0. If greater than 0, the logits will be capped according to formula: \(\texttt{logits_soft_cap} \times \mathrm{tanh}(x / \texttt{logits_soft_cap})\), where \(x\) is the input logits.sm_scale (Optional[float]) – The scale used in softmax, if not provided, will be set to
1.0 / sqrt(head_dim).rope_scale (Optional[float]) – The scale used in RoPE interpolation, if not provided, will be set to
1.0.rope_theta (Optional[float]) – The theta used in RoPE, if not provided, will be set to
1e4.q_data_type (str, optional) – The data type of the query tensor.
kv_data_type (Optional[Union[str, torch.dtype]]) – The data type of the key/value tensor. If None, will be set to
q_data_type.o_data_type (str, optional) – The data type of the output tensor. Default is
half. As output dtype cannot be inferred by input dtype in quantizationnon_blocking (bool) – Whether to copy the input tensors to the device asynchronously, defaults to
True.block_mask (torch.Tensor, optional) – Per-head block-level attention mask, dtype bool. Shape may be either
(num_qo_heads, MB, NB)or(num_kv_heads, MB, NB).block_mask[h, i, j] = Truemeans the Q-blockiattends to KV-blockjfor headh. For GQA (num_qo_heads > num_kv_heads), when providing(num_qo_heads, MB, NB), the first QO-head from each KV-head group is used (sparsity must be the same across QO-heads that share a KV-head). Supported by thecake,vsa_sm100_blk128,vsa_sm100_blk64, andvsa_sm120_blk64backends. When provided,indptr/indicesare not required and will be ignored.kv_block_lens (torch.Tensor, optional) – Number of valid tokens in every KV block, shape
(NB,). Entries must be in[1, C]. Supported by thecakeblock-64 route; when omitted, every block is treated as havingCvalid tokens.q2k_indices (torch.Tensor, optional) – Direct per-head KV-block selections, contiguous int32 with shape
(num_qo_heads, MB, topk). Supported by thecakeblock-64 route and mutually exclusive withblock_maskand BSR metadata.q2k_num (torch.Tensor, optional) – Number of valid entries in each direct selection row, contiguous int32 with shape
(num_qo_heads, MB). When omitted, every direct row uses the fulltopkdimension.kv_splits (Optional[Union[int, str]]) – Number of KV splits for the split-KV combine path, or
"auto"to pick a split count from the sparsity heuristics. Only supported for thevsa_sm100_blk64backend; must beNonefor all other backends.None(default) disables splitting, equivalent to passing1explicitly. Pass"auto"to select the split count automatically via a sparsity heuristic.use_clc (Optional[bool]) – Override the SM100 blk64 scheduler:
Trueforces the CLC persistent scheduler,Falseforces the static scheduler,None(default) uses the shape-based heuristic. Only supported for thevsa_sm100_blk64backend.q_scale (torch.Tensor, optional) – Sage FP8 quantization scale for
q, shape(1, num_qo_heads, seqlen_q), float32. Only supported for thevsa_sm100_blk64backend, and only whenq/k/varefloat8_e4m3fn. Must be provided together withk_scale/v_scale, or not at all. The Sage FP8 path additionally requiresbatch_size == 1,num_qo_heads in (4, 8), and dense (non-variable) block sparsity – seebsa_attn_sm100_blk64_fwd().k_scale (torch.Tensor, optional) – Sage FP8 quantization scale for
k, shape(1, num_qo_heads, ceil(seqlen_k / 16)), float32. Seeq_scale.v_scale (torch.Tensor, optional) – Sage FP8 quantization scale for
v, shape(num_qo_heads, head_dim), float32. Seeq_scale.
:param The
plan()method should be called before anyrun()or: :paramrun_return_lse()calls: :param auxiliary data structures will be created: :param during this call and cached for multiple kernel runs.: :param Thenum_qo_headsmust be a multiple ofnum_kv_heads. Ifnum_qo_heads: :param is not equal tonum_kv_heads: :param the function will use: :param grouped query attention.: :param .. note::: Thevsa_sm100_blk64backend does not support GQA/MQA: it has noKV-head mapping and requires
num_kv_heads == num_qo_heads.
- reset_workspace_buffer(float_workspace_buffer: Tensor, int_workspace_buffer: Tensor) None¶
Reset the workspace buffer.
- Parameters:
float_workspace_buffer (torch.Tensor) – The new float workspace buffer, the device of the new float workspace buffer should be the same as the device of the input tensors.
int_workspace_buffer (torch.Tensor) – The new int workspace buffer, the device of the new int workspace buffer should be the same as the device of the input tensors.
- run(q: Tensor, k: Tensor, v: Tensor, scale_q: Tensor | None = None, scale_k: Tensor | None = None, scale_v: Tensor | None = None, out: Tensor | None = None, lse: Tensor | None = None, return_lse: bool = False, enable_pdl: bool | None = None) Tensor | Tuple[Tensor, Tensor]¶
Compute block-sparse attention between Q/K/V tensors.
- Parameters:
q (torch.Tensor) – The query tensor with shape
(M, num_qo_heads, head_dim).k (torch.Tensor) – The key tensor with shape
(N, num_kv_heads, head_dim).v (torch.Tensor) – The value tensor with shape
(N, num_kv_heads, head_dim).scale_q (Optional[torch.Tensor]) – The scale tensor for query, per-head quantization with shape:
[num_qo_heads]. Used with FP8 Quantization. If not provided, will be set to1.0.scale_k (Optional[torch.Tensor]) – The scale tensor for key, per-head quantization with shape:
[num_kv_heads]. Used with FP8 Quantization. If not provided, will be set to1.0.scale_v (Optional[torch.Tensor]) – The scale tensor for value, per-head quantization with shape:
[num_kv_heads]. Used with FP8 Quantization. If not provided, will be set to1.0.out (Optional[torch.Tensor]) – The output tensor, if not provided, will be allocated internally.
lse (Optional[torch.Tensor]) – The log-sum-exp of attention logits, if not provided, will be allocated internally.
return_lse (bool) – Whether to return the log-sum-exp of attention logits
enable_pdl (bool) – Whether to enable Programmatic Dependent Launch (PDL). See https://docs.nvidia.com/cuda/cuda-c-programming-guide/#programmatic-dependent-launch-and-synchronization Only supported for >= sm90, and currently only for FA2 and CUDA core decode.
- Returns:
If
return_lseisFalse, the attention output, shape:[M, num_qo_heads, head_dim]. Ifreturn_lseisTrue, a tuple of two tensors:The attention output, shape:
[M, num_qo_heads, head_dim].The logsumexp of attention output, shape:
[M, num_qo_heads].
- Return type:
Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]
- class flashinfer.sparse.VariableBlockSparseAttentionWrapper(float_workspace_buffer: Tensor, backend: str = 'auto')¶
Wrapper class for attention computation with a block-sparse matrix as attention mask. This API supports variable block sizes provided by
block_row_szandblock_col_sz. Besides, eachkv_head_idxcan specify its own sparse patterns without using the same mask.Example
>>> import torch >>> import flashinfer >>> num_qo_heads = 1 >>> num_kv_heads = 1 >>> head_dim = 128 >>> seq_len = 6 # This corresponds to the `block_row_sz` and `block_col_sz` >>> # allocate 128MB workspace buffer >>> workspace_buffer = torch.empty(128 * 1024 * 1024, dtype=torch.uint8, device="cuda:0") >>> wrapper = flashinfer.VariableBlockSparseAttentionWrapper(workspace_buffer) >>> block_mask_map = torch.tensor([[[0, 0, 1], [1, 0, 1], [0, 1, 1]]], dtype=torch.bool, device="cuda:0") >>> block_row_sz = torch.tensor([[1, 2, 3]], dtype=torch.int32, device="cuda:0") >>> block_col_sz = torch.tensor([[3, 1, 2]], dtype=torch.int32, device="cuda:0") >>> wrapper.plan( ... block_mask_map, ... block_row_sz, ... block_col_sz, ... num_qo_heads, ... num_kv_heads, ... head_dim, ... ) >>> q = torch.randn((num_qo_heads, seq_len, head_dim), dtype=torch.float16, device="cuda:0") >>> k = torch.randn((num_kv_heads, seq_len, head_dim), dtype=torch.float16, device="cuda:0") >>> v = torch.randn((num_kv_heads, seq_len, head_dim), dtype=torch.float16, device="cuda:0") >>> o = wrapper.run(q, k, v)
- __init__(float_workspace_buffer: Tensor, backend: str = 'auto') None¶
Constructs of
VariableBlockSparseAttentionWrapper.- Parameters:
float_workspace_buffer (torch.Tensor) – The user reserved float workspace buffer used to store intermediate attention results in the split-k algorithm. The recommended size is 128MB, the device of the workspace buffer should be the same as the device of the input tensors.
backend (str) – The implementation backend, could be
auto/fa2orfa3. Defaults toauto. If set toauto, the function will automatically choose the backend based on the device architecture and kernel availability.
- plan(block_mask_map: Tensor, block_row_sz: Tensor, block_col_sz: Tensor, num_qo_heads: int, num_kv_heads: int, head_dim: int, causal: bool = False, pos_encoding_mode: str = 'NONE', use_fp16_qk_reduction: bool = False, logits_soft_cap: float | None = None, sm_scale: float | None = None, rope_scale: float | None = None, rope_theta: float | None = None, non_blocking: bool = True, q_data_type: str | dtype = 'float16', kv_data_type: str | dtype | None = None) None¶
Create auxiliary data structures for block sparse attention.
- Parameters:
block_mask_map (torch.Tensor) – The block mask map (boolean), shape
(num_kv_heads, MB, NB), whereMBis the number of blocks in the row dimension,NBis the number of blocks in the column dimension.block_row_sz (torch.Tensor) – The block row size, shape
(num_kv_heads, MB,).block_col_sz (torch.Tensor) – The block column size, shape
(num_kv_heads, NB,).num_qo_heads (int) – The number of heads in the query/output tensor.
num_kv_heads (int) – The number of heads in the key/value tensor. Note that a group of
qo_headsshares the same sparse pattern ofkv_heads.head_dim (int) – The dimension of each head.
causal (bool) – Whether to apply causal mask to the attention matrix.
pos_encoding_mode (str, optional) – The position encoding applied inside attention kernels, could be
NONE/ROPE_LLAMA(LLAMA style rotary embedding) /ALIBI. Default isNONE.use_fp16_qk_reduction (bool) – Whether to use f16 for qk reduction (faster at the cost of slight precision loss).
logits_soft_cap (Optional[float]) – The attention logits soft capping value (used in Gemini, Grok and Gemma-2, etc.), if not provided, will be set to
0. If greater than 0, the logits will be capped according to formula: \(\texttt{logits_soft_cap} \times \mathrm{tanh}(x / \texttt{logits_soft_cap})\), where \(x\) is the input logits.sm_scale (Optional[float]) – The scale used in softmax, if not provided, will be set to
1.0 / sqrt(head_dim).rope_scale (Optional[float]) – The scale used in RoPE interpolation, if not provided, will be set to
1.0.rope_theta (Optional[float]) – The theta used in RoPE, if not provided, will be set to
1e4.non_blocking (bool) – Whether to copy the input tensors to the device asynchronously, defaults to
True.q_data_type (Union[str, torch.dtype]) – Dtype of the query tensor. Used to specialize the JIT-compiled kernel. Defaults to
"float16".kv_data_type (Optional[Union[str, torch.dtype]]) – Dtype of the key/value tensors. When
None, defaults toq_data_type.
The
plan()method should be called before anyrun()orrun_return_lse()calls, auxiliary data structures will be created during this call and cached for multiple kernel runs.The
num_qo_headsmust be a multiple ofnum_kv_heads. Ifnum_qo_headsis not equal tonum_kv_heads, the function will use grouped query attention.
- reset_workspace_buffer(float_workspace_buffer: Tensor, int_workspace_buffer: Tensor) None¶
Reset the workspace buffer.
- Parameters:
float_workspace_buffer (torch.Tensor) – The new float workspace buffer, the device of the new float workspace buffer should be the same as the device of the input tensors.
int_workspace_buffer (torch.Tensor) – The new int workspace buffer, the device of the new int workspace buffer should be the same as the device of the input tensors.
- run(q: Tensor, k: Tensor, v: Tensor, out: Tensor | None = None, lse: Tensor | None = None, return_lse: bool = False, enable_pdl: bool | None = None) Tensor | Tuple[Tensor, Tensor]¶
Compute block-sparse attention between Q/K/V tensors.
- Parameters:
q (torch.Tensor) – The query tensor with shape
(num_qo_heads, qo_len, head_dim).k (torch.Tensor) – The key tensor with shape
(num_kv_heads, kv_len, head_dim).v (torch.Tensor) – The value tensor with shape
(num_kv_heads, kv_len, head_dim).out (Optional[torch.Tensor]) – The output tensor, if not provided, will be allocated internally.
lse (Optional[torch.Tensor]) – The log-sum-exp of attention logits, if not provided, will be allocated internally.
return_lse (bool) – Whether to return the log-sum-exp of attention logits
enable_pdl (bool) – Whether to enable Programmatic Dependent Launch (PDL). See https://docs.nvidia.com/cuda/cuda-c-programming-guide/#programmatic-dependent-launch-and-synchronization Only supported for >= sm90, and currently only for FA2 and CUDA core decode.
- Returns:
If
return_lseisFalse, the attention output, shape:[M, num_qo_heads, head_dim]. Ifreturn_lseisTrue, a tuple of two tensors:The attention output, shape:
[M, num_qo_heads, head_dim].The logsumexp of attention output, shape:
[M, num_qo_heads].
- Return type:
Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]
Cake VSA¶
|
Create stable metadata and workspaces for the source-level backend. |
|
Run one explicit source-level route; no external fallback is available. |
flashinfer.msa_ops¶
Minimax Sparse Attention (MSA) sparse prefill, sparse decode, and top-k
selection dispatch on compute capability 10.0/10.3 (SM100/SM103) and
SM120/SM121 Blackwell GPUs. The proxy-score operations remain SM120/SM121
only. NVFP4 K/V and views split from a packed paged K/V cache are also
SM120/SM121-only; the compute capability 10.0/10.3 attention backend requires
separate contiguous K and V tensors and does not make implicit copies.
The compute capability 10.0/10.3 backend uses TopK16 as its generic contract
and additionally retains four shape-exact routes: paged BF16 decode at
B64/Q8/KV65536/TopK32, 512-thread paged BF16 decode at
B2/Q1/KV257/TopK4, flat
BF16-query/FP8-KV prefill at B3/Q1024/KV8192/TopK8, and paged BF16 prefill at
B3/Q4096/KV8192/TopK4. Neighboring non-TopK16 shapes fail closed instead of
entering a generic kernel. The decode path uses direct persistent M16
ownership for both Q1 and multi-token decode; it does not route BF16 decode
through prefill or split-K.
Frozen BF16-query/FP8-KV Q1 serving shapes use exact or transformed direct
kernels, while paged uniform FP8 Q/K/V supports Q1 through Q32 and returns
BF16 output. Long batch-one BF16 causal prefill uses a selected-block reverse
producer and deterministic reduction once the query reaches 8192 tokens.
Call flashinfer.msa_ops.supports_packed_kv() with the active device when
integrating a cache manager across these architectures; the legacy aggregate
SUPPORTS_PACKED_KV flag describes the SM120/SM121 backend.
Per-token tensor num_valid_pages for
flashinfer.msa_ops.msa_topk_select() is likewise SM120/SM121-only;
compute capability 10.0/10.3 requires a scalar value or None and rejects
the tensor form before backend dispatch.
CUDA graph capture of sparse prefill or decode on compute capability 10.0/10.3
requires a caller-owned
flashinfer.msa_ops.MSASparseAttentionWorkspace. Warm the workspace
eagerly with the exact tensors, options, and capture stream before capture.
The exact decode overrides are eager-only. The exact TopK8 reverse-prefill
route is also eager-only because its reducer uses a host-owned monotonic launch
generation. The exact paged TopK4 route normally captures its producer and
reducer into an internal two-node CUDA graph; while an outer CUDA graph is
being captured it emits the two kernel nodes directly.
Normal callers should leave the Blackwell schedule environment variables
unset. For advanced diagnostics and benchmarking,
FLASHINFER_MSA_PREFILL_SCHEDULE=m64 forces the eligible M64 prefill
schedule. FLASHINFER_MSA_FP8_Q1_SCHEDULE can select
batch_attention, q1_exact, q1_flat_xform2,
q1_paged_xform2, or paged_uniform_fp8 for an eligible FP8 Q1 route.
Unsupported values, or a schedule incompatible with the input layout and
dtypes, raise ValueError.
|
MSA dense proxy pass for SM120/SM121: per-KV-block max attention logits. |
|
NVFP4 MSA dense proxy pass for SM120/SM121 (the FP4 counterpart of |
|
Caller-owned storage for SM100/SM103 MSA CUDA graph capture. |
|
Return whether MSA accepts packed paged K/V views on |
|
Minimax Sparse Attention forward for SM100/SM103 and SM120/SM121 GPUs. |
|
Sparse decode attention for SM100/SM103 and SM120/SM121 GPUs. |
|
Select the top-K KV blocks per query token based on attention scores. |