Skip to content
KernelIndex
Search⌘K

submission 800261

graphdynamic · python · License unknown

Use it

Vendorable · source mirrored · license unknownView source →

No package. Vendor the mirrored source: 277 lines, June 9 Researcher Reciprocity License v1.0.

submission.py
curl "https://kernelindex.com/api/v1/implementations/kernelbot-qr-v2-800261?include=source"
interfacepython
Compatibility
measured onNVIDIA B200
declared hardwareNVIDIA B200
architecturessm_100
dtypesfp32

Benchmark evidence

1 measurement across 1 GPU, fastest first.

Operation / workload
Hardware
Latency
Rank
Observed
NVIDIA B200
7.01ms
#236 of 515
2026-06-15

Reported · How evidence levels are derived →

Source and license

sourceavailable
revision digestsha256:4f9b60335f24de41ccf2b68002c8bf24356ac9794ee5c63af20ba7f6586698a4
license declaredunknown
license concludedunknown
authorsgraphdynamic
imported2026-08-26

Techniques

Extracted from the mirrored source by pattern, never inferred. Each row cites its line.

shared-memoryextern __shared__ float sm[];

Kernel source

submission.py277 lines
"""v42 = v41 + baddbmm-fused trailing subtract + in-place V diag. v41 = v40 + allow_tf32(tensor-core GEMMs) + hoist eye + drop redundant self-assign. v40 = v35 + COLUMN-MAJOR shared panel (kills 16-way bank conflicts in norm/apply). v35 = v34 + alpha/beta diagonal RACE FIX (missing syncthreads). v34 — packing-4 (race-fixed) + DOUBLE reductions (fast AND accurate for high-cond). v31: with RACE FIX (compute all w_k -> sync -> update; found via compute-sanitizer on A100). v27/v29: apply (4 cols/reduction via separate registers; 4x fewer syncs). v27:+T moved to bmm + build_T kernel (removes in-kernel VtV reductions). v24: with per-size nb dispatch: nb=16 (n<=1024), nb=8 (n=2048,
where Householder beats geqrf), geqrf (n=4096). v20/v21 base: v15 (fewer per-panel reductions). v20 base: v15 (per-column apply, in-kernel VtV+T) with WARP-shuffle block reductions (no shared tree).
Isolates whether warp reductions are safe; if so -> correct faster Householder.

v15 base: batched blocked Householder QR with a SHARED-MEMORY panel kernel (B200 specialization).

The whole column-panel (rows [kk,n) x nb cols) is staged in the 228 KB shared memory; all the
reflector norms / within-panel applies / VtV / compact-WY T are computed against shared memory
(fast reductions, no global re-reads). Trailing update = 2 cuBLAS batched GEMMs. Panel fits in
shared for n<=1024 (m*nb*4 <= ~131 KB); n>=2048 -> geqrf fallback.
"""
import torch
from torch.utils.cpp_extension import load_inline

torch.backends.cuda.matmul.allow_tf32 = False

