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
MLA_SM100_Decode_Sparse
struct MLA_SM100_Decode_Sparse[q_type: DType, KVLUTType: MHAOperand, output_type: DType, SplitAccumType: OptionalPointer, MaskType: MHAMask, config: MLA_SM100_Decode_Config, ValidLengthType: OptionalPointer, _is_cache_length_accurate: Bool = False, ragged: Bool = False, has_attn_sink: Bool = False, has_extra_kv: Bool = False, has_variable_topk: Bool = False]
Sparse MLA decoding kernel for SM100 with FP8 KV cache and gather4 TMA.
Extends the SM100 MLA decode kernel to sparse attention by loading KV tiles through gather4 TMA using per-tile sparse indices. Uses four warpgroups plus four individual warps: a convert warpgroup performs FP8-to-BF16 conversion in shared memory before the QK and PV MMA warps consume the data. Supports blockwise FP8 scaling, attention sinks, an extra KV cache for always-attend tokens, and variable top-k lengths.
Parametersβ
- βq_type (
DType):DTypeof the query tensor and softmax accumulator. - βKVLUTType (
MHAOperand):MHAOperanddescribing the paged KV cache layout and element type; itsdtypeis the FP8 KV element type. - βoutput_type (
DType):DTypeof the output tensor written via TMA store. - βSplitAccumType (
OptionalPointer):OptionalPointerselecting the split-K accumulation buffer dtype used by the combine kernel. - βMaskType (
MHAMask):MHAMaskselecting the attention mask; onlyNullMaskandCausalMaskare supported. - βconfig (
MLA_SM100_Decode_Config):MLA_SM100_Decode_Configwith tile sizes, stage counts, and swizzle parameters for the decode kernel. - βValidLengthType (
OptionalPointer):OptionalPointerselecting the dtype of the per-batch valid-length buffer. - β_is_cache_length_accurate (
Bool): Whether the cached sequence length is exact, enabling tighter bounds (defaults toFalse). - βragged (
Bool): Whether ragged batching is enabled, so each batch may have a different query length (defaults toFalse). - βhas_attn_sink (
Bool): Whether an attention sink is applied, keeping leading tokens always attended (defaults toFalse). - βhas_extra_kv (
Bool): Whether a separate extra KV cache holds always-attend tokens (defaults toFalse). - βhas_variable_topk (
Bool): Whether the sparse top-k length varies per batch, read fromtopk_lengths(defaults toFalse).
Implemented traitsβ
AnyType,
Copyable,
ImplicitlyCopyable,
ImplicitlyDeletable,
Movable,
RegisterPassable,
TrivialRegisterPassable
comptime membersβ
AccumTypeβ
comptime AccumType = get_accum_type[q_type]()
bf16_bytes_per_elementβ
comptime bf16_bytes_per_element = size_of[DType.bfloat16]()
bf16_typeβ
comptime bf16_type = DType.bfloat16
BlockElemsβ
comptime BlockElems = (config * config)
bytes_per_elementβ
comptime bytes_per_element = size_of[q_type]()
Common_MLA_Opβ
comptime Common_MLA_Op = MLA_SM100_Decode_Common[q_type, KVLUTType, output_type, SplitAccumType, MaskType, config, ValidLengthType, _is_cache_length_accurate, ragged]
fp8_bytes_per_elementβ
comptime fp8_bytes_per_element = size_of[DType.float8_e4m3fn]()
fp8_typeβ
comptime fp8_type = DType.float8_e4m3fn
gather4_indices_bytesβ
comptime gather4_indices_bytes = (config * size_of[Int32]())
gather4_num_4row_chunksβ
comptime gather4_num_4row_chunks = (config // Int(4))
kv_nope_typeβ
comptime kv_nope_type = KVLUTType.dtype
kv_rope_typeβ
comptime kv_rope_type = DType.bfloat16
kv_typeβ
comptime kv_type = KVLUTType.dtype
KVStageElemsβ
comptime KVStageElems = ((config // config) * Int((mul config.BM, config.BN_QK)))
KVStageTotalBytesβ
comptime KVStageTotalBytes = (Int((mul (config // config), size_of[DType.float8_e4m3fn](), config.BM, config.BN_QK)) + Int((mul (config // config), size_of[DType.bfloat16](), config.BM, config.BN_QK)))
load2cvt_num_producerβ
comptime load2cvt_num_producer = (Int(1) + Int(32) if (xor (eq (xor (lt config.scale_block_size, 1), True), False), True) else Int(0))
nope_gather4_box_wβ
comptime nope_gather4_box_w = _gather4_box_width[DType.int64, (config // Int(8)), TensorMapSwizzle.SWIZZLE_NONE]()
nope_gather4_num_col_groupsβ
comptime nope_gather4_num_col_groups = ceildiv((config // Int(8)), _gather4_box_width[DType.int64, (config // Int(8)), TensorMapSwizzle(Int32(0))]())
nope_gather4_tile_widthβ
comptime nope_gather4_tile_width = (config // Int(8))
NopeStageBytesβ
comptime NopeStageBytes = (Int((mul (config // config), config.BM, config.BN_QK)) * size_of[DType.float8_e4m3fn]())
NopeStageElemsβ
comptime NopeStageElems = ((config // config) * Int((mul config.BM, config.BN_QK)))
NumNopeBlocksβ
comptime NumNopeBlocks = (config // config)
NumQKBlocksβ
comptime NumQKBlocks = (config // config)
NumRopeBlocksβ
comptime NumRopeBlocks = (config // config)
NumVOBlocksβ
comptime NumVOBlocks = (config // config)
output_tile_widthβ
comptime output_tile_width = ((config // Int(2)) * (Int(4) // size_of[output_type]()))
rope_gather4_box_wβ
comptime rope_gather4_box_w = _gather4_box_width[DType.bfloat16, (Int((add (mul config.rope_depth, 2), config.padded_depth)) // Int(2)), TensorMapSwizzle.SWIZZLE_128B]()
rope_gather4_num_col_groupsβ
comptime rope_gather4_num_col_groups = ceildiv(config.rope_depth, _gather4_box_width[DType.bfloat16, (Int((add (mul config.rope_depth, 2), config.padded_depth)) // Int(2)), TensorMapSwizzle(Int32(3))]())
rope_gather4_tile_widthβ
comptime rope_gather4_tile_width = (Int((add (mul config.rope_depth, 2), config.padded_depth)) // Int(2))
RopeStageBytesβ
comptime RopeStageBytes = (Int((mul (config // config), config.BM, config.BN_QK)) * size_of[DType.bfloat16]())
RopeStageElemsβ
comptime RopeStageElems = ((config // config) * Int((mul config.BM, config.BN_QK)))
UMMAPVSSβ
comptime UMMAPVSS = DecodeSM100PVSS[q_type, MLA_SM100_Decode_Sparse[q_type, KVLUTType, output_type, SplitAccumType, MaskType, config, ValidLengthType, _is_cache_length_accurate, ragged, has_attn_sink, has_extra_kv, has_variable_topk].AccumType, config=config]
UMMAQKTSSβ
comptime UMMAQKTSS = DecodeSM100QKTSS[q_type, MLA_SM100_Decode_Sparse[q_type, KVLUTType, output_type, SplitAccumType, MaskType, config, ValidLengthType, _is_cache_length_accurate, ragged, has_attn_sink, has_extra_kv, has_variable_topk].AccumType, config=config]
Methodsβ
kernelβ
static def kernel(q_tma: TMATensorTile[q_type, Int(2), IndexList(config, config, __list_literal__=NoneType(None)), _default_desc_shape[Int(2), q_type, IndexList(config, config, __list_literal__=NoneType(None)), config.swizzle_mode]()], k_nope_tma: TMATensorTile[DType.int64, Int(2), IndexList(config, _gather4_box_width[DType.int64, (config // Int(8)), TensorMapSwizzle(Int32(0))](), __list_literal__=NoneType(None)), IndexList(Int(1), _gather4_box_width[DType.int64, (config // Int(8)), TensorMapSwizzle(Int32(0))](), __list_literal__=NoneType(None))], k_rope_tma: TMATensorTile[DType.bfloat16, Int(2), IndexList(config, _gather4_box_width[DType.bfloat16, (Int((add (mul config.rope_depth, 2), config.padded_depth)) // Int(2)), TensorMapSwizzle(Int32(3))](), __list_literal__=NoneType(None)), IndexList(Int(1), _gather4_box_width[DType.bfloat16, (Int((add (mul config.rope_depth, 2), config.padded_depth)) // Int(2)), TensorMapSwizzle(Int32(3))](), __list_literal__=NoneType(None))], o_tma: TMATensorTile[output_type, Int(2), IndexList(config, (config // Int(4)), __list_literal__=NoneType(None)), _default_desc_shape[Int(2), output_type, IndexList(config, (config // Int(4)), __list_literal__=NoneType(None)), config.swizzle_mode]()], kv_lut: KVLUTType, scale: Float32, mla_decode_pack: MLA_Decode_Pack[ValidLengthType, MaskType, SplitAccumType], d_indices: OptionalReg[Pointer[Int32, MutAnyOrigin, _safe=False]], indices_stride: Int, topk_lengths: OptionalReg[Pointer[Int32, MutAnyOrigin, _safe=False]], scales_ptr: Pointer[Float32, MutAnyOrigin, _safe=False], attn_sink_ptr: OptionalReg[Pointer[Float32, MutAnyOrigin, _safe=False]], extra_k_nope_tma: TMATensorTile[DType.int64, Int(2), IndexList(config, _gather4_box_width[DType.int64, (config // Int(8)), TensorMapSwizzle(Int32(0))](), __list_literal__=NoneType(None)), IndexList(Int(1), _gather4_box_width[DType.int64, (config // Int(8)), TensorMapSwizzle(Int32(0))](), __list_literal__=NoneType(None))], extra_k_rope_tma: TMATensorTile[DType.bfloat16, Int(2), IndexList(config, _gather4_box_width[DType.bfloat16, (Int((add (mul config.rope_depth, 2), config.padded_depth)) // Int(2)), TensorMapSwizzle(Int32(3))](), __list_literal__=NoneType(None)), IndexList(Int(1), _gather4_box_width[DType.bfloat16, (Int((add (mul config.rope_depth, 2), config.padded_depth)) // Int(2)), TensorMapSwizzle(Int32(3))](), __list_literal__=NoneType(None))], extra_kv_lut: KVLUTType, extra_d_indices: OptionalReg[Pointer[Int32, MutAnyOrigin, _safe=False]], extra_topk_lengths: OptionalReg[Pointer[Int32, MutAnyOrigin, _safe=False]], extra_indices_stride: Int, extra_scales_ptr: OptionalReg[Pointer[Float32, MutAnyOrigin, _safe=False]], scalar_args: TileTensor[DType.int64, Layout[*?, *?], MutAnyOrigin])
idx_producerβ
static def idx_producer(idx_bars: DecodeSM100MiscMBars[Int(2), Int(32), Int(32)], idx_smem_base: Pointer[Int32, MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False], kv_lut: KVLUTType, d_indices: OptionalReg[Pointer[Int32, MutAnyOrigin, _safe=False]], topk: Int, scales_ptr: Pointer[Float32, MutAnyOrigin, _safe=False], scale_smem_base: Pointer[UInt8, MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False], offset_position: OffsetPosition[config, KVLUTType, ragged, _is_cache_length_accurate, ValidLengthType, config.decoding_warp_split_k, True, has_extra_kv, has_variable_topk], num_orig_blocks: Int, extra_kv_lut: KVLUTType, extra_d_indices: OptionalReg[Pointer[Int32, MutAnyOrigin, _safe=False]], extra_topk: Int, extra_scales_ptr: OptionalReg[Pointer[Float32, MutAnyOrigin, _safe=False]])
Index transform producer running on warp 11 (32 threads).
For each KV tile, transforms d_indices to TMA rows and (when blockwise) loads FP32 scales to scale SMEM. Signals idx_bars when each tile's data is ready. Runs 1 tile ahead of warp 8.
Args:
- βidx_bars (
DecodeSM100MiscMBars[Int(2), Int(32), Int(32)]): Double-buffered barrier pipeline between this producer (warp 11) and the index consumer (warp 8). - βidx_smem_base (
Pointer[Int32, MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False]): Base SMEM pointer for the double-buffered transformed gather4 row indices,BN_QKInt32per stage. - βkv_lut (
KVLUTType):MHAOperandfor the original paged KV cache, used to convert encoded indices to TMA rows. - βd_indices (
OptionalReg[Pointer[Int32, MutAnyOrigin, _safe=False]]): Per-tile sparse indices into the original KV cache, encoded asphysical_block * page_size + offset;-1marks invalid entries. - βtopk (
Int): Number of selected KV tokens in the original cache for this batch. - βscales_ptr (
Pointer[Float32, MutAnyOrigin, _safe=False]): Pointer to FP32 blockwise scales for the original KV cache. - βscale_smem_base (
Pointer[UInt8, MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False]): Base SMEM pointer for the double-buffered e8m0 scales, used whenconfig.scale_block_size > 0. - βoffset_position (
OffsetPosition[config, KVLUTType, ragged, _is_cache_length_accurate, ValidLengthType, config.decoding_warp_split_k, True, has_extra_kv, has_variable_topk]): Precomputed per-CTA position and offset state for the current batch and split. - βnum_orig_blocks (
Int): Number ofBN_QK-sized KV tiles belonging to the original cache, equalsceildiv(topk, BN_QK). - βextra_kv_lut (
KVLUTType):MHAOperandfor the extra paged KV cache holding always-attend tokens. - βextra_d_indices (
OptionalReg[Pointer[Int32, MutAnyOrigin, _safe=False]]): Per-tile sparse indices into the extra KV cache, encoded asphysical_block * page_size + offset;-1marks invalid entries. - βextra_topk (
Int): Number of selected KV tokens in the extra cache for this batch. - βextra_scales_ptr (
OptionalReg[Pointer[Float32, MutAnyOrigin, _safe=False]]): Pointer to FP32 blockwise scales for the extra KV cache, orNonewhen blockwise scaling is off.
loadβ
static def load(q_tma: TMATensorTile[q_type, Int(2), IndexList(config, config, __list_literal__=NoneType(None)), _default_desc_shape[Int(2), q_type, IndexList(config, config, __list_literal__=NoneType(None)), config.swizzle_mode]()], k_nope_tma: TMATensorTile[DType.int64, Int(2), IndexList(config, _gather4_box_width[DType.int64, (config // Int(8)), TensorMapSwizzle(Int32(0))](), __list_literal__=NoneType(None)), IndexList(Int(1), _gather4_box_width[DType.int64, (config // Int(8)), TensorMapSwizzle(Int32(0))](), __list_literal__=NoneType(None))], k_rope_tma: TMATensorTile[DType.bfloat16, Int(2), IndexList(config, _gather4_box_width[DType.bfloat16, (Int((add (mul config.rope_depth, 2), config.padded_depth)) // Int(2)), TensorMapSwizzle(Int32(3))](), __list_literal__=NoneType(None)), IndexList(Int(1), _gather4_box_width[DType.bfloat16, (Int((add (mul config.rope_depth, 2), config.padded_depth)) // Int(2)), TensorMapSwizzle(Int32(3))](), __list_literal__=NoneType(None))], q_smem: Pointer[Scalar[q_type], MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False], kv_nope_smem_fp8: Pointer[Float8_e4m3fn, MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False], kv_rope_smem_bf16_base: Pointer[BFloat16, MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False], mbar_q: Pointer[SharedMemBarrier, MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False], kv_load2cvt_pipe: KVPipelineGeneric[config.num_kv_stages, Int(1), Int((add Int(32) if (xor (eq (xor (lt config.scale_block_size, 1), True), False), True) else Int(0), 1)), (_resolve_warpgroup_size() + Int(2))], offset_position: OffsetPosition[config, KVLUTType, ragged, _is_cache_length_accurate, ValidLengthType, config.decoding_warp_split_k, True, has_extra_kv, has_variable_topk], idx_bars: DecodeSM100MiscMBars[Int(2), Int(32), Int(32)], idx_smem_base: Pointer[Int32, MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False], num_orig_blocks: Int, topk: Int, extra_k_nope_tma: TMATensorTile[DType.int64, Int(2), IndexList(config, _gather4_box_width[DType.int64, (config // Int(8)), TensorMapSwizzle(Int32(0))](), __list_literal__=NoneType(None)), IndexList(Int(1), _gather4_box_width[DType.int64, (config // Int(8)), TensorMapSwizzle(Int32(0))](), __list_literal__=NoneType(None))], extra_k_rope_tma: TMATensorTile[DType.bfloat16, Int(2), IndexList(config, _gather4_box_width[DType.bfloat16, (Int((add (mul config.rope_depth, 2), config.padded_depth)) // Int(2)), TensorMapSwizzle(Int32(3))](), __list_literal__=NoneType(None)), IndexList(Int(1), _gather4_box_width[DType.bfloat16, (Int((add (mul config.rope_depth, 2), config.padded_depth)) // Int(2)), TensorMapSwizzle(Int32(3))](), __list_literal__=NoneType(None))], extra_topk: Int)
convertFP8ToBF16β
static def convertFP8ToBF16(kv_nope_smem_fp8: Pointer[Float8_e4m3fn, MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False], kv_smem_bf16: Pointer[Scalar[q_type], MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False], kv_load2cvt_pipe: KVPipelineGeneric[config.num_kv_stages, Int(1), Int((add Int(32) if (xor (eq (xor (lt config.scale_block_size, 1), True), False), True) else Int(0), 1)), (_resolve_warpgroup_size() + Int(2))], kv_cvt2mma_pipe: KVPipelineGeneric[config.num_kv_stages, Int(1), _resolve_warpgroup_size(), Int(2)], num_k_tiles: Int, scale_smem_base: Pointer[UInt8, MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False])
mmaQKβ
static def mmaQK(tmem_addr: UInt32, q_smem: Pointer[Scalar[q_type], MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False], kv_smem: Pointer[Scalar[q_type], MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False], mbar_q: Pointer[SharedMemBarrier, MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False], s_bars: DecodeSM100MiscMBars[Int(2), Int(1), _resolve_warpgroup_size()], kv_cvt2mma_pipe: KVPipelineGeneric[config.num_kv_stages, Int(1), _resolve_warpgroup_size(), Int(2)], kv_load2cvt_pipe: KVPipelineGeneric[config.num_kv_stages, Int(1), Int((add Int(32) if (xor (eq (xor (lt config.scale_block_size, 1), True), False), True) else Int(0), 1)), (_resolve_warpgroup_size() + Int(2))], offset_position: OffsetPosition[config, KVLUTType, ragged, _is_cache_length_accurate, ValidLengthType, config.decoding_warp_split_k, True, has_extra_kv, has_variable_topk])
mmaPVβ
static def mmaPV(tmem_addr: UInt32, kv_smem: Pointer[Scalar[q_type], MutAnyOrigin, address_space=AddressSpace.SHARED, _safe=False], p_bars: DecodeSM100MiscMBars[Int(2), _resolve_warpgroup_size(), Int(1)], o_bars: DecodeSM100MiscMBars[Int(2), Int(1), _resolve_warpgroup_size()], kv_cvt2mma_pipe: KVPipelineGeneric[config.num_kv_stages, Int(1), _resolve_warpgroup_size(), Int(2)], kv_load2cvt_pipe: KVPipelineGeneric[config.num_kv_stages, Int(1), Int((add Int(32) if (xor (eq (xor (lt config.scale_block_size, 1), True), False), True) else Int(0), 1)), (_resolve_warpgroup_size() + Int(2))], offset_position: OffsetPosition[config, KVLUTType, ragged, _is_cache_length_accurate, ValidLengthType, config.decoding_warp_split_k, True, has_extra_kv, has_variable_topk])
Was this page helpful?
Thank you! We'll create more content like this.
Thank you for helping us improve!