mstar.engine.resources.attn.flex#
Attention over a ring KV cache, through a compiled flex_attention.
The visibility of a ring cannot be expressed as a sequence length: the slots a
step may read are scattered across a fixed buffer that is overwritten in place,
so there is no prefix to pass a kernel. FlexAttention’s BlockMask names the
readable KV blocks directly, which is what makes the ring expressible at all.
The mask this builds is query-uniform and full-blocks-only — every query block sees the same KV blocks, and a visible block is wholly visible — because writes are whole frames of tokens. That is what makes “capacity must be a multiple of 128” a real constraint here rather than a convenience.
Functions
|
Build the query-uniform, full-blocks-only |
Classes
|
Attention against a ring KV cache, through |
- class mstar.engine.resources.attn.flex.FlexAttentionManager(kv_cache, device, dtype, kv_config)[source]#
Bases:
AttentionManagerAttention against a ring KV cache, through
flex_attention.Why FlexAttention and not the paged FlashInfer path that already exists here: numerical parity with the reference implementation, which runs
flex_attentionwith a full-block-onlyBlockMask. A paged kernel changes the accumulation order over the KV blocks, so a port on top of it could never be compared bit-exactly against the reference — and for the model this exists to serve, that comparison is the only check there is: a mask or position bug does not raise, it produces plausible, smoothly drifting video. The FlashInfer alternative was measured at ~9% on the attention kernel, against the 2x that had motivated trying it.Stateless across steps. The session state is the ring, and the ring belongs to the KV resource this one names in
depends_on; nothing here survives a call except the label/layer cursors the base class defines.- attend(q, k, v, visible, *, enable_gqa, layer_idx=None)[source]#
One layer’s attention over the ring.
qis[B, H_q, T, D];k/vare[B, H_kv, kv_len, D], the whole ring view (history slots plus the scratch frame) as the KV resource returned it.visibleis[kv_len]bool, True where that view holds KV this step may read — it is not derivable from a length, which is the entire reason this backend exists. Returns[B, H_q, T, D].
- build_accelerator_graph_buffers(slots, max_bs, max_seq_len)[source]#
Size whatever the captured replays will read.
Called once per runner that captures against this node — the whole forward’s, and one per piecewise region — so it must tolerate repeated calls: grow to the largest shape asked for, never clobber what an earlier call already sized.
- Parameters:
slots (list[CGSlotSpec])
max_bs (int)
max_seq_len (int)
- Return type:
None
- property needs_token_visibility: bool#
Whether the ring must construct its legacy token-level mask.
Engine execution stages a block mask in
planand does not need the per-layer row. The fallback remains useful for standalone numerical calls that invokeattendwithout a resource plan.
- plan(step, ctx)[source]#
Stage one local/global visibility mask for this frame and slot.
- Parameters:
step (AttentionStep)
ctx (StepContext)
- Return type:
None
- property requires_kv_write: bool#
the layer has already written this step’s K/V.
A ring
upsertis not the paged backends’write_kv. It writes the frame and returns the whole ring view to attend against, in one call, because which slots the write makes visible is part of its result — so there is no separate write step for a layer to perform and calling one would commit the frame twice.A
@property, not a class attribute, to keep the base’s read-only contract:AttentionManager.requires_kv_writeis a property andDenseAttentionManageroverrides it as one. Shadowing it with a plainFalsewould work at runtime and quietly make the attribute writable on this subclass alone.- Type:
False
- mstar.engine.resources.attn.flex.flex_attention_masked(query, key, value, score_mod=None, block_mask=None, scale=None, enable_gqa=False, return_lse=False, kernel_options=None, *, return_aux=None)#
This function implements scaled dot product attention with an arbitrary attention score modification function.
This function computes the scaled dot product attention between query, key, and value tensors with a user-defined attention score modification function. The attention score modification function will be applied after the attention scores have been calculated between the query and key tensors. The attention scores are calculated as follows:
The
score_modfunction should have the following signature:def score_mod( score: Tensor, batch: Tensor, head: Tensor, q_idx: Tensor, k_idx: Tensor ) -> Tensor:
- Where:
score: A scalar tensor representing the attention score, with the same data type and device as the query, key, and value tensors.batch,head,q_idx,k_idx: Scalar tensors indicating the batch index, query head index, query index, and key/value index, respectively. These should have thetorch.intdata type and be located on the same device as the score tensor.
- Parameters:
query (Tensor) – Query tensor; shape \((B, Hq, L, E)\). For FP8 dtypes, should be in row-major memory layout for optimal performance.
key (Tensor) – Key tensor; shape \((B, Hkv, S, E)\). For FP8 dtypes, should be in row-major memory layout for optimal performance.
value (Tensor) – Value tensor; shape \((B, Hkv, S, Ev)\). For FP8 dtypes, should be in column-major memory layout for optimal performance.
score_mod (Optional[Callable]) – Function to modify attention scores. By default no score_mod is applied.
block_mask (Optional[BlockMask]) – BlockMask object that controls the blocksparsity pattern of the attention.
scale (Optional[float]) – Scaling factor applied prior to softmax. If none, the default value is set to \(\frac{1}{\sqrt{E}}\).
enable_gqa (bool) – If set to True, enables Grouped Query Attention (GQA) and broadcasts key/value heads to query heads.
return_lse (bool) – Whether to return the logsumexp of the attention scores. Default is False. Deprecated: Use
return_aux=AuxRequest(lse=True)instead.kernel_options (Optional[FlexKernelOptions]) – Options to control the behavior of the underlying Triton kernels. See
FlexKernelOptionsfor available options and usage examples.return_aux (Optional[AuxRequest]) – Specifies which auxiliary outputs to compute and return. If None, only the attention output is returned. Use
AuxRequest(lse=True, max_scores=True)to request both auxiliary outputs.
- Returns:
Attention output; shape \((B, Hq, L, Ev)\).
- When
return_auxis not None: aux (AuxOutput): Auxiliary outputs with requested fields populated.
- When
return_auxis None (deprecated paths): lse (Tensor): Log-sum-exp of attention scores; shape \((B, Hq, L)\). Only returned if
return_lse=True.
- When
- Return type:
output (Tensor)
- Shape legend:
\(N: \text{Batch size} ... : \text{Any number of other batch dimensions (optional)}\)
\(S: \text{Source sequence length}\)
\(L: \text{Target sequence length}\)
\(E: \text{Embedding dimension of the query and key}\)
\(Ev: \text{Embedding dimension of the value}\)
Warning
torch.nn.attention.flex_attention is a prototype feature in PyTorch. Please look forward to a more stable implementation in a future version of PyTorch. Read more about feature classification at: https://pytorch.org/blog/pytorch-feature-classification-changes/#prototype
- mstar.engine.resources.attn.flex.make_block_mask(q_len, kv_len, written)[source]#
Build the query-uniform, full-blocks-only
BlockMaskoverwritten.writtenis[kv_len]bool, True where the ring holds valid KV. Both lengths must be exact multiples of the 128-token sparse block size andwrittenmust be block-aligned – both hold because writes are whole frames of 512 (or 128) tokens.Two properties are load-bearing. Every query block sees the same KV blocks, so the
[1, 1, 1, num_kv_blocks]row broadcasts over query blocks andcompute_q_blocks=Falseis safe. And every visible block is full (no partial blocks at all), because frame-granular writes mean “any token in the block is written” and “all of them are” coincide.