For the complete documentation index, see llms.txt. Markdown versions of all pages are available by appending .md to any URL (e.g. /max/get-started.md).
Mojo struct
DStateVecLoader
struct DStateVecLoader[state_dtype: DType, kernel_dtype: DType, ssm_pool_LT: TensorLayout, B_LT: TensorLayout, C_LT: TensorLayout, Storage: TensorStorage, VEC: Int, NCHUNK: Int]
Owner of the Apple SSD kernel's vectorized dstate state / B / C I/O.
Target hardware family: Apple silicon GPU (Metal 4). The B200
..._dstate_split sibling performs the identical widen-on-load /
round-on-store / vectorized-vs-scalar-fallback logic inline; it COULD reuse
this owner later (it is parameterized on the storage dtypes / layouts /
Storage), but is not wired to it here (Apple-scoped change).
Every DRAM <-> register transition on the innermost (dstate) axis has an
owner here instead of a raw_load / raw_store scattered across the
kernel body -- the owner-per-transition pattern (see VarlenConvIO in
varlen_causal_conv1d.mojo, Fp4WeightLoader in matmul2d_fp4.mojo,
and new-primitives/amd-tile-io-expert-objects). Three verbs:
load_state: widenssm_poolstorage -> fp32 register chunks (theNCHUNKVEC-wide initial-state read).load_bc: widen oneVEC-lane B and C chunk -> fp32.store_state: round the fp32 state chunks ->ssm_poolstorage.
Each verb owns the VEC-wide aligned raw_load / raw_store and the
scalar fallback, so the recurrence in the kernel body indexes only fp32
registers and issues no raw load/store. load_state / store_state
each own their contig branch, which wraps the whole NCHUNK loop (a
verbatim relocation of the prior inline loops). load_bc runs inside the
fused recurrence loop, so it takes the contig decision as a COMPTIME
contig parameter: the caller hoists the runtime bc_contig branch
ONCE outside the chunk loop, keeping the fast path a straight-line unrolled
vec-load loop (a per-chunk runtime branch measured ~18% slower on M5). Every
method is @always_inline. The vectorized fast path (unit innermost
stride) serves every row-major caller; a non-unit stride selects the exact
v1 scalar gather/scatter, so the result is bit-identical for any layout.
Parametersβ
- βstate_dtype (
DType):ssm_poolstorage dtype (fp32 or bf16). - βkernel_dtype (
DType): B / C element dtype. - βssm_pool_LT (
TensorLayout): Layout type of thessm_poolview. - βB_LT (
TensorLayout): Layout type of theBview. - βC_LT (
TensorLayout): Layout type of theCview. - βStorage (
TensorStorage): Shared tensor-storage policy of the views. - βVEC (
Int): SIMD load/store width over the contiguous dstate axis. - βNCHUNK (
Int): Number ofVEC-wide chunks spanningDSTATE.
Fieldsβ
- βssm_pool (
TileTensor[state_dtype, ssm_pool_LT, MutUntrackedOrigin, Storage=Storage]): - βB (
TileTensor[kernel_dtype, B_LT, MutUntrackedOrigin, Storage=Storage]): - βC (
TileTensor[kernel_dtype, C_LT, MutUntrackedOrigin, Storage=Storage]): - βpool_dstate_stride (
Int): - βb_dstate_stride (
Int): - βc_dstate_stride (
Int): - βpool_contig (
Bool): - βbc_contig (
Bool):
Implemented traitsβ
AnyType,
Copyable,
ImplicitlyCopyable,
ImplicitlyDeletable,
Movable
Methodsβ
__init__β
def __init__(out self, ssm_pool: TileTensor[state_dtype, ssm_pool_LT, MutUntrackedOrigin, Storage=Storage], B: TileTensor[kernel_dtype, B_LT, MutUntrackedOrigin, Storage=Storage], C: TileTensor[kernel_dtype, C_LT, MutUntrackedOrigin, Storage=Storage], pool_dstate_stride: Int, b_dstate_stride: Int, c_dstate_stride: Int)
load_stateβ
def load_state(self, mut state: Array[SIMD[DType.float32, VEC], NCHUNK], pool_base: UInt32)
Fill fp32 state from ssm_pool[.., pool_base + n] (widening).
The load widens to fp32 (a no-op when state_dtype is fp32); the
recurrence downstream runs on the fp32 register copy.
load_bcβ
def load_bc[c: Int, contig: Bool](self, b_base: UInt32, c_base: UInt32, mut b_c: SIMD[DType.float32, VEC], mut c_c: SIMD[DType.float32, VEC])
Load B and C chunk c (VEC dstate lanes each), widening to fp32.
contig is a COMPTIME parameter: the caller reads self.bc_contig
and hoists the runtime branch ONCE outside the NCHUNK chunk loop,
then instantiates the pure vectorized (contig=True) or pure
scalar-gather (contig=False) path here. A per-chunk runtime branch
interleaves the cold scalar-gather code into the hot vectorized loop and
measured ~18% slower on M5 (33.6 vs 28.4 us/launch at the decode shape),
so the fast path must stay a straight-line unrolled vec-load loop.
store_stateβ
def store_state(self, state: Array[SIMD[DType.float32, VEC], NCHUNK], pool_wb: UInt32)
Round fp32 state to state_dtype and write back to ssm_pool.
The round happens once here at the final write-back (a no-op when
state_dtype is fp32); the recurrent accumulator never leaves fp32.
Was this page helpful?
Thank you! We'll create more content like this.
Thank you for helping us improve!