KernelBench hard · H100
KDA CUTLASS LongCat 2.0
0.04%geomean peak fraction across shapes
manually audited: clean
harnesslongcat-claudeagent session6h 2mtotal wall6h 2mcheck16sbenchmark4soutput tokens489,381cost$82.84gpu-lock wait0sgpu-lock held20sregimecompute
Per-shape vs governing ceilingeach shape graded against whichever binds — bf16 compute or HBM bandwidth
2×1024×8×128×128×645.091 ms0.1%0.00 TB/s · 0% of 2.0 TB/s HBM · also 0 TFLOPS (0% of compute)
2×2048×8×128×128×647.750 ms0.1%0.01 TB/s · 0% of 2.0 TB/s HBM · also 1 TFLOPS (0% of compute)
1×4096×8×128×128×6412.445 ms0.1%0.00 TB/s · 0% of 2.0 TB/s HBM · also 0 TFLOPS (0% of compute)
1×2048×4×128×128×647.422 ms0.0%0.00 TB/s · 0% of 2.0 TB/s HBM · also 0 TFLOPS (0% of compute)
compute-bound memory-bound · bar + right column = official fraction of the ceiling (the geomean input)
geomean(0.1% · 0.1% · 0.1% · 0.0%) = 0.0%
Kernel source (redacted)
"""Kimi Delta Attention (KDA) forward, chunk form — batched PyTorch.
Reproduces fla/ops/kda chunk-parallel KDA forward without calling any FLA op.
Mirrors reference.py exactly; only the two structurally-sequential loops remain
(the intra-chunk triangular solve over BT=64 and the inter-chunk KxV state
recurrence over NT chunks), both batched over (B, H) so the heavy GEMMs hit
cuBLAS tensor cores on SM90.
Interface (per reference.py): Model, get_inputs, get_init_inputs.
"""
from __future__ import annotations
import torch
import torch.nn as nn
from einops import rearrange
OP_TYPE = "linear_attention"
SUPPORTED_PRECISIONS = ["bf16"]
HARDWARE_REQUIRED = ["RTX_PRO_6000", "H100", "B200"]
def _kda_fwd(
q: torch.Tensor,
k: torch.Tensor,
v: torch.Tensor,
g: torch.Tensor,
beta: torch.Tensor,
scale: float,
chunk_size: int = 64,
) -> torch.Tensor:
dtype = v.dtype
B, T, H, K = q.shape
V = v.shape[-1]
BT = chunk_size
NT = T // BT
q, k, v, g, beta = (x.to(torch.float32) for x in (q, k, v, g, beta))
q = q * scale
q = rearrange(q, "b (n c) h d -> b h n c d", c=BT)
k = rearrange(k, "b (n c) h d -> b h n c d", c=BT)
v = rearrange(v, "b (n c) h d -> b h n c d", c=BT)
g = rearrange(g, "b (n c) h d -> b h n c d", c=BT)
beta = rearrange(beta, "b (n c) h -> b h n c", c=BT)
g = g.cumsum(-2)
# Gated keys. A[c, i] = <kg_c, kgi_i>; Aqk[c, j] = <qg_c, kgi_j>.
kg = k * g.exp()
kgi = k * (-g).exp()
qg = q * g.exp()
# ---- Intra-chunk A: strict-lower K-K interaction (incl. diag masked) ----
A = torch.bmm(kg.reshape(-1, BT, K), kgi.reshape(-1, BT, K).transpose(-1, -2))
A = A.view(B, H, NT, BT, BT)
A = A * beta[:, :, :, :, None]
mask = torch.triu(torch.ones(BT, BT, device=q.device, dtype=torch.bool), diagonal=0)
A = -A.masked_fill(mask, 0)
for i in range(1, BT):
A[..., i, :i] += (A[..., i, :, None] * A[..., :, :i]).sum(-2)
A = (A + torch.eye(BT, device=q.device)) * beta[:, :, :, None, :]
# w = A @ (exp(g)*k), u = A @ v
ek = g.exp() * k
w = torch.bmm(A.reshape(-1, BT, BT), ek.reshape(-1, BT, K)).view(B, H, NT, BT, K)
u = torch.bmm(A.reshape(-1, BT, BT), v.reshape(-1, BT, V)).view(B, H, NT, BT, V)
# Aqk: inter-chunk q-k interaction, strict-upper masked.
Aqk = torch.bmm(qg.reshape(-1, BT, K), kgi.reshape(-1, BT, K).transpose(-1, -2))
Aqk = Aqk.view(B, H, NT, BT, BT)
mask_strict = torch.triu(torch.ones(BT, BT, device=q.device, dtype=torch.bool), diagonal=1)
Aqk = Aqk.masked_fill(mask_strict, 0)
# ---- Inter-chunk recurrence over the KxV state S ----
S = q.new_zeros(B, H, K, V)
o = torch.zeros_like(v)
for i in range(NT):
q_i, k_i, u_i, g_i, w_i = q[:, :, i], k[:, :, i], u[:, :, i], g[:, :, i], w[:, :, i]
aqk_i = Aqk[:, :, i]
v_i = u_i - w_i @ S
o[:, :, i] = qg[:, :, i] @ S + aqk_i @ v_i
S = S * g_i[:, :, -1].exp()[..., None]
S = S + ((g_i[:, :, -1:] - g_i).exp() * k_i).transpose(-1, -2) @ v_i
o = rearrange(o, "b h n c d -> b (n c) h d")
return o.to(dtype)
class Model(nn.Module):
"""KDA forward (chunk form). No learned parameters; all inputs are activations."""
def __init__(self, B: int, T: int, H: int, K: int, V: int, chunk_size: int = 64):
super().__init__()
self.B, self.T, self.H, self.K, self.V = B, T, H, K, V
self.chunk_size = chunk_size
self.scale = float(K) ** -0.5
self.register_buffer("_dummy", torch.zeros(1), persistent=False)
def forward(
self,
q: torch.Tensor,
k: torch.Tensor,
v: torch.Tensor,
g: torch.Tensor,
beta: torch.Tensor,
) -> torch.Tensor:
return _kda_fwd(q, k, v, g, beta, scale=self.scale, chunk_size=self.chunk_size)
B = 2
T = 1024
H = 8
K = 128
V = 128
CHUNK_SIZE = 64
def get_inputs():
torch.manual_seed(0)
q = torch.randn(B, T, H, K, dtype=torch.bfloat16) * 0.1
k = torch.randn(B, T, H, K, dtype=torch.bfloat16) * 0.1
v = torch.randn(B, T, H, V, dtype=torch.bfloat16) * 0.1
g = torch.randn(B, T, H, K, dtype=torch.float32) * 0.1 - 0.05
beta = torch.sigmoid(torch.randn(B, T, H, dtype=torch.bfloat16))
return [q, k, v, g, beta]
def get_init_inputs():
return [B, T, H, K, V, CHUNK_SIZE]
20260707_102426_longcat-claude_LongCat-2.0_02_kda_cutlass