KernelBench hard · H100
TopK Bitonic Kimi K3 (1M)
wrongdid not score
harnesskinetic-claudeagent session2h 3mtotal wall2h 7mcheck3mbenchmark—output tokens146,120cost$36.97gpu-lock wait50mgpu-lock held6mregimememory
Per-shape vs governing ceilingeach shape graded against whichever binds — fp32 compute or HBM bandwidth
No per-shape benchmark data archived for this run.
Kernel source (redacted)
"""Top-k via radix-filter + register-resident compaction (custom CUDA kernels).
fp32 2D input -> top-k (values desc, int64 indices) over the last dim.
Algorithm
---------
1. Histogram phase: map fp32 to order-preserving uint32, take top 11 bits as a
bin (2048 bins). Per-row histogram tells us which bin the k-th largest
falls into (tau). All elements with bin >= tau form a candidate superset of
the true top-k. Exact for any input; ties only inflate the candidate set.
2. Compaction phase: warp-ballot + prefix scans emit candidates contiguously
(no atomic hot-spot); candidates stay register-resident until written.
3. Selection phase: an exact truncated bitonic network in shared memory takes
the top-k2 (k2 = pow2 >= k) of the (usually tiny) candidate set.
4. Multi-chunk rows (n > 16384) run a 3-kernel pipeline: K1 histogram, K2
filter+local top-k2 per chunk, K3 merge sorted chunk lists.
Same contract as the framework top-k op (largest=True, sorted=True).
"""
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline
_CUDA_SRC = r"""
#include <torch/extension.h>
#include <ATen/cuda/CUDAContext.h>
#include <cuda_runtime.h>
#include <math_constants.h>
namespace {
#define FULLMASK 0xffffffffu
#define NEG_INF (-CUDART_INF_F)
__device__ __forceinline__ unsigned map_key(float v) {
unsigned u = __float_as_uint(v);
return (u & 0x80000000u) ? ~u : (u | 0x80000000u);
}
__device__ __forceinline__ void hist_add(unsigned* hist, float v) {
atomicAdd(&hist[map_key(v) >> 21], 1u);
}
__device__ __forceinline__ bool key_before(float va, int ia, float vb, int ib) {
return (va > vb) || (va == vb && ia < ib);
}
__device__ __forceinline__ void cswap(float* val, int* idx, int i, int j, bool desc) {
float vi = val[i], vj = val[j];
int ii = idx[i], ij = idx[j];
bool i_better = (vi > vj) || (vi == vj && ii < ij);
bool swap = (i_better != desc);
if (swap) { val[i] = vj; idx[i] = ij; val[j] = vi; idx[j] = ii; }
}
__device__ __forceinline__ int ilog2(int x) { return 31 - __clz(x); }
// ---------------------------------------------------------------------------
// Parallel tau seek: locate the smallest bin b with sum_{h>=b} hist[h] >= k.
// All warps participate; ~3 short stages.
// ---------------------------------------------------------------------------
__device__ int seek_tau_parallel(const unsigned* hist, int* scratch, int k, int tid) {
const int nwarps = blockDim.x >> 5;
const int wid = tid >> 5;
const int lane = tid & 31;
const int S = 2048 / nwarps; // bins per warp (pow2, >= 64)
// A: per-warp slice totals
if (wid < nwarps) {
int base = wid * S;
unsigned c = 0;
for (int i = lane; i < S; i += 32) c += hist[base + i];
#pragma unroll
for (int off = 16; off > 0; off >>= 1) c += __shfl_down_sync(FULLMASK, c, off);
if (lane == 0) scratch[wid] = (int)c;
}
__syncthreads();
// B: warp 0 finds owning slice (from the top) and counts above it
if (wid == 0) {
// c_j = total of j-th slice from top
int myc = (lane < nwarps) ? scratch[nwarps - 1 - lane] : 0;
int pre = myc;
#pragma unroll
for (int off = 16; off > 0; off >>= 1) {
int t = __shfl_up_sync(FULLMASK, pre, off);
if (lane >= off) pre += t;
}
bool hit = pre >= k;
unsigned m = __ballot_sync(FULLMASK, hit);
int fl = m ? (__ffs(m) - 1) : 0; // first (top-most) slice reaching k
int acc_above = pre - myc; // counts strictly above owning slice
// broadcast owner + need
int aaf = __shfl_sync(FULLMASK, acc_above, fl);
if (lane == 0) scratch[32] = nwarps - 1 - fl; // owner warp id
if (lane == 1) scratch[33] = aaf; // counts above owner
}
__syncthreads();
const int owner = scratch[32];
const int acc0 = scratch[33];
// C: owning warp scans its slice from top
int result = 0;
if (wid == owner) {
int acc = acc0;
int base_hi = (owner + 1) * S; // one past slice end
for (int rounds = 0; rounds < S / 32; ++rounds) {
int hi = base_hi - 32 * rounds; // window (hi-32, hi]
int idx = hi - 32 + lane; // lane maps ascending bins
int c = (int)hist[idx];
// suffix sums (higher lanes = higher bins)
int suf = c;
#pragma unroll
for (int off = 16; off > 0; off >>= 1) suf += __shfl_down_sync(FULLMASK, suf, off);
int need = k - acc;
unsigned m = __ballot_sync(FULLMASK, suf >= need);
if (m) {
result = hi - 32 + (31 - __clz((int)m));
break;
}
acc += __shfl_sync(FULLMASK, suf, 0);
}
}
// broadcast result via scratch
if (wid == owner && lane == 0) scratch[34] = result;
__syncthreads();
return scratch[34];
}
// ---------------------------------------------------------------------------
// Truncated bitonic top-k: region of length 2^Llog (>= 2*k2) -> top-k2 sorted
// desc in [0, k2).
// ---------------------------------------------------------------------------
__device__ void block_topk(float* val, int* idx, int Llog, int k2log, int tid) {
const int L = 1 << Llog;
const int k2 = 1 << k2log;
const int T = blockDim.x;
const int m1 = 2 << k2log;
const int mmask = m1 - 1;
for (int sizelog = 1; sizelog <= k2log + 1; ++sizelog) {
for (int s = 1 << (sizelog - 1); s > 0; s >>= 1) {
for (int i = tid; i < L; i += T) {
if (i & s) continue;
bool desc = ((((i & mmask) >> sizelog) & 1) == 0);
cswap(val, idx, i, i + s, desc);
}
__syncthreads();
}
}
for (int mlog = k2log + 1; mlog < Llog; ++mlog) {
const int npair = L >> (mlog + 1);
const int items = npair << k2log;
for (int t = tid; t < items; t += T) {
int pair = t >> k2log;
int i = t & (k2 - 1);
int head = pair << (mlog + 1);
int a = head + i;
int b = head + (1 << mlog) + k2 - 1 - i;
float va = val[a], vb = val[b];
int ia = idx[a], ib = idx[b];
if (key_before(vb, ib, va, ia)) { val[a] = vb; idx[a] = ib; }
}
__syncthreads();
for (int s = k2 >> 1; s > 0; s >>= 1) {
for (int i = tid; i < items; i += T) {
int p = i & (k2 - 1);
if (p & s) continue;
int head = (i >> k2log) << (mlog + 1);
cswap(val, idx, head + p, head + p + s, true);
}
__syncthreads();
}
}
}
__device__ void merge_sorted_lists(float* val, int* idx, int Lflog, int k2log, int tid) {
const int k2 = 1 << k2log;
const int T = blockDim.x;
for (int mlog = k2log; mlog < Lflog; ++mlog) {
const int npair = 1 << (Lflog - mlog - 1);
const int items = npair << k2log;
for (int t = tid; t < items; t += T) {
int pair = t >> k2log;
int i = t & (k2 - 1);
int head = pair << (mlog + 1);
int a = head + i;
int b = head + (1 << mlog) + k2 - 1 - i;
float va = val[a], vb = val[b];
int ia = idx[a], ib = idx[b];
if (key_before(vb, ib, va, ia)) { val[a] = vb; idx[a] = ib; }
}
__syncthreads();
for (int s = k2 >> 1; s > 0; s >>= 1) {
for (int i = tid; i < items; i += T) {
int p = i & (k2 - 1);
if (p & s) continue;
int head = (i >> k2log) << (mlog + 1);
cswap(val, idx, head + p, head + p + s, true);
}
__syncthreads();
}
}
}
// ---------------------------------------------------------------------------
// Register-resident load + ballot compaction core (shared by fused & k2).
// Fills: v[] registers with chunk values, histograms them, then after tau is
// known compacts candidates to (pval, pidx). Returns candidate count in ctl[0]
// (smem). c0 = global index of chunk start.
// ---------------------------------------------------------------------------
template <int TpE>
struct ChunkRegs {
float v[TpE];
};
// global element index for register slot e (must match load_chunk mapping)
template <int TpE>
__device__ __forceinline__ int slot_gidx(int e, int tid, int T, int c0, bool vectorizable) {
if (vectorizable) {
int j = e >> 2, sp = e & 3;
return c0 + (tid + j * T) * 4 + sp;
}
return c0 + tid + e * T;
}
template <int TpE>
__device__ __forceinline__ void load_chunk(const float* __restrict__ xrow, int clen,
ChunkRegs<TpE>& r, int tid, int T, int c0,
bool vectorizable) {
if (vectorizable) {
const float4* x4 = reinterpret_cast<const float4*>(xrow);
#pragma unroll
for (int j = 0; j < TpE / 4; ++j) {
int base = (tid + j * T) * 4;
if (base + 3 < clen) {
float4 t = x4[tid + j * T];
r.v[4*j] = t.x; r.v[4*j+1] = t.y; r.v[4*j+2] = t.z; r.v[4*j+3] = t.w;
} else {
#pragma unroll
for (int s = 0; s < 4; ++s) {
int g = base + s;
r.v[4*j+s] = (g < clen) ? xrow[g] : NEG_INF;
}
}
}
} else {
#pragma unroll
for (int e = 0; e < TpE; ++e) {
int g = tid + e * T;
r.v[e] = (g < clen) ? xrow[g] : NEG_INF;
}
}
}
// after tau known: emit candidates to smem pairs; returns via ctl[0]
template <int TpE>
__device__ __forceinline__ void compact_candidates(ChunkRegs<TpE>& r, int tau_bin,
float* pval, int* pidx, int* ctl,
int tid, int T, int c0, bool vectorizable) {
const int lane = tid & 31;
const int lt = (1 << lane) - 1;
// pass 1: warp count
int cnt = 0;
#pragma unroll
for (int e = 0; e < TpE; ++e)
cnt += ((int)(map_key(r.v[e]) >> 21) >= tau_bin) ? 1 : 0;
#pragma unroll
for (int off = 16; off > 0; off >>= 1) cnt += __shfl_down_sync(FULLMASK, cnt, off);
__shared__ int wbase[32];
if (lane == 0) wbase[tid >> 5] = atomicAdd(&ctl[0], cnt);
__syncthreads();
int base = wbase[tid >> 5];
// pass 2: emit (intra-warp order via ballots)
int run = 0;
#pragma unroll
for (int e = 0; e < TpE; ++e) {
bool cand = (int)(map_key(r.v[e]) >> 21) >= tau_bin;
unsigned m = __ballot_sync(FULLMASK, cand);
if (cand) {
int pos = base + run + __popc(m & lt);
pval[pos] = r.v[e];
pidx[pos] = slot_gidx<TpE>(e, tid, T, c0, vectorizable);
}
run += __popc(m);
}
}
// ---------------------------------------------------------------------------
// Fused kernel: one block per row.
// smem: hist 2048*4 + ctl 4*4 + pairs L*8
// ---------------------------------------------------------------------------
template <int TpE>
__global__ void fused_kernel(const float* __restrict__ x,
float* __restrict__ out_v, long long* __restrict__ out_i,
int n, int k, int Llog, int k2log, int vect) {
extern __shared__ float smem[];
const int tid = threadIdx.x;
const int row = blockIdx.x;
const int row_g = tid; // dummy
(void)row_g;
const int T = blockDim.x;
const int L = 1 << Llog;
const int k2 = 1 << k2log;
unsigned* shist = reinterpret_cast<unsigned*>(smem);
int* sctl = reinterpret_cast<int*>(smem + 2048); // [0]=counter [1]=tau
int* sscratch = sctl + 4; // 40 ints seek scratch
float* pval = smem + 2048 + 44;
int* pidx = reinterpret_cast<int*>(pval + L);
const int clen = min(L, n);
const float* xrow = x + (long)row * n;
for (int i = tid; i < 2048 + 44; i += T) reinterpret_cast<unsigned*>(smem)[i] = 0;
__syncthreads();
ChunkRegs<TpE> r;
load_chunk<TpE>(xrow, clen, r, tid, T, 0, vect != 0);
#pragma unroll
for (int e = 0; e < TpE; ++e)
if (r.v[e] > NEG_INF) hist_add(shist, r.v[e]);
__syncthreads();
int tau = seek_tau_parallel(shist, sscratch, k, tid);
__syncthreads();
compact_candidates<TpE>(r, tau, pval, pidx, sctl, tid, T, 0, vect != 0);
__syncthreads();
const int c = sctl[0];
int rlog = c <= 1 ? 0 : ilog2(c - 1) + 1;
rlog = max(rlog, k2log + 1);
const int rlen = 1 << rlog;
for (int i = c + tid; i < rlen; i += T) { pval[i] = NEG_INF; pidx[i] = 0x7fffffff; }
__syncthreads();
if (c > 0) block_topk(pval, pidx, rlog, k2log, tid);
for (int j = tid; j < k; j += T) {
out_v[(long)row * k + j] = (c > 0) ? pval[j] : NEG_INF;
out_i[(long)row * k + j] = (c > 0) ? (long long)pidx[j] : 0;
}
}
// ---------------------------------------------------------------------------
// Piped: K1 histogram (deterministic partial hists, no atomics on gmem)
// ---------------------------------------------------------------------------
__global__ void k1_hist(const float* __restrict__ x, unsigned* __restrict__ parts,
int n, int Cb, int Llog, int vect) {
__shared__ unsigned shist[2048];
const int tid = threadIdx.x;
const int row = blockIdx.y;
const int chunk = blockIdx.x;
const int L = 1 << Llog;
const int c0 = chunk * L;
const int clen = min(c0 + L, n) - c0;
const float* xrow = x + (long)row * n + c0;
for (int i = tid; i < 2048; i += blockDim.x) shist[i] = 0;
__syncthreads();
if (vect) {
const float4* x4 = reinterpret_cast<const float4*>(xrow);
const int c4 = clen >> 2;
for (int i = tid; i < c4; i += blockDim.x) {
float4 v = x4[i];
hist_add(shist, v.x); hist_add(shist, v.y); hist_add(shist, v.z); hist_add(shist, v.w);
}
for (int i = (c4 << 2) + tid; i < clen; i += blockDim.x) hist_add(shist, xrow[i]);
} else {
for (int i = tid; i < clen; i += blockDim.x) hist_add(shist, xrow[i]);
}
__syncthreads();
unsigned* out = parts + ((long)row * Cb + chunk) * 2048;
for (int i = tid; i < 2048; i += blockDim.x) out[i] = shist[i];
}
// Piped: K2 reduce hists, seek tau, filter chunk, local top-k2 -> scratch
template <int TpE>
__global__ void k2_filter(const float* __restrict__ x, const unsigned* __restrict__ parts,
float* __restrict__ ws_v, int* __restrict__ ws_i,
int n, int k, int Cb, int Llog, int k2log, int vect) {
extern __shared__ float smem[];
const int tid = threadIdx.x;
const int row = blockIdx.y;
const int chunk = blockIdx.x;
const int T = blockDim.x;
const int L = 1 << Llog;
const int k2 = 1 << k2log;
unsigned* shist = reinterpret_cast<unsigned*>(smem);
int* sctl = reinterpret_cast<int*>(smem + 2048);
int* sscratch = sctl + 4;
float* pval = smem + 2048 + 44;
int* pidx = reinterpret_cast<int*>(pval + L);
const unsigned* rowparts = parts + (long)row * Cb * 2048;
for (int i = tid; i < 2048 + 44; i += T) {
unsigned s = 0;
if (i < 2048) {
for (int c = 0; c < Cb; ++c) s += rowparts[c * 2048 + i];
}
reinterpret_cast<unsigned*>(smem)[i] = s;
}
__syncthreads();
int tau = seek_tau_parallel(shist, sscratch, k, tid);
__syncthreads();
const int c0 = chunk * L;
const int clen = min(c0 + L, n) - c0;
const float* xrow = x + (long)row * n + c0;
ChunkRegs<TpE> r;
load_chunk<TpE>(xrow, clen, r, tid, T, c0, vect != 0);
compact_candidates<TpE>(r, tau, pval, pidx, sctl, tid, T, c0, vect != 0);
__syncthreads();
const int c = sctl[0];
int rlog = c <= 1 ? 0 : ilog2(c - 1) + 1;
rlog = max(rlog, k2log + 1);
const int rlen = 1 << rlog;
for (int i = c + tid; i < rlen; i += T) { pval[i] = NEG_INF; pidx[i] = 0x7fffffff; }
__syncthreads();
if (c > 0) block_topk(pval, pidx, rlog, k2log, tid);
const long slot = ((long)row * Cb + chunk) * k2;
for (int j = tid; j < k2; j += T) {
ws_v[slot + j] = (c > 0) ? pval[j] : NEG_INF;
ws_i[slot + j] = (c > 0) ? pidx[j] : 0x7fffffff;
}
}
// Piped: K3 merge per row -> outputs
__global__ void k3_merge(const float* __restrict__ ws_v, const int* __restrict__ ws_i,
float* __restrict__ out_v, long long* __restrict__ out_i,
int k, int Cb, int Lflog, int k2log) {
extern __shared__ float smem[];
const int tid = threadIdx.x;
const int row = blockIdx.x;
const int Lf = 1 << Lflog;
const int k2 = 1 << k2log;
float* sval = smem;
int* sidx = reinterpret_cast<int*>(smem + Lf);
const long base = (long)row * Cb * k2;
const int real = Cb * k2;
for (int i = tid; i < real; i += blockDim.x) { sval[i] = ws_v[base+i]; sidx[i] = ws_i[base+i]; }
for (int i = real + tid; i < Lf; i += blockDim.x) { sval[i] = NEG_INF; sidx[i] = 0x7fffffff; }
__syncthreads();
merge_sorted_lists(sval, sidx, Lflog, k2log, tid);
for (int j = tid; j < k; j += blockDim.x) {
out_v[(long)row * k + j] = sval[j];
out_i[(long)row * k + j] = (long long)sidx[j];
}
}
// ------------------------------ host --------------------------------------
int pow2ceil_h(int x) { int p = 1; while (p < x) p <<= 1; return p; }
int ilog2_h(int x) { return 31 - __builtin_clz(x); }
unsigned* g_parts = nullptr;
float* g_ws_v = nullptr;
int* g_ws_i = nullptr;
void ensure_workspace(int parts_words, int pair_elems, const at::TensorOptions& opt) {
static int parts_cap = 0, pair_cap = 0;
static std::vector<at::Tensor> keep;
if (parts_words > parts_cap) {
keep.push_back(at::empty({(long)parts_words}, opt.dtype(at::kInt)));
g_parts = reinterpret_cast<unsigned*>(keep.back().data_ptr<int>());
parts_cap = parts_words;
}
if (pair_elems > pair_cap) {
keep.push_back(at::empty({(long)pair_elems}, opt.dtype(at::kFloat)));
g_ws_v = keep.back().data_ptr<float>();
keep.push_back(at::empty({(long)pair_elems}, opt.dtype(at::kInt)));
g_ws_i = keep.back().data_ptr<int>();
pair_cap = pair_elems;
}
}
} // namespace
void init_ext() {
cudaFuncSetAttribute(fused_kernel<8>, cudaFuncAttributeMaxDynamicSharedMemorySize, 220 * 1024);
cudaFuncSetAttribute(fused_kernel<16>, cudaFuncAttributeMaxDynamicSharedMemorySize, 220 * 1024);
cudaFuncSetAttribute(k2_filter<8>, cudaFuncAttributeMaxDynamicSharedMemorySize, 220 * 1024);
cudaFuncSetAttribute(k2_filter<16>, cudaFuncAttributeMaxDynamicSharedMemorySize, 220 * 1024);
cudaFuncSetAttribute(k3_merge, cudaFuncAttributeMaxDynamicSharedMemorySize, 64 * 1024);
}
std::tuple<at::Tensor, at::Tensor> topk(const at::Tensor& x, int64_t k_in,
int64_t mode_ovr, int64_t Llog_ovr) {
const int B = (int)x.size(0);
const int N = (int)x.size(1);
const int k = (int)k_in;
const int k2 = pow2ceil_h(k);
const int k2log = ilog2_h(k2);
auto stream = at::cuda::getCurrentCUDAStream();
auto vals = at::empty({B, k_in}, x.options());
auto idxs = at::empty({B, k_in}, x.options().dtype(at::kLong));
const int vect = (N % 4 == 0) ? 1 : 0;
int Llog, mode;
if (N <= 16384) {
mode = 0;
Llog = ilog2_h(pow2ceil_h(N));
if (Llog < 10) Llog = 10;
} else {
mode = 1;
Llog = 13; // 8192 per chunk
}
if ((int)Llog_ovr > 0) {
Llog = (int)Llog_ovr;
mode = (((int64_t)N <= (1LL << Llog) && (int)mode_ovr == 0) || (int)mode_ovr != 1) && (int)mode_ovr == 0 ? 0 : 1;
}
if ((int)mode_ovr >= 0) mode = (int)mode_ovr;
if (mode == 0 && N > (1 << Llog)) mode = 1;
if (mode == 0) {
const int L = 1 << Llog;
const int smem = (2048 + 44) * 4 + L * 8;
if (Llog <= 12) {
fused_kernel<8><<<B, 512, smem, stream>>>(
x.data_ptr<float>(), vals.data_ptr<float>(),
(long long*)idxs.data_ptr<long>(), N, k, Llog, k2log, vect);
} else if (Llog == 13) {
fused_kernel<8><<<B, 1024, smem, stream>>>(
x.data_ptr<float>(), vals.data_ptr<float>(),
(long long*)idxs.data_ptr<long>(), N, k, Llog, k2log, vect);
} else {
fused_kernel<16><<<B, 1024, smem, stream>>>(
x.data_ptr<float>(), vals.data_ptr<float>(),
(long long*)idxs.data_ptr<long>(), N, k, Llog, k2log, vect);
}
return std::make_tuple(vals, idxs);
}
const int L = 1 << Llog;
const int Cb = (N + L - 1) / L;
ensure_workspace(B * Cb * 2048, B * Cb * k2, x.options());
dim3 grid(Cb, B);
k1_hist<<<grid, 512, 0, stream>>>(x.data_ptr<float>(), g_parts, N, Cb, Llog, vect);
const int smem2 = (2048 + 44) * 4 + L * 8;
if (Llog <= 12) {
k2_filter<8><<<grid, 512, smem2, stream>>>(
x.data_ptr<float>(), g_parts, g_ws_v, g_ws_i, N, k, Cb, Llog, k2log, vect);
} else {
k2_filter<16><<<grid, 512, smem2, stream>>>(
x.data_ptr<float>(), g_parts, g_ws_v, g_ws_i, N, k, Cb, Llog, k2log, vect);
}
const int Lf = pow2ceil_h(Cb * k2);
const int Lflog = ilog2_h(Lf);
k3_merge<<<B, 256, Lf * 8, stream>>>(
g_ws_v, g_ws_i, vals.data_ptr<float>(), (long long*)idxs.data_ptr<long>(),
k, Cb, Lflog, k2log);
return std::make_tuple(vals, idxs);
}
"""
_CPP_SRC = "void init_ext(); std::tuple<at::Tensor, at::Tensor> topk(const at::Tensor& x, int64_t k, int64_t mode_ovr, int64_t Llog_ovr);"
_ext = load_inline(
name="topk_radix2_ext",
cpp_sources=[_CPP_SRC],
cuda_sources=[_CUDA_SRC],
functions=["init_ext", "topk"],
extra_cuda_cflags=["-O3"],
verbose=False,
)
_ext.init_ext()
class Model(nn.Module):
def __init__(self, batch: int, n: int, k: int):
super().__init__()
self.k = int(k)
self.register_buffer("_dummy", torch.zeros(1))
self._fn = _ext.topk
def forward(self, x: torch.Tensor):
return self._fn(x, self.k, -1, -1)
__call__ = forward
batch = 64
n = 8192
k = 8
def get_inputs():
return [torch.randn(batch, n, dtype=torch.float32)]
def get_init_inputs():
return [batch, n, k]
20260716_145917_kinetic-claude_kinetic-0715_1m__05_topk_bitonic