mstar.engine.resources.attn.flashinfer_mla#
Multi-head Latent Attention through FlashInfer’s BatchMLAPagedAttentionWrapper.
The cache (KVLayout.MLA) holds one [ckv | kpe] latent per token; the layer writes
it through the KV resource and attends with the absorbed query
(q_nope @ W_UK -> kv_lora_rank wide, plus the un-rotated q_pe). The kernel’s
output is in the latent space ([tokens, heads, kv_lora_rank]); the layer applies
W_UV. One wrapper class serves prefill and decode (query lengths come from
qo_indptr), so the slot/label bookkeeping is the same as FlashInferManager’s.
Functions
|
FlashInfer's Hopper MLA kernel is specialised for the DeepSeek/Kimi latent shape ( |
Classes
|
|
|
Thin wrapper over |
- class mstar.engine.resources.attn.flashinfer_mla.FlashInferMLAManager(kv_cache, device, dtype, kv_config, backend='auto', sm_scale=None)[source]#
Bases:
AttentionManager- Parameters:
kv_cache (str)
device (torch.device)
dtype (torch.dtype)
kv_config (KVConfig)
backend (str)
sm_scale (float | None)
- property force_double_buffer#
Whether this resource needs double-buffering even off the pre-plan path.
A resource that stages a step’s layout into a reused host buffer and issues a non-blocking H2D into a graph-read device buffer has a race the moment the CPU runs ahead of the GPU: plan(N+1) can overwrite the buffer before step N’s DMA has retired, and the replay attends with N+1’s data. The buffer need not be ours — FlashInfer’s
planholds one per wrapper, which is why the attention managers key theirs per slot. The main runner already double-buffers whenever a resourcesupports_preplan; this flag extends that to a runner that has no pre-plan path but still replays such a resource — notably the piecewise runner — and makes_exec_per_requestfence before it reuses a slot, since its sub-steps all run inside one step. Off by default; a resource opts in only if it has this hazard.
- kv_len_buf(label='main')[source]#
The rows’ planned kv lengths, int32 on device (static under a lease): for a
context_onlyplan the length of each row’s stored context, which is where the row’s queries (and the entries the step appends) start.
- plan(step, ctx)[source]#
ret is immutable and opaque to runner; only gives to ctx.plan_results
- Parameters:
step (AttentionStep)
ctx (StepContext)
- run(q, label=None, kv_cache_layer=None, k=None, v=None, layer_idx=None, q_pe=None, return_lse=False)[source]#
qis the absorbedq_nope([T, H, kv_lora_rank]);q_pethe rope-part query ([T, H, qk_rope_head_dim]). Withreturn_lsealso the natural log-sum-exp of the scores[T, H]fp32, for merging with another key segment.
- property supports_preplan#
- class mstar.engine.resources.attn.flashinfer_mla.FlashInferMLAWrapper(workspace_buffer, num_qo_heads, kv_lora_rank, qk_rope_head_dim, page_size, sm_scale, batch_size=None, max_num_pages=None, device=torch.device('cuda'), use_cuda_graph=False, backend='auto')[source]#
Bases:
objectThin wrapper over
flashinfer.mla.BatchMLAPagedAttentionWrapper.- Parameters:
workspace_buffer (torch.Tensor) – FlashInfer float workspace.
num_qo_heads (int) – local query heads.
qk_rope_head_dim (int) – latent split (
ckv/kpewidths).page_size (int) – cache geometry.
max_num_pages (int | None) – cache geometry.
batch_size (int | None) – rows (requests) for CUDA-graph mode; fixed for the wrapper’s life.
sm_scale (float) – softmax scale of the original
qk_head_dim(e.g.192 ** -0.5).kv_lora_rank (int)
qk_rope_head_dim
device (torch.device)
use_cuda_graph (bool)
backend (str)
- plan(qo_indptr, paged_kv_indptr, paged_kv_indices, paged_kv_last_page_len, causal=True, dtype=torch.bfloat16, kv_dtype=None, **kwargs)[source]#
Inputs may be CPU tensors (the KV plan builds them on the host).
- mstar.engine.resources.attn.flashinfer_mla.flashinfer_mla_supports(kv_lora_rank, qk_rope_head_dim)[source]#
FlashInfer’s Hopper MLA kernel is specialised for the DeepSeek/Kimi latent shape (
ckv512,kpe0 or 64); other shapes are JIT-compiled but read out of bounds. Anything else runs the torch fallback (eager, not CUDA-graph safe): small test checkpoints, not production models.