KernelBench hard · B200

W4A16 GEMM GLM-5.2

passdid not score
harnesszai-claudeagent session1h 40mtotal wall1h 45mcheck3mbenchmark2moutput tokens226,029gpu-lock wait4mgpu-lock held89sregimememory

Per-shape vs governing ceilingeach shape graded against whichever binds — bf16 compute or HBM bandwidth

1×12288×40960.048 ms6.9%0.56 TB/s · 7% of 8.0 TB/s HBM · also 2 TFLOPS (0% of compute)
32×12288×40960.055 ms6.4%0.51 TB/s · 6% of 8.0 TB/s HBM · also 59 TFLOPS (3% of compute)
256×12288×40960.169 ms2.6%152 TFLOPS · 7% of 2,250 TF bf16 peak · also 0.21 TB/s (3% of HBM)
1×4096×40960.040 ms2.8%0.22 TB/s · 3% of 8.0 TB/s HBM · also 1 TFLOPS (0% of compute)
16×14336×40960.048 ms8.2%0.66 TB/s · 8% of 8.0 TB/s HBM · also 39 TFLOPS (2% of compute)

compute-bound memory-bound · bar + right column = official fraction of the ceiling (the geomean input)

geomean(6.9% · 6.4% · 2.6% · 2.8% · 8.2%) = 4.8%

Kernel source (redacted)
"""W4A16 weight-only int4 quantized GEMM for B200 (SM100, Blackwell).

Fused int4 unpack + per-group dequant + GEMM in Triton. AWQ/GPTQ-style asymmetric
int4 with explicit bf16 zero-points and per-group bf16 scales, group size 128.

Weight packing: w_q is (K//2, N) uint8; two int4 per byte, low nibble = even-K
row, high nibble = odd-K row.

Dequant (cvt-free via bf16 bitcast magic): zero-points are integers 0..15, so
  raw   = bitcast_bf16(0x4300 | nibble) = 128 + nibble   (exact)
  z_adj = bitcast_bf16(0x4300 | z)      = 128 + z         (exact)
  w_bf  = (raw - z_adj) * scale                            (exact integer diff)
The integer subtraction at magnitude ~135 is exact in bf16, so no fp cvt is
needed for the unpack -- only free bitcasts.
"""
from __future__ import annotations

import torch
import torch.nn as nn
import triton
import triton.language as tl

GROUP_SIZE = 128


def _configs():
    cfgs = []
    for bm in (16, 32, 64, 128):
        for bn in (64, 128, 256):
            for nw in (4, 8):
                for ns in (3, 4):
                    cfgs.append(
                        triton.Config({"BLOCK_M": bm, "BLOCK_N": bn, "BLOCK_K": 128},
                                      num_warps=nw, num_stages=ns)
                    )
    return cfgs