_CUDA_SRC = r"""
#include <torch/extension.h>
#include <cuda_runtime.h>

__device__ __forceinline__ float blkReduceSum(float v, float* s, int t, int nt) {
    for (int o = 16; o > 0; o >>= 1) v += __shfl_down_sync(0xffffffff, v, o);
    int warp = t >> 5, lane = t & 31, nwarps = nt >> 5;
    if (lane == 0) s[warp] = v;
    __syncthreads();
    if (t == 0) { float r = 0.f; for (int w = 0; w < nwarps; ++w) r += s[w]; s[0] = r; }
    __syncthreads();
    float r = s[0]; __syncthreads(); return r;
}


__device__ __forceinline__ void blkReduceSum4(float& a, float& b_, float& c, float& d, float* s, int t, int nt) {
    for (int o = 16; o > 0; o >>= 1) { a += __shfl_down_sync(0xffffffff, a, o); b_ += __shfl_down_sync(0xffffffff, b_, o);
        c += __shfl_down_sync(0xffffffff, c, o); d += __shfl_down_sync(0xffffffff, d, o); }
    int warp = t >> 5, lane = t & 31, nw = nt >> 5;
    if (lane == 0) { s[warp*4+0]=a; s[warp*4+1]=b_; s[warp*4+2]=c; s[warp*4+3]=d; }
    __syncthreads();
    if (t == 0) { double r0=0,r1=0,r2=0,r3=0; for (int w=0;w<nw;++w){ r0+=s[w*4+0]; r1+=s[w*4+1]; r2+=s[w*4+2]; r3+=s[w*4+3]; }
        s[0]=r0; s[1]=r1; s[2]=r2; s[3]=r3; }
    __syncthreads();
    a=s[0]; b_=s[1]; c=s[2]; d=s[3]; __syncthreads();
}

// One block per matrix. Panel = rows [kk,n) (m of them) x cols [kk,kk+nb). Staged in shared sP
// (row-major sP[r*nb + j], r in [0,m), j in [0,nb)). Emits V (back into M's lower), R diag, tau, T.
extern "C" __global__ void panel_qr_sh(float* __restrict__ Q, float* __restrict__ tau,
                                       int n, int kk, int nb) {
    const int b = blockIdx.x;
    float* M = Q + (long)b * n * n;
    float* tb = tau + (long)b * n;
    const int t = threadIdx.x, nt = blockDim.x;
    const int m = n - kk;
    extern __shared__ float sm[];
    float* sP = sm;                       // m*nb
    float* red = sP + (long)m * nb;
    float* staus = (float*)(red + nt);    // nb

    // load panel
    for (long idx = t; idx < (long)m * nb; idx += nt) {
        int r = idx / nb, j = idx % nb;
        sP[(long)j * m + r] = M[(long)(kk + r) * n + (kk + j)];
    }
    __syncthreads();

    for (int jc = 0; jc < nb; ++jc) {
        // norm of sP[r,jc] for r>jc
        float part = 0.f;
        for (int r = jc + 1 + t; r < m; r += nt) { float v = sP[(long)jc * m + r]; part += v * v; }
        const float ssq = blkReduceSum(part, red, t, nt);
        const float alpha = sP[(long)jc * m + jc];
        float beta, tau_c, inv_denom;
        if (ssq == 0.f) { beta = alpha; tau_c = 0.f; inv_denom = 0.f; }
        else { float nrm = sqrtf(alpha * alpha + ssq); float bd = (alpha > 0.f) ? -nrm : nrm;
               beta = bd; tau_c = (bd - alpha) / bd; inv_denom = 1.f / (alpha - bd); }
        if (t == 0) { tb[kk + jc] = tau_c; staus[jc] = tau_c; }
        for (int r = jc + 1 + t; r < m; r += nt) if (ssq != 0.f) sP[(long)jc * m + r] *= inv_denom;
        __syncthreads();   // RACE FIX: all threads must finish reading alpha=sP[jc,jc] before t0 overwrites it with beta
        if (t == 0) sP[(long)jc * m + jc] = beta;
        __syncthreads();
        // apply reflector to panel cols (jc, nb): 4 columns per reduction (separate registers)
        for (int jp = jc + 1; jp < nb; jp += 4) {
            const bool h1 = jp + 1 < nb, h2 = jp + 2 < nb, h3 = jp + 3 < nb;
            float p0 = 0.f, p1 = 0.f, p2 = 0.f, p3 = 0.f;
            for (int r = jc + 1 + t; r < m; r += nt) {
                float vr = sP[(long)jc * m + r];
                p0 += vr * sP[(long)jp * m + r];
                if (h1) p1 += vr * sP[(long)(jp + 1) * m + r];
                if (h2) p2 += vr * sP[(long)(jp + 2) * m + r];
                if (h3) p3 += vr * sP[(long)(jp + 3) * m + r];
            }
            blkReduceSum4(p0, p1, p2, p3, red, t, nt);
            // READ phase: all w_k while threads aligned (post-reduction); then sync; then write.
            float w0 = p0 + sP[(long)jp * m + jc];
            float w1 = h1 ? p1 + sP[(long)(jp + 1) * m + jc] : 0.f;
            float w2 = h2 ? p2 + sP[(long)(jp + 2) * m + jc] : 0.f;
            float w3 = h3 ? p3 + sP[(long)(jp + 3) * m + jc] : 0.f;
            __syncthreads();
            if (t == 0) { sP[(long)jp * m + jc] -= tau_c * w0;
                if (h1) sP[(long)(jp + 1) * m + jc] -= tau_c * w1;
                if (h2) sP[(long)(jp + 2) * m + jc] -= tau_c * w2;
                if (h3) sP[(long)(jp + 3) * m + jc] -= tau_c * w3; }
            for (int r = jc + 1 + t; r < m; r += nt) { float vr = sP[(long)jc * m + r];
                sP[(long)jp * m + r] -= tau_c * vr * w0;
                if (h1) sP[(long)(jp + 1) * m + r] -= tau_c * vr * w1;
                if (h2) sP[(long)(jp + 2) * m + r] -= tau_c * vr * w2;
                if (h3) sP[(long)(jp + 3) * m + r] -= tau_c * vr * w3; }
            __syncthreads();
        }
    }
    // write panel back (VtV+T computed on host via bmm + build_T)
    for (long idx = t; idx < (long)m * nb; idx += nt) {
        int r = idx / nb, j = idx % nb;
        M[(long)(kk + r) * n + (kk + j)] = sP[(long)j * m + r];
    }
}


extern "C" __global__ void build_T(const float* __restrict__ VtV, const float* __restrict__ tau,
                                   float* __restrict__ Tout, int n, int kk, int nb) {
    // Parallel across ROWS of T: each row a is independent (T[a,i] depends only on T[a,l], l<i, same row).
    const int b = blockIdx.x;
    const float* G = VtV + (long)b * nb * nb;
    const float* tb = tau + (long)b * n + kk;
    float* Tb = Tout + (long)b * nb * nb;
    extern __shared__ float sm[];
    float* sg = sm;              // VtV : nb*nb
    float* sT = sm + nb * nb;    // T   : nb*nb
    const int a = threadIdx.x, nt = blockDim.x;
    for (int idx = a; idx < nb * nb; idx += nt) sg[idx] = G[idx];
    __syncthreads();
    if (a < nb) {
        for (int i = 0; i < a; ++i) sT[a * nb + i] = 0.f;
        sT[a * nb + a] = tb[a];
        for (int i = a + 1; i < nb; ++i) {
            float acc = 0.f;
            const float ti = -tb[i];
            for (int l = a; l < i; ++l) acc += sT[a * nb + l] * (ti * sg[l * nb + i]);
            sT[a * nb + i] = acc;
        }
    }
    __syncthreads();
    for (int idx = a; idx < nb * nb; idx += nt) Tb[idx] = sT[idx];
}

void build_T_launch(torch::Tensor VtV, torch::Tensor tau, torch::Tensor Tout, int kk, int nb) {
    const int B = VtV.size(0);
    int thr = nb < 32 ? 32 : nb;
    build_T<<<B, thr, (size_t)2*nb*nb*sizeof(float)>>>(VtV.data_ptr<float>(), tau.data_ptr<float>(), Tout.data_ptr<float>(), tau.size(1), kk, nb);
}
void panel_qr_sh_launch(torch::Tensor Q, torch::Tensor tau, int kk, int nb) {
    const int B = Q.size(0), n = Q.size(1);
    const int m = n - kk;
    int threads = 256;
    size_t shmem = ((size_t)m * nb + threads + nb) * sizeof(float);
    cudaFuncSetAttribute(panel_qr_sh, cudaFuncAttributeMaxDynamicSharedMemorySize, (int)shmem);
    panel_qr_sh<<<B, threads, shmem>>>(Q.data_ptr<float>(), tau.data_ptr<float>(), n, kk, nb);
}
"""

