Skip to content

vllm.models.muse_spark.amd.mono.kernels.k3

K3: one Muse Spark decoder layer for S = 8 / 16 rows as one persistent launch.

One rank of a TP = EP = 8 group (rank r owns experts [32 r, 32 r + 32)), 256 CTAs x 512 threads, everything between two attention cores:

[attention]  optional: this layer's verify attention (attn_frag.py) at the head
O      o-norm x sigmoid(gate) -> o_proj rows 32 b .. over this rank's K slice; the bf16
       partial goes to the owner rank of the column block (b // 32): reduce-scatter
AB     the owner sums the 8 partials in rank order and all-gathers the reduced o and its
       norm partials; every CTA: post-attention norm, gated residual on the fp32 stream,
       pre-FFN norm -> ffn_in (one token-reduction round for both norms)
A      router logits (fp32) + pre_expert_proj of this rank's shard, K in 8 parts over
       8-CTA groups; logit partials and h_raw go to every rank's peer buffer
route  every CTA routes every token (identical top-8), the local experts' picks
C, D   gate_up / down of the local experts: MXFP4 weights in vLLM's shuffled layouts,
       decoded in registers, bf16 MFMA
E      per-pick post-expert norm and weighted sum -> the EP partial, reduce-scattered to
       the block owner, summed in rank order, all-gathered
F      post_expert_proj (this rank's 1024 rows, K in 4 parts) -> every rank
G      post-FFN norm, gated residual, the next layer's input norm -> stream (fp32) and
       the next attention input (bf16)
QKV    the next layer's qkv + gate GEMV (K in eighths); the owners finish whole heads:
       qk-norm, RoPE (next_rope), q out, bf16 K / V into vLLM's LBHNC KV cache

Peer regions are double buffered by tag parity; tag = epoch * 64 + layer + 1 with the epoch bumped in lockstep by every rank once per forward.

Functions:

  • bf_mma_operand –

    Coalesced bf16 weight registers (4 instructions: rows 8 blk + lane / 8, 16 B at

  • bf_tile_load –

    16 rows (row16 ..) x 128 K (k ..) of a row-major bf16 [*, ldk] weight, coalesced.

  • bf_tile_load_mma –

    16 rows (row16 ..) x 128 K (k ..) of a row-major bf16 [*, ldk] weight, loaded straight in the

  • build_vllm –

    The K3 build vLLM launches for S rows (8 / 16) of a TP = EP = 8 group; next_rope: the next

  • dn_loads –

    Task (u, j)'s w2 operands for this wave (expert etab[u], u clamped below nv).

  • fp4_mma –

    Chunk c (256 K) of a 16-row MXFP4 group: 8 MFMA steps, B column n = LDS row row0 + n (at

  • mx_chunk –

    Rows rbase .. rbase + 16 x K chunk c (256) of a shuffled MXFP4 [*, k] weight w and its e8m0

  • o_gate –

    o-norm (over the head's 8 lanes) x sigmoid(gate) of 8 bf16 (4 pair words xv, gv) -> 4 words.

  • peer_layout –

    Every rank's peer buffer (IPC-shared), [parity] first.

  • route_token –

    Tokens tkns (this wave's, all valid), interleaved for ILP: sigmoid +

  • scratch_layout –

    This rank's scratch regions. ss, ss1, ss2g, ssa1 and ssa2 are unused; they keep the

  • task_ring –

    Tasks task .. end - 1: compute(q[0], task, it, *args) with the next len(q) tasks' loads

bf_mma_operand(ops, qq, lane)

Coalesced bf16 weight registers (4 instructions: rows 8 blk + lane / 8, 16 B at 128 h + 16 (lane % 8)) -> the MFMA A operand of step qq (K 32 qq + 8 g of row r).

Source code in vllm/models/muse_spark/amd/mono/kernels/k3.py
def bf_mma_operand(ops, qq, lane):
    """Coalesced bf16 weight registers (4 instructions: rows 8 blk + lane / 8, 16 B at
    128 h + 16 (lane % 8)) -> the MFMA A operand of step qq (K 32 qq + 8 g of row r)."""
    r = lane % 16
    g = lane // 16
    h = qq // 2
    src = 8 * (r % 8) + 4 * (qq % 2) + g
    hi = r >= 8
    ws = []
    for jj in range_constexpr(4):
        pa = bpermute(ops[h][jj], src)
        pb = bpermute(ops[2 + h][jj], src)
        ws.append(hi.select(pb, pa))
    return fx.Vector.from_elements(ws, fx.Int32)

bf_tile_load(wbase, row16, ldk, k, lane)

16 rows (row16 ..) x 128 K (k ..) of a row-major bf16 [*, ldk] weight, coalesced.

Source code in vllm/models/muse_spark/amd/mono/kernels/k3.py
def bf_tile_load(wbase, row16, ldk, k, lane):
    """16 rows (row16 ..) x 128 K (k ..) of a row-major bf16 [*, ldk] weight, coalesced."""
    out = []
    for blk in range_constexpr(2):
        rowc = row16 + 8 * blk + lane // 8
        for h in range_constexpr(2):
            out.append(
                ld_vec(wbase, (rowc * ldk + k + 64 * h + 8 * (lane % 8)) // 2, 4, CM_NT)
            )
    return out

bf_tile_load_mma(wbase, row16, ldk, k, lane, cm=CM_NT)

16 rows (row16 ..) x 128 K (k ..) of a row-major bf16 [*, ldk] weight, loaded straight in the 16x16x32 bf16 MFMA A-operand layout: element qq (of 4) is the operand of MFMA step qq (lane l = row l % 16, K 32 qq + 8 (l / 16) .. + 8), 16 rows x 64 B an instruction. The same operand values as bf_tile_load + bf_mma_operand (bit-identical results) without the 8 ds_bpermute a step.

Source code in vllm/models/muse_spark/amd/mono/kernels/k3.py
def bf_tile_load_mma(wbase, row16, ldk, k, lane, cm=CM_NT):
    """16 rows (row16 ..) x 128 K (k ..) of a row-major bf16 [*, ldk] weight, loaded straight in the
    16x16x32 bf16 MFMA A-operand layout: element qq (of 4) is the operand of MFMA step qq (lane l = row
    l % 16, K 32 qq + 8 (l / 16) .. + 8), 16 rows x 64 B an instruction. The same operand values as
    bf_tile_load + bf_mma_operand (bit-identical results) without the 8 ds_bpermute a step."""
    rowm = row16 + lane % 16
    kk = k + 8 * (lane // 16)
    return [ld_vec(wbase, (rowm * ldk + kk + 32 * qq) // 2, 4, cm) for qq in range(4)]

build_vllm(S=8, W=8, next_rope=True, attn='')

The K3 build vLLM launches for S rows (8 / 16) of a TP = EP = 8 group; next_rope: the next layer has RoPE; attn = "swa" / "full": this layer's verify attention fused at the head.

Source code in vllm/models/muse_spark/amd/mono/kernels/k3.py
def build_vllm(S=8, W=8, next_rope=True, attn=""):
    """The K3 build vLLM launches for S rows (8 / 16) of a TP = EP = 8 group; next_rope: the next
    layer has RoPE; attn = "swa" / "full": this layer's verify attention fused at the head."""
    assert W == 8 and S in (8, 16), (S, W)
    return Build(S=S, next_rope=bool(next_rope), attn=attn)

dn_loads(w2, w2s, w_post, etab, task, lane, wave, ok, nv=None)

Task (u, j)'s w2 operands for this wave (expert etab[u], u clamped below nv).

Source code in vllm/models/muse_spark/amd/mono/kernels/k3.py
def dn_loads(w2, w2s, w_post, etab, task, lane, wave, ok, nv=None):
    """Task (u, j)'s w2 operands for this wave (expert etab[u], u clamped below nv)."""
    r = lane % 16
    g = lane // 16
    task = ok.select(task, fx.Int32(0))
    u = task >> 8
    j = task & 255
    e = uniform(fx.ptr_load(etab + (u if nv is None else fx.min(u, nv - 1))))
    rbase = e * DM + j * 16
    ops = []
    for i in range_constexpr(2):
        c = 2 * wave + i
        ops += mx_chunk(ok, w2, w2s, rbase, INTER, c, lane, g, r, W2_BYTES, W2S_BYTES)
    # the epilogue's w_post pair (rows 16j + 2 (lane % 8), +1): loaded with the weights,
    # not in the epilogue, where it would wait behind the whole prefetch queue
    ops.append(ld_i32_if(ok, w_post, 8 * j + lane % 8, DM * 2))
    return ops

fp4_mma(ops, base, bl, brow, lane, acc, c, jpar, rows, row0=0)

Chunk c (256 K) of a 16-row MXFP4 group: 8 MFMA steps, B column n = LDS row row0 + n (at most rows - 1: columns past the expert's picks read some row, their outputs are never stored). jpar: the task's 16-row group parity (j & 1), for the shuffled scales.

Source code in vllm/models/muse_spark/amd/mono/kernels/k3.py
def fp4_mma(ops, base, bl, brow, lane, acc, c, jpar, rows, row0=0):
    """Chunk c (256 K) of a 16-row MXFP4 group: 8 MFMA steps, B column n = LDS row row0 + n (at
    most rows - 1: columns past the expert's picks read some row, their outputs are never stored).
    ``jpar``: the task's 16-row group parity (j & 1), for the shuffled scales."""
    g = lane // 16
    t = fx.min(row0 + lane % 16, rows - 1)
    sw = ops[base + 2]
    # a = the dword of the lane's lower-half partner (K block % 4 = 2 (g % 2)), b = of the upper-half one
    # (2 (g % 2) + 1); the byte = 2 (g // 2) (K block + 4) + the row group parity (rows + 16)
    sa_, sb_ = permlane_swap(32, sw, sw)
    shs = (g // 2) * 16 + jpar * 8
    s0 = e8m0_f32((sa_ >> shs) & 0xFF)
    s1 = e8m0_f32((sb_ >> shs) & 0xFF)
    # loaded (shuffled): vector q lane 16 p + r' = row r', piece 4 q + p; MFMA lane 16 g + r wants row r
    # pieces 2 g, 2 g + 1: X0 = [V0 p0, V0 p2, V1 p0, V1 p2], X1 = [V0 p1, V0 p3, V1 p1, V1 p3] (16-lane
    # rows) = permlane32_swap then permlane16_swap, no bpermute
    x0, x1 = [], []
    for jj in range_constexpr(4):
        a_, b_ = permlane_swap(32, ops[base][jj], ops[base + 1][jj])
        p_, q_ = permlane_swap(16, a_, b_)
        x0.append(p_)
        x1.append(q_)
    xs = [x0, x1]
    for d in range_constexpr(8):
        word = xs[d // 4][d % 4]
        a = fp4x8_bf16(word, s0 if d < 4 else s1)
        kk = FCH * c + 64 * g + 8 * d
        b = fx.Vector(
            fx.ptr_load(
                bl + (t * brow + kk) // 2,
                result_type=fx.Vector.make_type(4, fx.Int32),
            )
        ).bitcast(fx.BFloat16)
        acc = mfma_bf16(a, b, acc)
    return acc

mx_chunk(ok, w, ws, rbase, k, c, lane, g, r, nbytes, sbytes)

Rows rbase .. rbase + 16 x K chunk c (256) of a shuffled MXFP4 [*, k] weight w and its e8m0 scales ws: 2 dwordx4 + 1 scale dword. vLLM shuffle_weight((16, 16)): lane L reads the 16 B at 16 L of the 1 KB block (16 rows x K bytes 64 (2 c + q) ..): one instruction = 1 KB contiguous; fp4_mma's permlane swaps map the pieces to the MFMA lanes. e8m0_shuffle: lane 16 g + r reads the dword (rbase // 32, c, K block % 4 = 2 (g % 2) + g // 2, row r): rows r, r + 16 x K blocks of 4 apart; 64 lanes = 256 B contiguous (kernel_s_dword).

Source code in vllm/models/muse_spark/amd/mono/kernels/k3.py
def mx_chunk(ok, w, ws, rbase, k, c, lane, g, r, nbytes, sbytes):
    """Rows rbase .. rbase + 16 x K chunk c (256) of a shuffled MXFP4 [*, k] weight w and its e8m0
    scales ws: 2 dwordx4 + 1 scale dword. vLLM shuffle_weight((16, 16)): lane L reads the 16 B at
    16 L of the 1 KB block (16 rows x K bytes 64 (2 c + q) ..): one instruction = 1 KB contiguous;
    fp4_mma's permlane swaps map the pieces to the MFMA lanes. e8m0_shuffle: lane 16 g + r reads
    the dword (rbase // 32, c, K block % 4 = 2 (g % 2) + g // 2, row r): rows r, r + 16 x K blocks
    of 4 apart; 64 lanes = 256 B contiguous (kernel_s_dword)."""
    wb = (rbase * (k // 2) + (2 * c) * 1024 + lane * 16) // 4
    ops = [
        ld_vec_if(ok, w, wb, 4, nbytes, CM_NT),
        ld_vec_if(ok, w, wb + 256, 4, nbytes, CM_NT),
    ]
    sdw = (rbase >> 5) * (8 * (k // 32)) + 64 * c + 16 * (2 * (g % 2) + g // 2) + r
    return ops + [ld_i32_if(ok, ws, sdw, sbytes)]

o_gate(xv, gv)

o-norm (over the head's 8 lanes) x sigmoid(gate) of 8 bf16 (4 pair words xv, gv) -> 4 words.

Source code in vllm/models/muse_spark/amd/mono/kernels/k3.py
def o_gate(xv, gv):
    """o-norm (over the head's 8 lanes) x sigmoid(gate) of 8 bf16 (4 pair words xv, gv) -> 4 words."""
    ss = fx.Float32(0.0)
    for d in range_constexpr(4):
        ss = ss + bf_lo(xv[d]) * bf_lo(xv[d]) + bf_hi(xv[d]) * bf_hi(xv[d])
    ss = butterfly(ss, (1, 2, 4))
    rstd = fx.Float32(1.0) / hw_sqrt(ss * fx.Float32(1.0 / HD) + fx.Float32(PRE_EPS))
    sig = lambda x: fx.Float32(1.0) / (
        fx.Float32(1.0) + hw_exp2(x * fx.Float32(-LOG2E))
    )
    ow = []
    for d in range_constexpr(4):
        s0 = sig(bf_lo(gv[d]))
        s1 = sig(bf_hi(gv[d]))
        ow.append(bf16_pair(bf_lo(xv[d]) * rstd * s0, bf_hi(xv[d]) * rstd * s1))
    return ow

peer_layout(S, world=W)

Every rank's peer buffer (IPC-shared), [parity] first.

Source code in vllm/models/muse_spark/amd/mono/kernels/k3.py
def peer_layout(S, world=W):
    """Every rank's peer buffer (IPC-shared), [parity] first."""
    assert world == W, world
    return _lay(
        [
            ("logit", 2 * KQ * S * E * 8),  # [par][kq][t][e] tagged
            ("hraw", 2 * S * DM * 2),  # [par][t][col] bf16 plain
            ("hf", 2 * W * BLOCKS * 8),  # [par][src][CTA] tagged flags
            ("moep", 2 * W * S * (DM // 2) * 8),  # [par][src][t][pair] tagged
            ("y", 2 * S * (HID // 2) * 8),  # [par][t][pair] tagged
            # o_proj partials [par][src][t][pair] tagged
            ("op", 2 * W * S * (HID // 2) * 8),
            # the owner's reduced o_proj [par][t][pair] tagged (all-gather)
            ("orr", 2 * S * (HID // 2) * 8),
            # the owner's reduced EP sum [par][t][pair] tagged (all-gather)
            ("mrr", 2 * S * (DM // 2) * 8),
            # the AB owners' norm partials [par][t][CTA][4] tagged (all-gather)
            ("ssa4p", 2 * 4 * S * BLOCKS * 8),
        ]
    )

route_token(tkns, bias_v, lgss, tid, lane, rt)

Tokens tkns (this wave's, all valid), interleaved for ILP: sigmoid + bias, radix top-8, rank, renorm -> rid / rw.

Source code in vllm/models/muse_spark/amd/mono/kernels/k3.py
@traced
def route_token(tkns, bias_v, lgss, tid, lane, rt):
    """Tokens ``tkns`` (this wave's, all valid), interleaved for ILP: sigmoid +
    bias, radix top-8, rank, renorm -> rid / rw."""
    T_ = len(tkns)
    keys, sigs = [], []
    for x_ in range_constexpr(T_):
        kx, sx = [], []
        for i in range_constexpr(4):
            lg = lgss[x_][i].bitcast(fx.Float32)
            sg = fx.Float32(1.0) / (fx.Float32(1.0) + hw_exp2(lg * fx.Float32(-LOG2E)))
            sc = sg + bias_v[i]
            live = sc == sc  # NaN ranks last
            kx.append(okey(live.select(sc, fx.Float32(-3.0e38))))
            sx.append((sg == sg).select(sg, fx.Float32(0.0)))
        keys.append(kx)
        sigs.append(sx)
    th = [fx.Uint32(0) for _ in range(T_)]
    for bit in range_constexpr(31, -1, -1):
        for x_ in range_constexpr(T_):
            cand = th[x_] | fx.Uint32(1 << bit)
            n = fx.Int32(0)
            for i in range_constexpr(4):
                n = n + popcount(ballot(keys[x_][i] >= cand))
            th[x_] = (n >= TOPK).select(cand, th[x_])
    for x_ in range_constexpr(T_):
        tkn = tkns[x_]
        n_gt = fx.Int32(0)
        for i in range_constexpr(4):
            n_gt = n_gt + popcount(ballot(keys[x_][i] > th[x_]))
        need = fx.Int32(TOPK) - n_gt
        eq_before = fx.Int32(0)
        sel_before = fx.Int32(0)
        sel_base = rt["sel"] + tkn * (TOPK * 3)
        for i in range_constexpr(4):
            eqb = ballot(keys[x_][i] == th[x_])
            eq_rank = eq_before + lanes_below(eqb, lane)
            sel = (keys[x_][i] > th[x_]) | ((keys[x_][i] == th[x_]) & (eq_rank < need))
            selb = ballot(sel)
            pos = sel_before + lanes_below(selb, lane)
            if sel:
                fx.ptr_store(keys[x_][i].bitcast(fx.Int32), sel_base + pos * 3)
                fx.ptr_store(fx.Int32(lane + 64 * i), sel_base + (pos * 3 + 1))
                fx.ptr_store(sigs[x_][i].bitcast(fx.Int32), sel_base + (pos * 3 + 2))
            eq_before = eq_before + popcount(eqb)
            sel_before = sel_before + popcount(selb)
    q = fx.min(lane, TOPK - 1)
    mks, mes, mss, ranks = [], [], [], []
    for x_ in range_constexpr(T_):
        sel_base = rt["sel"] + tkns[x_] * (TOPK * 3)
        mk = fx.Uint32(fx.ptr_load(sel_base + q * 3))
        me = fx.ptr_load(sel_base + (q * 3 + 1))
        ms = fx.ptr_load(sel_base + (q * 3 + 2)).bitcast(fx.Float32)
        rank_ = fx.Int32(0)
        for j in range_constexpr(TOPK):
            ok = fx.Uint32(fx.ptr_load(sel_base + j * 3))
            oe = fx.ptr_load(sel_base + (j * 3 + 1))
            before = (ok > mk) | ((ok == mk) & (oe < me))
            rank_ = rank_ + before.select(fx.Int32(1), fx.Int32(0))
        mks.append(mk)
        mes.append(me)
        mss.append(ms)
        ranks.append(rank_)
    # serial sum of the 8 sigmoids in rank order (+ eps), IEEE division
    for x_ in range_constexpr(T_):
        if lane < TOPK:
            fx.ptr_store(mss[x_], rt["rw"] + (tkns[x_] * TOPK + ranks[x_]))
    for x_ in range_constexpr(T_):
        tkn = tkns[x_]
        total = fx.Float32(0.0)
        for j in range_constexpr(TOPK):
            total = total + fx.ptr_load(rt["rw"] + (tkn * TOPK + j))
        total = total + fx.Float32(ROUTE_EPS)
        if lane < TOPK:
            fx.ptr_store(
                fx.min(fx.max(mes[x_], 0), fx.Int32(E - 1)),
                rt["rid"] + (tkn * TOPK + ranks[x_]),
            )
            fx.ptr_store(mss[x_] / total, rt["rw"] + (tkn * TOPK + ranks[x_]))

scratch_layout(S, world=W)

This rank's scratch regions. ss, ss1, ss2g, ssa1 and ssa2 are unused; they keep the offsets of the regions after them.

Source code in vllm/models/muse_spark/amd/mono/kernels/k3.py
def scratch_layout(S, world=W):
    """This rank's scratch regions. ss, ss1, ss2g, ssa1 and ssa2 are unused; they keep the
    offsets of the regions after them."""
    assert world == W, world
    P = S * TOPK
    return _lay(
        [
            ("px", NG * KQ * 64 * S * 8),  # [group][K part][row < RT <= 64][t]
            ("a", P * (INTER // 2) * 8),
            ("z", P * (DM // 2) * 8),
            ("ss", P * 256 * 8),
            ("ss2", P * 256 * 8),
            ("m", S * DM * 2),  # all-reduced MoE output (bf16, plain)
            ("mf", BLOCKS * 8),  # m tile flags
            ("py", 512 * 16 * S * 8),  # post-proj K-part partials
            ("ss1", (S * BLOCKS + S) * 8),
            ("ss2g", (S * BLOCKS + S) * 8),
            ("route", P * 8),
            ("xin", S * HID * 2),  # ffn_in (bf16 plain), CTA b's 32 columns each
            ("xf", BLOCKS * 8),  # its flags
            ("smid", S * HID * 4),  # stream after the attention residual (fp32 plain)
            ("ssa1", (S * BLOCKS + S) * 8),
            ("ssa2", (S * BLOCKS + S) * 8),
            ("xn", S * HID * 2),  # next layer's attention input (bf16 plain)
            ("xnf", BLOCKS * 8),
            # AB: 4 partials [t][CTA][4], then (r1, r2)[t]
            ("ssa4", (4 * S * BLOCKS + 2 * S) * 8),
            ("ssg4", (4 * S * BLOCKS + 2 * S) * 8),  # G
            # qkvg K-eighth partials [group][src][tile row][t]
            ("qx", 32 * 8 * NQT * 16 * S * 8),
            # q / k / v rows (tagged bf16 pairs)
            ("qkv", S * (QKV_ROWS // 2) * 8),
        ]
    )

task_ring(load, compute, q, task, it, end, unr, *args)

Tasks task .. end - 1: compute(q[0], task, it, *args) with the next len(q) tasks' loads (load(task)) in flight. unr (len(q) = 2): three tasks an iteration in fixed slots (q[0], q[1], qc): two tasks' loads stay in flight during each compute, no rotation copy waits for its data (the tail: the second loop).

Source code in vllm/models/muse_spark/amd/mono/kernels/k3.py
@traced
def task_ring(load, compute, q, task, it, end, unr, *args):
    """Tasks task .. end - 1: compute(q[0], task, it, *args) with the next len(q) tasks' loads
    (load(task)) in flight. ``unr`` (len(q) = 2): three tasks an iteration in fixed slots (q[0],
    q[1], qc): two tasks' loads stay in flight during each compute, no rotation copy waits for its
    data (the tail: the second loop)."""
    if const_expr(unr):
        while task + 2 < end:
            qc = load(task + 2)
            compute(q[0], task, it, *args)
            qa = load(task + 3)
            compute(q[1], task + 1, it + 1, *args)
            qb = load(task + 4)
            compute(qc, task + 2, it + 2, *args)
            q = [qa, qb]
            task = task + 3
            it = it + 3
    while task < end:
        nxt = load(task + len(q))
        compute(q[0], task, it, *args)
        q = q[1:] + [nxt]
        task = task + 1
        it = it + 1
    return q, task, it