Skip to content
KernelIndex
Search⌘K

submission 597516

KernelAgent · python · License unknown

Use it

Vendorable · source mirrored · license unknownView source →

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

gpumode_submit_x0s4q5r3.py
curl "https://kernelindex.com/api/v1/implementations/kernelbot-conv2d-v2-597516?include=source"
interfacepython
Compatibility
measured onNVIDIA H100
declared hardwareNVIDIA H100
architecturessm_90
dtypesfp32

Benchmark evidence

1 measurement across 1 GPU, fastest first.

Operation / workload
Hardware
Latency
Rank
Observed
2D convolutionsuite of 5 cases
NVIDIA H100
132.0ms
#21 of 35
2026-03-20

Reported · How evidence levels are derived →

Source and license

sourceavailable
revision digestsha256:1241a54856d02519119b5e5af1c182a7dd9eafdb2a43cd49eae8d9ccd88ccd9d
license declaredunknown
license concludedunknown
authorsKernelAgent
imported2026-08-15

Techniques

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

mmaacc += tl.dot(a_tile, tl.trans(w_tile), allow_tf32=False)
tile-k = 32BLOCK_K = 32
tile-m = 64BLOCK_M = 64
tile-n = 64BLOCK_N = 64

Kernel source

gpumode_submit_x0s4q5r3.py121 lines
import torch
import triton
import triton.language as tl


@triton.jit
def _conv2d_kernel(
    input_ptr, weight_ptr, output_ptr,
    in_channels, out_channels,
    in_h, in_w, out_h, out_w,
    kernel_h, kernel_w,
    stride_in_b, stride_in_c, stride_in_h, stride_in_w,
    stride_w_oc, stride_w_ic, stride_w_kh, stride_w_kw,
    stride_out_b, stride_out_c, stride_out_h, stride_out_w,
    K,  # in_channels * kernel_h * kernel_w
    M,  # out_h * out_w
    BLOCK_M: tl.constexpr,
    BLOCK_N: tl.constexpr,
    BLOCK_K: tl.constexpr,
):
    pid_m = tl.program_id(0)
    pid_n = tl.program_id(1)
    b = tl.program_id(2)

    offs_m = pid_m * BLOCK_M + tl.arange(0, BLOCK_M)
    offs_n = pid_n * BLOCK_N + tl.arange(0, BLOCK_N)

    mask_m = offs_m < M
    mask_n = offs_n < out_channels

    oh = offs_m // out_w
    ow = offs_m % out_w

    acc = tl.zeros((BLOCK_M, BLOCK_N), dtype=tl.float32)

    kh_kw = kernel_h * kernel_w

    for k_start in range(0, K, BLOCK_K):
        offs_k = k_start + tl.arange(0, BLOCK_K)
        mask_k = offs_k < K

        ic = offs_k // kh_kw
        rem = offs_k % kh_kw
        kh = rem // kernel_w
        kw = rem % kernel_w

        ih = oh[:, None] + kh[None, :]
        iw = ow[:, None] + kw[None, :]

        in_offset = (b * stride_in_b +
                     ic[None, :] * stride_in_c +
                     ih * stride_in_h +
                     iw * stride_in_w)
        a_tile = tl.load(input_ptr + in_offset,
                         mask=mask_m[:, None] & mask_k[None, :], other=0.0)

        w_offset = (offs_n[:, None] * stride_w_oc +
                    ic[None, :] * stride_w_ic +
                    kh[None, :] * stride_w_kh +
                    kw[None, :] * stride_w_kw)
        w_tile = tl.load(weight_ptr + w_offset,
                         mask=mask_n[:, None] & mask_k[None, :], other=0.0)

        acc += tl.dot(a_tile, tl.trans(w_tile), allow_tf32=False)

    out_offset = (b * stride_out_b +
                  offs_n[None, :] * stride_out_c +
                  oh[:, None] * stride_out_h +
                  ow[:, None] * stride_out_w)
    out_mask = mask_m[:, None] & mask_n[None, :]
    tl.store(output_ptr + out_offset, acc, mask=out_mask)


