KernelBench mega · RTX PRO 6000
Kimi-Linear Decode GPT-6.1 Sol
4.99×geomean speedup across shapes
One persistent Triton launch per decode step covers all four layers: streamed int4 GEMVs that dequantize per 128-row group and round weights to bf16 like the reference, KDA short convolutions and delta-rule state updates, MLA attention in the 512-dim latent space with W_k absorbed into the query, the router top-8, and routed plus shared experts, synchronized by an atomic counter barrier. Profiling confirmed one GPU kernel per step.
harnesscodex
Kernel source (redacted)
"""Single-launch, persistent Triton implementation of the hybrid decode motif.
All large matrices stay in the original packed int4 representation. The one
resident grid executes the entire motif and synchronizes through an acquire /
release device counter. No expanded weight matrices or expanded KV cache exist.
"""
import torch
from torch import nn
import triton
import triton.language as tl
class QuantLinear(nn.Module):
def __init__(self, k, n, group=128):
super().__init__()
self.register_buffer('w_q', torch.empty(k // 2, n, dtype=torch.uint8))
self.register_buffer('scales', torch.empty(k // group, n, dtype=torch.bfloat16))
self.register_buffer('zeros', torch.empty(k // group, n, dtype=torch.bfloat16))
class QuantExperts(nn.Module):
def __init__(self, e, k, n, group=128):
super().__init__()
self.register_buffer('w_q', torch.empty(e, k // 2, n, dtype=torch.uint8))
self.register_buffer('scales', torch.empty(e, k // group, n, dtype=torch.bfloat16))
self.register_buffer('zeros', torch.empty(e, k // group, n, dtype=torch.bfloat16))
class KDA(nn.Module):
def __init__(self, c):
super().__init__()
d, a = c.hidden, c.kda_heads * c.kda_head_dim
self.q_proj = QuantLinear(d, a)
self.k_proj = QuantLinear(d, a)
self.v_proj = QuantLinear(d, a)
self.g_proj = QuantLinear(d, a)
self.o_proj = QuantLinear(a, d)
self.beta_proj = nn.Linear(d, c.kda_heads, bias=False, dtype=c.dtype)
self.conv_w = nn.Parameter(torch.empty(3, a, c.short_conv, dtype=c.dtype))
class MLA(nn.Module):
def __init__(self, c):
super().__init__()
self.q_proj = QuantLinear(c.hidden, c.mla_heads * (c.qk_nope + c.qk_rope))
self.kv_a = QuantLinear(c.hidden, c.kv_lora + c.qk_rope)
self.kv_b = QuantLinear(c.kv_lora, c.mla_heads * (c.qk_nope + c.v_head))
self.o_proj = QuantLinear(c.mla_heads * c.v_head, c.hidden)
class MoE(nn.Module):
def __init__(self, c):
super().__init__()
self.router = nn.Linear(c.hidden, c.n_experts, bias=False, dtype=c.dtype)
self.gate = QuantExperts(c.n_experts, c.hidden, c.moe_inter)
self.up = QuantExperts(c.n_experts, c.hidden, c.moe_inter)
self.down = QuantExperts(c.n_experts, c.moe_inter, c.hidden)
self.s_gate = QuantExperts(c.n_shared, c.hidden, c.moe_inter)
self.s_up = QuantExperts(c.n_shared, c.hidden, c.moe_inter)
self.s_down = QuantExperts(c.n_shared, c.moe_inter, c.hidden)
class Block(nn.Module):
def __init__(self, c, kind):
super().__init__()
self.attn_norm = nn.Parameter(torch.ones(c.hidden, dtype=c.dtype))
self.moe_norm = nn.Parameter(torch.ones(c.hidden, dtype=c.dtype))
self.attn = KDA(c) if kind == 'K' else MLA(c)
self.moe = MoE(c)
@triton.jit
def _barrier(Counter, GRID: tl.constexpr):
# The grid is smaller than the SM count; every CTA can remain resident.
tl.debug_barrier()
ticket = tl.atomic_add(Counter, 1, sem='acq_rel', scope='gpu')
target = (ticket // GRID + 1) * GRID
while tl.atomic_add(Counter, 0, sem='acquire', scope='gpu') < target:
pass
tl.debug_barrier()
@triton.jit
def _pointer(W, layer, slot: tl.constexpr, DT: tl.constexpr):
return tl.load(W + layer * 40 + slot).to(tl.pointer_type(DT))
@triton.jit
def _gemv(X, Q, Scale, Zero, n, K: tl.constexpr, N: tl.constexpr, BN: tl.constexpr):
"""Stream one group at a time and reduce without materializing any weights."""
kk = tl.arange(0, 128)
acc = tl.full((128, BN), 0, tl.float32)
for g in range(K // 128):
k = g * 128 + kk
packed = tl.load(Q + (k[:, None] // 2) * N + n[None, :], n[None, :] < N, 0)
iq = (packed >> ((k[:, None] & 1) * 4)) & 15
s = tl.load(Scale + g * N + n, n < N, 0).to(tl.float32)
z = tl.load(Zero + g * N + n, n < N, 0).to(tl.float32)
wt = ((iq.to(tl.float32) - z[None, :]) * s[None, :]).to(tl.bfloat16).to(tl.float32)
x = tl.load(X + k).to(tl.float32)
acc += x[:, None] * wt
return tl.sum(acc, 0)
@triton.jit
def _norm(Hidden, X, Weight):
d = tl.arange(0, 4096)
h = tl.load(Hidden + d, d < 2304, 0).to(tl.float32)
w = tl.load(Weight + d, d < 2304, 0).to(tl.float32)
inv = tl.rsqrt(tl.sum(h * h, 0) / 2304 + 1.e-6)
tl.store(X + d, (h * inv * w).to(tl.bfloat16).to(tl.float32), d < 2304)
@triton.jit
def _mega(Hin, Hout, W, Counter, Work,
S0, CQ0, CK0, CV0, S1, CQ1, CK1, CV1, S2, CQ2, CK2, CV2,
Cold, Rold, Cnew, Rnew, L,
E: tl.constexpr, GRID: tl.constexpr, BN: tl.constexpr):
pid = tl.program_id(0)
# Work is fp32 scratch, allocated once per model. Distinct phase lifetimes
# allow these arrays to be reused across all four layers.
X = Work
A = Work + 4096
B = Work + 20480
O = Work + 20544
Idx = Work + 24640
RW = Work + 24672
FF = Work + 24704
FO = Work + 33920
Qlatent = Work + 54656
Parts = Work + 71040
Latent = Work + 137088
if pid == 0:
d = tl.arange(0, 4096)
tl.store(Hout + d, tl.load(Hin + d, d < 2304, 0), d < 2304)
_barrier(Counter, GRID)
for layer in range(4):
if pid == 0:
_norm(Hout, X, _pointer(W, layer, 0, tl.bfloat16))
_barrier(Counter, GRID)
if layer < 3:
if layer == 0:
S, CQ, CK, CV = S0, CQ0, CK0, CV0
elif layer == 1:
S, CQ, CK, CV = S1, CQ1, CK1, CV1
else:
S, CQ, CK, CV = S2, CQ2, CK2, CV2
for task in range(pid, 4 * (4096 // BN), GRID):
which = task // (4096 // BN)
n = (task % (4096 // BN)) * BN + tl.arange(0, BN)
# Projection slots 2,5,8,11. Runtime selection keeps one body.
qp = tl.load(W + layer * 40 + 2 + which * 3).to(tl.pointer_type(tl.uint8))
sp = tl.load(W + layer * 40 + 3 + which * 3).to(tl.pointer_type(tl.bfloat16))
zp = tl.load(W + layer * 40 + 4 + which * 3).to(tl.pointer_type(tl.bfloat16))
val = _gemv(X, qp, sp, zp, n, 2304, 4096, BN).to(tl.bfloat16).to(tl.float32)
if which < 3:
if which == 0:
C = CQ
elif which == 1:
C = CK
else:
C = CV
cw = _pointer(W, layer, 18, tl.bfloat16) + which * 4096 * 4
c0 = tl.load(C + n).to(tl.float32)
c1 = tl.load(C + 4096 + n).to(tl.float32)
c2 = tl.load(C + 8192 + n).to(tl.float32)
y = c0 * tl.load(cw + n * 4).to(tl.float32)
y += c1 * tl.load(cw + n * 4 + 1).to(tl.float32)
y += c2 * tl.load(cw + n * 4 + 2).to(tl.float32)
y += val * tl.load(cw + n * 4 + 3).to(tl.float32)
tl.store(C + n, c1)
tl.store(C + 4096 + n, c2)
tl.store(C + 8192 + n, val)
val = (y / (1 + tl.exp(-y))).to(tl.bfloat16).to(tl.float32)
else:
val = 1 / (1 + tl.exp(val))
tl.store(A + which * 4096 + n, val)
if pid < 32:
d = tl.arange(0, 4096)
bp = _pointer(W, layer, 17, tl.bfloat16)
x = tl.load(X + d, d < 2304, 0)
b = tl.load(bp + pid * 2304 + d, d < 2304, 0).to(tl.float32)
bv = tl.sum(x * b, 0).to(tl.bfloat16).to(tl.float32)
tl.store(B + pid, 1 / (1 + tl.exp(-bv)))
_barrier(Counter, GRID)
# Independent state columns: each worker owns 32 value channels.
for task in range(pid, 128, GRID):
head = task // 4
ki = tl.arange(0, 128)
vi = (task % 4) * 32 + tl.arange(0, 32)
q = tl.load(A + head * 128 + ki) * (128 ** -0.5)
k = tl.load(A + 4096 + head * 128 + ki)
v = tl.load(A + 8192 + head * 128 + vi)
decay = tl.load(A + 12288 + head * 128 + ki)
beta = tl.load(B + head)
address = S + head * 16384 + ki[:, None] * 128 + vi[None, :]
sv = tl.load(address) * decay[:, None]
pred = tl.sum(sv * k[:, None], 0)
sv += beta * k[:, None] * (v - pred)[None, :]
tl.store(address, sv)
out = tl.sum(sv * q[:, None], 0).to(tl.bfloat16).to(tl.float32)
tl.store(O + head * 128 + vi, out)
_barrier(Counter, GRID)
else:
# Query and current compressed KV projections.
for task in range(pid, triton.cdiv(6144, BN) + triton.cdiv(576, BN), GRID):
if task < 6144 // BN:
n = task * BN + tl.arange(0, BN)
val = _gemv(X, _pointer(W, layer, 2, tl.uint8),
_pointer(W, layer, 3, tl.bfloat16), _pointer(W, layer, 4, tl.bfloat16),
n, 2304, 6144, BN).to(tl.bfloat16).to(tl.float32)
tl.store(A + n, val)
else:
n = (task - 6144 // BN) * BN + tl.arange(0, BN)
val = _gemv(X, _pointer(W, layer, 5, tl.uint8),
_pointer(W, layer, 6, tl.bfloat16), _pointer(W, layer, 7, tl.bfloat16),
n, 2304, 576, BN).to(tl.bfloat16).to(tl.float32)
tl.store(B + n, val, n < 576)
# Copy the fed caches, including when they came from another model.
for t in range(pid * 1024, L * 512, GRID * 1024):
ix = t + tl.arange(0, 1024)
tl.store(Cnew + ix, tl.load(Cold + ix, ix < L * 512, 0), ix < L * 512)
for t in range(pid * 1024, L * 64, GRID * 1024):
ix = t + tl.arange(0, 1024)
tl.store(Rnew + ix, tl.load(Rold + ix, ix < L * 64, 0), ix < L * 64)
_barrier(Counter, GRID)
if pid == 0:
r = tl.arange(0, 512)
tl.store(Cnew + L * 512 + r, tl.load(B + r))
if pid < 32:
r = tl.arange(0, 32)
angle = L * tl.exp(-tl.log(10000.) * (2 * r / 64.))
co, si = tl.cos(angle), tl.sin(angle)
qe = tl.load(A + pid * 192 + 128 + r * 2)
qo = tl.load(A + pid * 192 + 129 + r * 2)
tl.store(A + pid * 192 + 128 + r * 2, (qe * co - qo * si).to(tl.bfloat16).to(tl.float32))
tl.store(A + pid * 192 + 129 + r * 2, (qo * co + qe * si).to(tl.bfloat16).to(tl.float32))
if pid == 0:
ke, ko = tl.load(B + 512 + 2 * r), tl.load(B + 513 + 2 * r)
tl.store(Rnew + L * 64 + 2 * r, ke * co - ko * si)
tl.store(Rnew + L * 64 + 2 * r + 1, ko * co + ke * si)
# Absorb W_k into each head's query, without storing W_k.
for task in range(pid, 128, GRID):
head = task // 4
k = (task % 4) * 128 + tl.arange(0, 128)
n = head * 256 + tl.arange(0, 128)
qp = _pointer(W, layer, 8, tl.uint8)
sp = _pointer(W, layer, 9, tl.bfloat16)
zp = _pointer(W, layer, 10, tl.bfloat16)
packed = tl.load(qp + (k[:, None] // 2) * 8192 + n[None, :])
iq = (packed >> ((k[:, None] & 1) * 4)) & 15
sc = tl.load(sp + (k[:, None] // 128) * 8192 + n[None, :]).to(tl.float32)
ze = tl.load(zp + (k[:, None] // 128) * 8192 + n[None, :]).to(tl.float32)
wt = ((iq.to(tl.float32) - ze) * sc).to(tl.bfloat16).to(tl.float32)
q = tl.load(A + head * 192 + tl.arange(0, 128))
ql = tl.sum(wt * q[None, :], 1)
tl.store(Qlatent + head * 512 + k, ql)
_barrier(Counter, GRID)
# Four independent ranges per head, online softmax in latent space.
for task in range(pid, 128, GRID):
head, split = task // 4, task % 4
d = tl.arange(0, 512)
rr = tl.arange(0, 64)
ql = tl.load(Qlatent + head * 512 + d)
qr = tl.load(A + head * 192 + 128 + rr)
m = tl.full((), -float('inf'), tl.float32)
den = tl.full((), 0, tl.float32)
acc = tl.full((512,), 0, tl.float32)
chunks = tl.cdiv(L + 1, 4 * 32)
for block in range(chunks):
tok = (split * chunks + block) * 32 + tl.arange(0, 32)
c = tl.load(Cnew + tok[:, None] * 512 + d[None, :], tok[:, None] <= L, 0).to(tl.float32)
kr = tl.load(Rnew + tok[:, None] * 64 + rr[None, :], tok[:, None] <= L, 0).to(tl.float32)
score = (tl.sum(c * ql[None, :], 1) + tl.sum(kr * qr[None, :], 1)) * (192 ** -0.5)
score = tl.where(tok <= L, score, -float('inf'))
nm = tl.maximum(m, tl.max(score, 0))
alpha = tl.exp(m - nm)
p = tl.exp(score - nm)
acc = acc * alpha + tl.sum(c * p[:, None], 0)
den = den * alpha + tl.sum(p, 0)
m = nm
tl.store(Parts + task * 516 + d, acc)
tl.store(Parts + task * 516 + 512, den)
tl.store(Parts + task * 516 + 513, m)
_barrier(Counter, GRID)
if pid < 32:
splits = tl.arange(0, 4)
d = tl.arange(0, 512)
mm = tl.load(Parts + (pid * 4 + splits) * 516 + 513)
dd = tl.load(Parts + (pid * 4 + splits) * 516 + 512)
factor = tl.exp(mm - tl.max(mm, 0))
av = tl.load(Parts + (pid * 4 + splits[:, None]) * 516 + d[None, :])
out = tl.sum(av * factor[:, None], 0) / tl.sum(dd * factor, 0)
tl.store(Latent + pid * 512 + d, out)
_barrier(Counter, GRID)
for task in range(pid, 4096 // BN, GRID):
head = task // (128 // BN)
n = head * 256 + 128 + (task % (128 // BN)) * BN + tl.arange(0, BN)
val = _gemv(Latent + head * 512, _pointer(W, layer, 8, tl.uint8),
_pointer(W, layer, 9, tl.bfloat16), _pointer(W, layer, 10, tl.bfloat16),
n, 512, 8192, BN).to(tl.bfloat16).to(tl.float32)
tl.store(O + task * BN + tl.arange(0, BN), val)
_barrier(Counter, GRID)
# Output projection, residual, and second RMS normalization.
for task in range(pid, triton.cdiv(2304, BN), GRID):
n = task * BN + tl.arange(0, BN)
val = _gemv(O, _pointer(W, layer, 14, tl.uint8),
_pointer(W, layer, 15, tl.bfloat16), _pointer(W, layer, 16, tl.bfloat16),
n, 4096, 2304, BN).to(tl.bfloat16).to(tl.float32)
h = tl.load(Hout + n, n < 2304, 0).to(tl.float32)
tl.store(Hout + n, h + val, n < 2304)
_barrier(Counter, GRID)
if pid == 0:
_norm(Hout, X, _pointer(W, layer, 1, tl.bfloat16))
_barrier(Counter, GRID)
# Tiny bf16 router, rounded like nn.Linear in the oracle.
for expert in range(pid, E, GRID):
d = tl.arange(0, 4096)
x = tl.load(X + d, d < 2304, 0)
r = tl.load(_pointer(W, layer, 19, tl.bfloat16) + expert * 2304 + d, d < 2304, 0).to(tl.float32)
tl.store(B + expert, tl.sum(x * r, 0).to(tl.bfloat16).to(tl.float32))
_barrier(Counter, GRID)
if pid == 0:
r = tl.arange(0, triton.next_power_of_2(E))
logits = tl.load(B + r, r < E, -float('inf'))
maximum = tl.max(logits, 0)
chosen = tl.full((8,), 0, tl.float32)
ar = tl.arange(0, 8)
for j in tl.static_range(8):
best = tl.max(logits, 0)
ix = tl.min(tl.where(logits == best, r, 2147483647), 0)
tl.store(Idx + j, ix)
chosen = tl.where(ar == j, tl.exp(best - maximum), chosen)
logits = tl.where(r == ix, -float('inf'), logits)
weights = chosen / tl.sum(chosen, 0) * 2.446
tl.store(RW + ar, weights)
_barrier(Counter, GRID)
for task in range(pid, 9 * (1024 // BN), GRID):
selected = task // (1024 // BN)
n = (task % (1024 // BN)) * BN + tl.arange(0, BN)
if selected < 8:
ix = tl.load(Idx + selected).to(tl.int32)
qg = _pointer(W, layer, 20, tl.uint8) + ix * (2304 // 2) * 1024
sg = _pointer(W, layer, 21, tl.bfloat16) + ix * 18 * 1024
zg = _pointer(W, layer, 22, tl.bfloat16) + ix * 18 * 1024
qu = _pointer(W, layer, 23, tl.uint8) + ix * (2304 // 2) * 1024
su = _pointer(W, layer, 24, tl.bfloat16) + ix * 18 * 1024
zu = _pointer(W, layer, 25, tl.bfloat16) + ix * 18 * 1024
else:
qg, sg, zg = _pointer(W, layer, 29, tl.uint8), _pointer(W, layer, 30, tl.bfloat16), _pointer(W, layer, 31, tl.bfloat16)
qu, su, zu = _pointer(W, layer, 32, tl.uint8), _pointer(W, layer, 33, tl.bfloat16), _pointer(W, layer, 34, tl.bfloat16)
gv = _gemv(X, qg, sg, zg, n, 2304, 1024, BN)
uv = _gemv(X, qu, su, zu, n, 2304, 1024, BN)
tl.store(FF + selected * 1024 + n, gv / (1 + tl.exp(-gv)) * uv)
_barrier(Counter, GRID)
for task in range(pid, 9 * triton.cdiv(2304, BN), GRID):
selected = task // triton.cdiv(2304, BN)
n = (task % triton.cdiv(2304, BN)) * BN + tl.arange(0, BN)
if selected < 8:
ix = tl.load(Idx + selected).to(tl.int32)
qd = _pointer(W, layer, 26, tl.uint8) + ix * 512 * 2304
sd = _pointer(W, layer, 27, tl.bfloat16) + ix * 8 * 2304
zd = _pointer(W, layer, 28, tl.bfloat16) + ix * 8 * 2304
else:
qd, sd, zd = _pointer(W, layer, 35, tl.uint8), _pointer(W, layer, 36, tl.bfloat16), _pointer(W, layer, 37, tl.bfloat16)
val = _gemv(FF + selected * 1024, qd, sd, zd, n, 1024, 2304, BN)
tl.store(FO + selected * 2304 + n, val, n < 2304)
_barrier(Counter, GRID)
for task in range(pid, triton.cdiv(2304, 128), GRID):
n = task * 128 + tl.arange(0, 128)
total = tl.full((128,), 0, tl.float32)
for j in tl.static_range(8):
total += tl.load(FO + j * 2304 + n, n < 2304, 0) * tl.load(RW + j)
total += tl.load(FO + 8 * 2304 + n, n < 2304, 0)
total = total.to(tl.bfloat16).to(tl.float32)
h = tl.load(Hout + n, n < 2304, 0).to(tl.float32)
tl.store(Hout + n, h + total, n < 2304)
_barrier(Counter, GRID)
class Model(nn.Module):
def __init__(self, cfg):
super().__init__()
self.cfg = cfg
self.blocks = nn.ModuleList(Block(cfg, k) for k in cfg.pattern)
self.register_buffer('_counter', torch.zeros(1, dtype=torch.int32), persistent=False)
self.register_buffer('_work', torch.empty(154000, dtype=torch.float32), persistent=False)
self.register_buffer('_weights', torch.empty(4, 40, dtype=torch.int64), persistent=False)
self._ready = False
def _prepare(self):
rows = []
for block in self.blocks:
a, m = block.attn, block.moe
row = [0] * 40
row[0], row[1] = block.attn_norm.data_ptr(), block.moe_norm.data_ptr()
def qset(slot, mod):
row[slot:slot + 3] = [mod.w_q.data_ptr(), mod.scales.data_ptr(), mod.zeros.data_ptr()]
qset(2, a.q_proj)
if isinstance(a, KDA):
qset(5, a.k_proj)
qset(8, a.v_proj)
qset(11, a.g_proj)
row[17], row[18] = a.beta_proj.weight.data_ptr(), a.conv_w.data_ptr()
else:
qset(5, a.kv_a)
qset(8, a.kv_b)
qset(14, a.o_proj)
row[19] = m.router.weight.data_ptr()
for slot, mod in zip((20, 23, 26, 29, 32, 35), (m.gate, m.up, m.down, m.s_gate, m.s_up, m.s_down)):
qset(slot, mod)
rows.append(row)
self._weights.copy_(torch.tensor(rows, dtype=torch.int64))
self._ready = True
def load_state_dict(self, state_dict, strict=True, assign=False):
result = super().load_state_dict(state_dict, strict=strict, assign=assign)
self._prepare()
return result
def _apply(self, fn, recurse=True):
result = super()._apply(fn, recurse)
self._ready = False
return result
@torch.no_grad()
def step(self, hidden, state):
if not self._ready:
self._prepare()
h = torch.empty_like(hidden)
oldc, oldr = state[3]['c_kv'], state[3]['k_rope']
length = oldc.shape[0]
newc = torch.empty((length + 1, 512), device=hidden.device, dtype=torch.bfloat16)
newr = torch.empty((length + 1, 64), device=hidden.device, dtype=torch.bfloat16)
_mega[(128,)](hidden, h, self._weights, self._counter, self._work,
state[0]['S'], state[0]['cq'], state[0]['ck'], state[0]['cv'],
state[1]['S'], state[1]['cq'], state[1]['ck'], state[1]['cv'],
state[2]['S'], state[2]['cq'], state[2]['ck'], state[2]['cv'],
oldc, oldr, newc, newr, length,
E=self.cfg.n_experts, GRID=128, BN=32, num_warps=4, enable_fp_fusion=False)
state[3]['c_kv'], state[3]['k_rope'] = newc, newr
return h, state
20260930_115311_codex_gpt-6.1-sol_02_kimi_linear_decode