_mod = load_inline(
    name="hh_v55",
    cpp_sources="void panel_qr_sh_launch(torch::Tensor Q, torch::Tensor tau, int kk, int nb);\nvoid build_T_launch(torch::Tensor VtV, torch::Tensor tau, torch::Tensor Tout, int kk, int nb);",
    cuda_sources=_CUDA_SRC,
    functions=["panel_qr_sh_launch","build_T_launch"],
    extra_cuda_cflags=["-O3", "--use_fast_math"],
    verbose=False,
)

_NB = 16


def _householder_qr(A, _NB):
    B, n, _ = A.shape
    M = A.clone()
    tau = torch.zeros(B, n, device=A.device, dtype=torch.float32)
    Tfull = torch.empty(B, _NB, _NB, device=A.device, dtype=torch.float32)
    eye = torch.eye(_NB, device=A.device, dtype=torch.float32)
    for kk in range(0, n, _NB):
        nb = min(_NB, n - kk)
        _mod.panel_qr_sh_launch(M, tau, kk, nb)
        hi = kk + nb
        if hi < n:
            V = M[:, kk:, kk:hi].clone()
            Vblk = V[:, :nb, :nb]
            Vblk.tril_(-1)
            Vblk.diagonal(dim1=-2, dim2=-1).fill_(1.0)
            VtV = V.transpose(-1, -2) @ V
            Tk = Tfull if nb == _NB else torch.empty(B, nb, nb, device=A.device, dtype=torch.float32)
            _mod.build_T_launch(VtV, tau, Tk, kk, nb)
            Atrail = M[:, kk:, hi:]
            W = V.transpose(-1, -2) @ Atrail
            Y = Tk.transpose(-1, -2) @ W
            Atrail.baddbmm_(V, Y, beta=1.0, alpha=-1.0)
    return M, tau