@triton.autotune(configs=_configs(), key=["M", "N", "K"])
@triton.jit
def w4a16_gemm_kernel(
    x_ptr, wq_ptr, scales_ptr, zeros_ptr, out_ptr,
    M, N, K,
    stride_xm, stride_xk,
    stride_wkh, stride_wn,
    stride_sg, stride_sn,
    stride_om, stride_on,
    BLOCK_M: tl.constexpr, BLOCK_N: tl.constexpr, BLOCK_K: tl.constexpr,
    GROUP_SIZE_K: tl.constexpr,
    GROUP_M: tl.constexpr = 8,
):
    pid = tl.program_id(0)
    num_pid_m = tl.cdiv(M, BLOCK_M)
    num_pid_n = tl.cdiv(N, BLOCK_N)
    num_pid_in_group = GROUP_M * num_pid_n
    group_id = pid // num_pid_in_group
    first_pid_m = group_id * GROUP_M
    group_size_m = min(num_pid_m - first_pid_m, GROUP_M)
    pid_m = first_pid_m + (pid % group_size_m)
    pid_n = (pid % num_pid_in_group) // group_size_m

    rm = pid_m * BLOCK_M + tl.arange(0, BLOCK_M)
    rn = pid_n * BLOCK_N + tl.arange(0, BLOCK_N)
    rk = tl.arange(0, BLOCK_K)
    BK_HALF: tl.constexpr = BLOCK_K // 2
    rkh = tl.arange(0, BK_HALF)

    m_mask = rm < M
    n_mask = rn < N

    acc = tl.zeros((BLOCK_M, BLOCK_N), dtype=tl.float32)
    x_rm = x_ptr + rm[:, None] * stride_xm
    w_rn = wq_ptr + rn[None, :] * stride_wn

    for ki in range(0, K, BLOCK_K):
        g_idx = ki // GROUP_SIZE_K

        x = tl.load(x_rm + (ki + rk)[None, :] * stride_xk, mask=m_mask[:, None], other=0.0)
        x2 = tl.reshape(x, (BLOCK_M, BK_HALF, 2))
        x_even, x_odd = tl.split(x2)

        kh = (ki // 2) + rkh
        w_packed = tl.load(w_rn + kh[:, None] * stride_wkh, mask=n_mask[None, :], other=0)
        raw_lo = tl.cast((w_packed & 0xF).to(tl.uint16) | 0x4300, tl.bfloat16, bitcast=True)
        raw_hi = tl.cast(((w_packed >> 4) & 0xF).to(tl.uint16) | 0x4300, tl.bfloat16, bitcast=True)

        z = tl.load(zeros_ptr + g_idx * stride_sg + rn * stride_sn, mask=n_mask, other=0.0)
        s = tl.load(scales_ptr + g_idx * stride_sg + rn * stride_sn, mask=n_mask, other=0.0)
        z_adj = tl.cast(z.to(tl.uint16) | 0x4300, tl.bfloat16, bitcast=True)

        w_lo = (raw_lo - z_adj[None, :]) * s[None, :]
        w_hi = (raw_hi - z_adj[None, :]) * s[None, :]

        acc += tl.dot(x_even, w_lo)
        acc += tl.dot(x_odd, w_hi)

    out_ptrs = out_ptr + rm[:, None] * stride_om + rn[None, :] * stride_on
    tl.store(out_ptrs, acc.to(tl.bfloat16), mask=m_mask[:, None] & n_mask[None, :])


class Model(nn.Module):
    """W4A16 GEMM: y = x @ dequant(w_q, scales, zeros)."""

    def __init__(self, M: int, N: int, K: int, group_size: int = GROUP_SIZE):
        super().__init__()
        self.M, self.N, self.K = M, N, K
        self.group_size = group_size
        n_groups = K // group_size
        self.register_buffer("w_q", torch.zeros(K // 2, N, dtype=torch.uint8))
        self.register_buffer("scales", torch.zeros(n_groups, N, dtype=torch.bfloat16))
        self.register_buffer("zeros", torch.zeros(n_groups, N, dtype=torch.bfloat16))

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        x = x.contiguous()
        M = x.shape[0]
        N, K = self.N, self.K
        out = torch.empty((M, N), dtype=torch.bfloat16, device=x.device)
        grid = lambda meta: (triton.cdiv(M, meta["BLOCK_M"]) * triton.cdiv(N, meta["BLOCK_N"]),)
        w4a16_gemm_kernel[grid](
            x, self.w_q, self.scales, self.zeros, out,
            M, N, K,
            x.stride(0), x.stride(1),
            self.w_q.stride(0), self.w_q.stride(1),
            self.scales.stride(0), self.scales.stride(1),
            out.stride(0), out.stride(1),
            GROUP_SIZE_K=self.group_size,
        )
        return out


M = 1
N = 12288
K = 4096


def get_inputs():
    x = torch.randn(M, K, dtype=torch.bfloat16)
    return [x]


def get_init_inputs():
    return [M, N, K]

20260620_130026_zai-claude_glm-5.2_07_w4a16_gemm