def kernel_function(input_tensor, kernel_weights, output_tensor=None):
    batch, in_channels, in_h, in_w = input_tensor.shape
    out_channels, _, kernel_h, kernel_w = kernel_weights.shape
    out_h = in_h - kernel_h + 1
    out_w = in_w - kernel_w + 1

    if output_tensor is None:
        output_tensor = torch.empty(
            (batch, out_channels, out_h, out_w),
            device=input_tensor.device, dtype=input_tensor.dtype)

    M = out_h * out_w
    K = in_channels * kernel_h * kernel_w

    BLOCK_M = 64
    BLOCK_N = 64
    BLOCK_K = 32

    grid = (triton.cdiv(M, BLOCK_M), triton.cdiv(out_channels, BLOCK_N), batch)

    _conv2d_kernel[grid](
        input_tensor, kernel_weights, output_tensor,
        in_channels, out_channels,
        in_h, in_w, out_h, out_w,
        kernel_h, kernel_w,
        input_tensor.stride(0), input_tensor.stride(1),
        input_tensor.stride(2), input_tensor.stride(3),
        kernel_weights.stride(0), kernel_weights.stride(1),
        kernel_weights.stride(2), kernel_weights.stride(3),
        output_tensor.stride(0), output_tensor.stride(1),
        output_tensor.stride(2), output_tensor.stride(3),
        K, M,
        BLOCK_M=BLOCK_M, BLOCK_N=BLOCK_N, BLOCK_K=BLOCK_K,
    )
    return output_tensor

import inspect
def custom_kernel(input):
    sig = inspect.signature(kernel_function)
    num_params = len(sig.parameters)
    if len(input) == num_params:
        return kernel_function(*input)
    return kernel_function(input)

import os
if os.environ.get("CUBLAS_WORKSPACE_CONFIG", "") not in (":4096:8", ":16:8"):
    os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8"
scrolls · 121 lines total

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

Changes from previous submission

Against this author's previous submission submission 550064.