_MM = torch.backends.cuda.matmul
_eye_cache = {}
def _eye(k, dev):
    e = _eye_cache.get((k, dev))
    if e is None:
        e = torch.eye(k, device=dev, dtype=torch.float32); _eye_cache[(k, dev)] = e
    return e


def _bounded_apply(M, V, T, r0, c0, c1, tf32):
    # M[:, r0:, c0:c1] -= V @ (T^T @ (V^T @ M[:, r0:, c0:c1]))
    if c0 >= c1:
        return
    At = M[:, r0:, c0:c1]
    _MM.allow_tf32 = tf32
    W = V.transpose(-1, -2) @ At
    Y = T.transpose(-1, -2) @ W
    At.baddbmm_(V, Y, beta=1.0, alpha=-1.0)
    _MM.allow_tf32 = False


def _make_V(M, r0, c0, c1):
    w = c1 - c0
    V = M[:, r0:, c0:c1].clone()
    Vb = V[:, :w, :w]; Vb.tril_(-1); Vb.diagonal(dim1=-2, dim2=-1).fill_(1.0)
    return V


def _householder_2level(A, nb, NB, tf32_big):
    B, n, _ = A.shape
    M = A.clone()
    tau = torch.zeros(B, n, device=A.device, dtype=torch.float32)
    for K in range(0, n, NB):
        NBk = min(NB, n - K); Kend = K + NBk
        for kk in range(K, Kend, nb):
            nbk = min(nb, Kend - kk); hi = kk + nbk
            _mod.panel_qr_sh_launch(M, tau, kk, nbk)
            if hi < Kend:
                V = _make_V(M, kk, kk, hi)
                VtV = V.transpose(-1, -2) @ V
                T = torch.empty(B, nbk, nbk, device=A.device, dtype=torch.float32)
                _mod.build_T_launch(VtV, tau, T, kk, nbk)
                _bounded_apply(M, V, T, kk, hi, Kend, tf32_big)   # within-block, tf32 when safe
        if Kend < n:
            Vb = _make_V(M, K, K, Kend)
            VtVb = Vb.transpose(-1, -2) @ Vb
            Tb = torch.empty(B, NBk, NBk, device=A.device, dtype=torch.float32)
            _mod.build_T_launch(VtVb, tau, Tb, K, NBk)
            _bounded_apply(M, Vb, Tb, K, Kend, n, tf32_big)    # block trailing, tf32
    return M, tau


def _tf32_unsafe(A):
    n = A.shape[-1]
    rn = A.norm(dim=-1)
    rng = rn.amax(dim=-1) / rn.amin(dim=-1).clamp_min(1e-30)
    if float(rng.amax()) > 1.0e3:
        return True
    if n >= 16:
        q = n // 4
        if float(A[:, :q, 3 * q:].abs().amax()) < 1.0e-6 * float(A.abs().amax()):
            return True
    return False


def custom_kernel(data):
    A = data
    n = A.shape[-1]
    if n > 2048:
        return torch.geqrf(A)
    Af = A.float()
    if n <= 256:
        H, tau = _householder_qr(Af, 16)
    else:
        use_tf32 = not _tf32_unsafe(Af)
        H, tau = _householder_2level(Af, 16, 64, use_tf32)
    if not torch.isfinite(H).all():
        return torch.geqrf(A)
    return H.to(A.dtype), tau.to(A.dtype)
scrolls · 277 lines total

Source code from GPU Mode and the KernelBot dataset · June 9 Researcher Reciprocity License v1.0

Best evidence level for this revision: reported

JSON