⋯ 3 unchanged lines
@triton.jit
- def _conv2d_nchw_str1_nopad_kernel(
- x_ptr, # *const T_x
- w_ptr, # *const T_w
- y_ptr, # *T_y
- # sizes
- N, C_in, H, W,
- C_out, K, H_out, W_out,
- # strides for input x (NCHW)
- stride_xn, stride_xc, stride_xh, stride_xw,
- # strides for weight w (O, I, KH, KW)
- stride_wo, stride_wi, stride_wkh, stride_wkw,
- # strides for output y (N, O, H_out, W_out)
- stride_yn, stride_yc, stride_yh, stride_yw,
- # compile-time tile/block params
- BLOCK_H: tl.constexpr,
- BLOCK_W: tl.constexpr,
- BLOCK_OC: tl.constexpr,
- M: tl.constexpr, # = BLOCK_H * BLOCK_W (compile-time)
+ def _conv2d_kernel(
+ input_ptr, weight_ptr, output_ptr,
+ in_channels, out_channels,
+ in_h, in_w, out_h, out_w,
+ kernel_h, kernel_w,
+ stride_in_b, stride_in_c, stride_in_h, stride_in_w,
+ stride_w_oc, stride_w_ic, stride_w_kh, stride_w_kw,
+ stride_out_b, stride_out_c, stride_out_h, stride_out_w,
+ K, # in_channels * kernel_h * kernel_w
+ M, # out_h * out_w
+ BLOCK_M: tl.constexpr,
+ BLOCK_N: tl.constexpr,
+ BLOCK_K: tl.constexpr,
):
- # Program IDs
- pid_n = tl.program_id(0)
- pid_sp = tl.program_id(1)
- pid_ocg = tl.program_id(2)
+ pid_m = tl.program_id(0)
+ pid_n = tl.program_id(1)
+ b = tl.program_id(2)
- # Tile decomposition for spatial output grid
- num_tiles_w = tl.cdiv(W_out, BLOCK_W)
- tile_h_idx = pid_sp // num_tiles_w
- tile_w_idx = pid_sp % num_tiles_w
- oh0 = tile_h_idx * BLOCK_H
- ow0 = tile_w_idx * BLOCK_W
+ offs_m = pid_m * BLOCK_M + tl.arange(0, BLOCK_M)
+ offs_n = pid_n * BLOCK_N + tl.arange(0, BLOCK_N)
- # Output channel group origin
- oc0 = pid_ocg * BLOCK_OC
+ mask_m = offs_m < M
+ mask_n = offs_n < out_channels
- # Output channel range and mask
- oc_range = oc0 + tl.arange(0, BLOCK_OC)
- oc_mask = oc_range < C_out
+ oh = offs_m // out_w
+ ow = offs_m % out_w
- # Flatten spatial tile indexing: indices 0..M-1 map to (mh, mw)
- m_idx = tl.arange(0, M)
- mh = m_idx // BLOCK_W # [0..BLOCK_H-1]
- mw = m_idx % BLOCK_W # [0..BLOCK_W-1]
+ acc = tl.zeros((BLOCK_M, BLOCK_N), dtype=tl.float32)
- # Per-lane output coords and mask for in-bounds (avoid indexing tensors with tensors)
- oh_m = oh0 + mh
- ow_m = ow0 + mw
- mask_m = (oh_m < H_out) & (ow_m < W_out)
+ kh_kw = kernel_h * kernel_w
- # Base pointers for this program instance
- x_n_base = x_ptr + pid_n * stride_xn
- y_n_base = y_ptr + pid_n * stride_yn
+ for k_start in range(0, K, BLOCK_K):
+ offs_k = k_start + tl.arange(0, BLOCK_K)
+ mask_k = offs_k < K
- # Accumulator (M x BLOCK_OC) in fp32 for numerical stability
- acc = tl.zeros((M, BLOCK_OC), dtype=tl.float32)
+ ic = offs_k // kh_kw
+ rem = offs_k % kh_kw
+ kh = rem // kernel_w
+ kw = rem % kernel_w
- # Convolution:
- # y[n, oc, oh, ow] = sum_{ic, kh, kw} x[n, ic, oh+kh, ow+kw] * w[oc, ic, kh, kw]
- for ic in tl.range(0, C_in):
- x_ic_base = x_n_base + ic * stride_xc
- w_ic_base = w_ptr + ic * stride_wi
- for kh in tl.range(0, K):
- ih_m = oh_m + kh # (M,)
- x_ptrs_row = x_ic_base + ih_m * stride_xh # (M,)
- for kw in tl.range(0, K):
- iw_m = ow_m + kw # (M,)
- x_ptrs_m = x_ptrs_row + iw_m * stride_xw # (M,)
- x_vec = tl.load(x_ptrs_m, mask=mask_m, other=0.0)
+ ih = oh[:, None] + kh[None, :]
+ iw = ow[:, None] + kw[None, :]
- # Weight vector for this (ic, kh, kw) and output channel group
- w_ptrs_vec = (
- w_ic_base
- + oc0 * stride_wo
- + kh * stride_wkh
- + kw * stride_wkw
- + tl.arange(0, BLOCK_OC) * stride_wo
- )
- w_vec = tl.load(w_ptrs_vec, mask=oc_mask, other=0.0)
+ in_offset = (b * stride_in_b +
+ ic[None, :] * stride_in_c +
+ ih * stride_in_h +
+ iw * stride_in_w)
+ a_tile = tl.load(input_ptr + in_offset,
+ mask=mask_m[:, None] & mask_k[None, :], other=0.0)
- # Outer product accumulation into (M, BLOCK_OC)
- acc += x_vec.to(tl.float32)[:, None] * w_vec.to(tl.float32)[None, :]
+ w_offset = (offs_n[:, None] * stride_w_oc +
+ ic[None, :] * stride_w_ic +
+ kh[None, :] * stride_w_kh +
+ kw[None, :] * stride_w_kw)
+ w_tile = tl.load(weight_ptr + w_offset,
+ mask=mask_n[:, None] & mask_k[None, :], other=0.0)
- # Store results
- y_ptrs = (
- y_n_base
- + oc_range[None, :] * stride_yc
- + oh_m[:, None] * stride_yh
- + ow_m[:, None] * stride_yw
- )
- out_dtype = y_ptr.dtype.element_ty
- y_vals = acc.to(out_dtype)
- y_mask = mask_m[:, None] & oc_mask[None, :]
- tl.store(y_ptrs, y_vals, mask=y_mask)
+ acc += tl.dot(a_tile, tl.trans(w_tile), allow_tf32=False)
+ out_offset = (b * stride_out_b +
+ offs_n[None, :] * stride_out_c +
+ oh[:, None] * stride_out_h +
+ ow[:, None] * stride_out_w)
+ out_mask = mask_m[:, None] & mask_n[None, :]
+ tl.store(output_ptr + out_offset, acc, mask=out_mask)
- def kernel_function(input_tensor: torch.Tensor, kernel: torch.Tensor, out: torch.Tensor = None):
- """
- Triton 2D convolution (NCHW) with stride=1 and padding=0.
- - Single fused kernel: performs full accumulation over input channels and kernel spatial dims.
- - No math or reductions in the wrapper: only validation, allocation, and launch.
- Args:
- input_tensor: (N, C_in, H, W), CUDA tensor (float32 / float16 / bfloat16)
- kernel: (C_out, C_in, K, K), contiguous CUDA tensor, same dtype/device as input
- out: Optional preallocated tensor (N, C_out, H-K+1, W-K+1)
+ def kernel_function(input_tensor, kernel_weights, output_tensor=None):
+ batch, in_channels, in_h, in_w = input_tensor.shape
+ out_channels, _, kernel_h, kernel_w = kernel_weights.shape
+ out_h = in_h - kernel_h + 1
+ out_w = in_w - kernel_w + 1
- Returns:
- (N, C_out, H-K+1, W-K+1) tensor on CUDA with same dtype as input.
- """
- # Validation (no compute)
- assert isinstance(input_tensor, torch.Tensor) and isinstance(kernel, torch.Tensor)
- assert input_tensor.is_cuda and kernel.is_cuda
- assert input_tensor.dim() == 4 and kernel.dim() == 4
- assert input_tensor.device == kernel.device
- assert input_tensor.dtype == kernel.dtype
- assert input_tensor.is_contiguous() and kernel.is_contiguous()
+ if output_tensor is None:
+ output_tensor = torch.empty(
+ (batch, out_channels, out_h, out_w),
+ device=input_tensor.device, dtype=input_tensor.dtype)
- N, C_in, H, W = input_tensor.shape
- C_out, C_in_w, K, K_w = kernel.shape
- assert C_in == C_in_w and K == K_w, "Incompatible kernel shape"
- assert H >= K and W >= K, "Kernel larger than input"
- H_out = H - K + 1
- W_out = W - K + 1
+ M = out_h * out_w
+ K = in_channels * kernel_h * kernel_w
- # Supported dtypes
- if input_tensor.dtype not in (torch.float32, torch.float16, torch.bfloat16):
- raise TypeError(f"Unsupported dtype: {input_tensor.dtype}")
- out_dtype = input_tensor.dtype
+ BLOCK_M = 64
+ BLOCK_N = 64
+ BLOCK_K = 32
- # Allocate output if needed
- if out is None:
- out = torch.empty((N, C_out, H_out, W_out), device=input_tensor.device, dtype=out_dtype)
- else:
- assert isinstance(out, torch.Tensor) and out.is_cuda
- assert out.device == input_tensor.device
- assert out.dtype == out_dtype
- assert out.shape == (N, C_out, H_out, W_out)
- assert out.is_contiguous()
+ grid = (triton.cdiv(M, BLOCK_M), triton.cdiv(out_channels, BLOCK_N), batch)
- # Element-wise strides
- stride_xn, stride_xc, stride_xh, stride_xw = input_tensor.stride()
- stride_wo, stride_wi, stride_wkh, stride_wkw = kernel.stride()
- stride_yn, stride_yc, stride_yh, stride_yw = out.stride()
-
- # Tile sizes (powers of two, masks handle tails)
- BLOCK_H = 16
- BLOCK_W = 16
- BLOCK_OC = 32
- M = BLOCK_H * BLOCK_W # constexpr
-
- def grid(meta):
- num_tiles_h = triton.cdiv(H_out, meta["BLOCK_H"])
- num_tiles_w = triton.cdiv(W_out, meta["BLOCK_W"])
- return (
- N, # batch
- num_tiles_h * num_tiles_w, # spatial tiles
- triton.cdiv(C_out, meta["BLOCK_OC"]), # output channel tiles
- )
-
- # Launch kernel
- _conv2d_nchw_str1_nopad_kernel[grid](
- input_tensor, kernel, out,
- N, C_in, H, W,
- C_out, K, H_out, W_out,
- stride_xn, stride_xc, stride_xh, stride_xw,
- stride_wo, stride_wi, stride_wkh, stride_wkw,
- stride_yn, stride_yc, stride_yh, stride_yw,
- BLOCK_H=BLOCK_H, BLOCK_W=BLOCK_W, BLOCK_OC=BLOCK_OC, M=M,
- num_warps=4, num_stages=2,
+ _conv2d_kernel[grid](
+ input_tensor, kernel_weights, output_tensor,
+ in_channels, out_channels,
+ in_h, in_w, out_h, out_w,
+ kernel_h, kernel_w,
+ input_tensor.stride(0), input_tensor.stride(1),
+ input_tensor.stride(2), input_tensor.stride(3),
+ kernel_weights.stride(0), kernel_weights.stride(1),
+ kernel_weights.stride(2), kernel_weights.stride(3),
+ output_tensor.stride(0), output_tensor.stride(1),
+ output_tensor.stride(2), output_tensor.stride(3),
+ K, M,
+ BLOCK_M=BLOCK_M, BLOCK_N=BLOCK_N, BLOCK_K=BLOCK_K,
)
- return out
+ return output_tensor
import inspect
def custom_kernel(input):
scrolls · 258 diff lines total

Best evidence level for this revision: reported

JSON