Skip to content
KernelIndex
Search⌘K

submission 99142

Petr_Rocoss · python · License unknown

Use it

Vendorable · source mirrored · license unknownView source →

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

submission_batched_experimental.py
curl "https://kernelindex.com/api/v1/implementations/kernelbot-conv2d-v2-99142?include=source"
interfacepython
Compatibility
measured onNVIDIA A100
declared hardwareNVIDIA A100
architecturessm_80
dtypesfp32

Benchmark evidence

1 measurement across 1 GPU, fastest first.

Operation / workload
Hardware
Latency
Rank
Observed
2D convolutionsuite of 5 cases
NVIDIA A100
313.6ms
#26 of 40
2025-11-23

Reported · How evidence levels are derived →

Source and license

sourceavailable
revision digestsha256:8b7257bf79d952f2d39d417e9dc23c3ddd3c7461959a4e4212a50c208cca3b53
license declaredunknown
license concludedunknown
authorsPetr_Rocoss
imported2026-08-15

Techniques

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

autotune@triton.autotune(
num-warps = 8triton.Config({'BLOCK_H': 8, 'BLOCK_W': 128}, num_warps=8, num_stages=6),
stages = 6triton.Config({'BLOCK_H': 8, 'BLOCK_W': 128}, num_warps=8, num_stages=6),

Kernel source

submission_batched_experimental.py167 lines
import torch
import triton
import triton.language as tl

@triton.autotune(
    configs=[
        # === High-End (A100, H100, B200) ===
        # Максимальный prefetch (stages=6) скрывает латентность HBM
        triton.Config({'BLOCK_H': 8, 'BLOCK_W': 128}, num_warps=8, num_stages=6),
        triton.Config({'BLOCK_H': 4, 'BLOCK_W': 256}, num_warps=8, num_stages=6),
        triton.Config({'BLOCK_H': 4, 'BLOCK_W': 128}, num_warps=8, num_stages=5),
        
        # === Mid-Range / General ===
        triton.Config({'BLOCK_H': 4, 'BLOCK_W': 64},  num_warps=4, num_stages=4),
        triton.Config({'BLOCK_H': 2, 'BLOCK_W': 128}, num_warps=4, num_stages=4),
        
        # === Small sizes / Latency ===
        triton.Config({'BLOCK_H': 2, 'BLOCK_W': 64},  num_warps=4, num_stages=3),
    ],
    key=['W_OUT', 'H_OUT', 'C_IN', 'K'],
)
@triton.jit
def conv2d_kernel_ultimate(
    input_ptr, weight_ptr, output_ptr,
    stride_in_n, stride_in_c, stride_in_h, stride_in_w,
    stride_w_out, stride_w_in, stride_w_h, stride_w_w,
    stride_out_n, stride_out_c, stride_out_h, stride_out_w,
    H_IN, W_IN, H_OUT, W_OUT, C_IN, C_OUT, K,
    BLOCK_H: tl.constexpr, BLOCK_W: tl.constexpr
):
    """
    Ultimate Optimized Conv2D Kernel.
    Особенности:
    1. 2D Tiling (H, W) для переиспользования данных в L1 кэше.
    2. Pointer Induction: замена умножения на сложение в циклах.
    3. Pre-calculated Masks: вынос логики масок из горячих циклов.
    """
    
    # --- 1. Setup Grid & Indices ---
    pid_w = tl.program_id(0)
    pid_h = tl.program_id(1)
    pid_z = tl.program_id(2)
    
    batch_idx = pid_z // C_OUT
    out_ch = pid_z % C_OUT
    
    # --- 2. Offsets & Masks (Computed ONCE) ---
    
    # Output Y offsets [BLOCK_H]
    offs_h = pid_h * BLOCK_H + tl.arange(0, BLOCK_H)
    # Output X offsets [BLOCK_W]
    offs_w = pid_w * BLOCK_W + tl.arange(0, BLOCK_W)
    
    # Pre-calculate mask [BLOCK_H, BLOCK_W]
    # Примечание: при валидных размерах тензоров и stride=1, 
    # проверка выхода гарантирует валидность входа для padding=0.
    mask_h = offs_h < H_OUT
    mask_w = offs_w < W_OUT
    mask_block = mask_h[:, None] & mask_w[None, :]
    
    # --- 3. Initial Pointers Setup ---
    
    # Output Pointer [BLOCK_H, BLOCK_W] (Broadcasting)
    # Base + Batch + Channel + H_offset + W_offset
    ptr_out = output_ptr + \
              batch_idx * stride_out_n + \
              out_ch * stride_out_c + \
              (offs_h[:, None] * stride_out_h) + \
              (offs_w[None, :] * stride_out_w)

    # Input Pointer Base [BLOCK_H, BLOCK_W]
    # Мы начинаем с позиции, соответствующей верхнему левому углу окна для первого пикселя блока.
    # Так как stride=1, input_h == output_h
    ptr_in_base = input_ptr + \
                  batch_idx * stride_in_n + \
                  (offs_h[:, None] * stride_in_h) + \
                  (offs_w[None, :] * stride_in_w)

    # Weight Pointer Base
    ptr_wei_base = weight_ptr + out_ch * stride_w_out
    
    # Accumulator
    acc = tl.zeros([BLOCK_H, BLOCK_W], dtype=tl.float32)
    
    # --- 4. Main Loop (Pointer Chasing) ---
    
    # Текущие указатели для начала канала
    curr_in_ch = ptr_in_base
    curr_wei_ch = ptr_wei_base
    
    for cin in range(C_IN):
        # Временные указатели для Spatial Loop
        curr_in_row = curr_in_ch
        curr_wei_row = curr_wei_ch
        
        for kh in range(K):
            # Смещение внутри строки (kw)
            # Мы не меняем указатель строки, а вычисляем смещения от него,
            # так как K обычно мал, и компилятор хорошо разворачивает это.
            # Однако для строки мы делаем инкремент.
            
            for kw in range(K):
                # Load Weight: Scalar -> Broadcast
                # ptr + kw * stride_w
                wei_val = tl.load(curr_wei_row + kw * stride_w_w)
                
                # Load Input: 2D Block
                # ptr + kw * stride_in (т.к. contiguous по W, это просто смещение на kw)
                # Input Stride W обычно равен 1, но используем переменную для универсальности.
                val_in = tl.load(curr_in_row + kw * stride_in_w, mask=mask_block, other=0.0)
                
                # FMA
                acc = acc + val_in * wei_val
            
            # Инкремент указателей строк (сдвиг вниз по H)
            curr_in_row += stride_in_h
            curr_wei_row += stride_w_h

        # Инкремент указателей каналов (Pointer Induction)
        # Это заменяет умножение `cin * stride` на сложение
        curr_in_ch += stride_in_c
        curr_wei_ch += stride_w_in

    # --- 5. Store Result ---
    tl.store(ptr_out, acc, mask=mask_block)


def custom_kernel(data):
    """
    Optimized Conv2D entry point.
    """
    input_tensor, kernel, output_tensor = data
    
    # 1. Ensure contiguous layout (Critical for vectorization)
    if not input_tensor.is_contiguous():
        input_tensor = input_tensor.contiguous()
    if not kernel.is_contiguous():
        kernel = kernel.contiguous()
    
    # 2. Extract shapes
    batch, c_in, h_in, w_in = input_tensor.shape
    c_out, _, k_h, k_w = kernel.shape
    
    h_out = h_in - k_h + 1
    w_out = w_in - k_w + 1
    
    # 3. Grid definition
    grid = lambda META: (
        triton.cdiv(w_out, META['BLOCK_W']),
        triton.cdiv(h_out, META['BLOCK_H']),
        batch * c_out
    )
    
    # 4. Launch
    conv2d_kernel_ultimate[grid](
        input_tensor, kernel, output_tensor,
        # Strides
        *input_tensor.stride(),
        *kernel.stride(),
        *output_tensor.stride(),
        # Dims
        h_in, w_in, h_out, w_out,
        c_in, c_out, k_h,
    )
    
    return output_tensor
scrolls · 167 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 99134.

⋯ 3 unchanged lines
@triton.autotune(
configs=[
- # === High-end (A100, H100, B200) ===
- # Большой тайл по ширине (W) и средний по высоте (H) + высокий prefetch
- triton.Config({'BLOCK_H': 4, 'BLOCK_W': 256}, num_warps=8, num_stages=5),
- triton.Config({'BLOCK_H': 8, 'BLOCK_W': 128}, num_warps=8, num_stages=5),
- triton.Config({'BLOCK_H': 4, 'BLOCK_W': 128}, num_warps=8, num_stages=6),
+ # === High-End (A100, H100, B200) ===
+ # Максимальный prefetch (stages=6) скрывает латентность HBM
+ triton.Config({'BLOCK_H': 8, 'BLOCK_W': 128}, num_warps=8, num_stages=6),
+ triton.Config({'BLOCK_H': 4, 'BLOCK_W': 256}, num_warps=8, num_stages=6),
+ triton.Config({'BLOCK_H': 4, 'BLOCK_W': 128}, num_warps=8, num_stages=5),
- # === Balanced (L4, A10) ===
+ # === Mid-Range / General ===
triton.Config({'BLOCK_H': 4, 'BLOCK_W': 64}, num_warps=4, num_stages=4),
triton.Config({'BLOCK_H': 2, 'BLOCK_W': 128}, num_warps=4, num_stages=4),
- # === Small / Latency optimized ===
+ # === Small sizes / Latency ===
triton.Config({'BLOCK_H': 2, 'BLOCK_W': 64}, num_warps=4, num_stages=3),
],
key=['W_OUT', 'H_OUT', 'C_IN', 'K'],
)
@triton.jit
- def conv2d_kernel_optimized(
+ def conv2d_kernel_ultimate(
input_ptr, weight_ptr, output_ptr,
stride_in_n, stride_in_c, stride_in_h, stride_in_w,
stride_w_out, stride_w_in, stride_w_h, stride_w_w,
⋯ 2 unchanged lines
BLOCK_H: tl.constexpr, BLOCK_W: tl.constexpr
):
"""
- Ultimate Optimized Conv2D Kernel (2D Tiling + Pre-calc Masks + Pointer Arithmetic).
+ Ultimate Optimized Conv2D Kernel.
+ Особенности:
+ 1. 2D Tiling (H, W) для переиспользования данных в L1 кэше.
+ 2. Pointer Induction: замена умножения на сложение в циклах.
+ 3. Pre-calculated Masks: вынос логики масок из горячих циклов.
"""
- # 1. Grid IDs
+ # --- 1. Setup Grid & Indices ---
pid_w = tl.program_id(0)
pid_h = tl.program_id(1)
pid_z = tl.program_id(2)
- # 2. Decode Dimensions
batch_idx = pid_z // C_OUT
out_ch = pid_z % C_OUT
- # 3. Calculate Offsets & Masks (Pre-calculated!)
- # Output Y coords [BLOCK_H]
- offs_h = pid_h * BLOCK_H + tl.arange(0, BLOCK_H)
- mask_h = offs_h < H_OUT
+ # --- 2. Offsets & Masks (Computed ONCE) ---
- # Output X coords [BLOCK_W]
+ # Output Y offsets [BLOCK_H]
+ offs_h = pid_h * BLOCK_H + tl.arange(0, BLOCK_H)
+ # Output X offsets [BLOCK_W]
offs_w = pid_w * BLOCK_W + tl.arange(0, BLOCK_W)
- mask_w = offs_w < W_OUT
- # Combined Mask [BLOCK_H, BLOCK_W]
- # Вычисляем один раз и используем везде.
- # При stride=1 и padding=0 валидность выхода гарантирует валидность входа.
+ # Pre-calculate mask [BLOCK_H, BLOCK_W]
+ # Примечание: при валидных размерах тензоров и stride=1,
+ # проверка выхода гарантирует валидность входа для padding=0.
+ mask_h = offs_h < H_OUT
+ mask_w = offs_w < W_OUT
mask_block = mask_h[:, None] & mask_w[None, :]
- # 4. Base Pointers Setup
- # Output Ptr: Base + Batch offset + Channel offset
- dst_ptr_base = output_ptr + batch_idx * stride_out_n + out_ch * stride_out_c
+ # --- 3. Initial Pointers Setup ---
- # Input Ptr: Base + Batch offset + (Initial H offset) + (Initial W offset)
- # Входной H начинается там же, где выходной H (offs_h), так как stride=1
- # Входной W начинается там же, где выходной W (offs_w)
- # Мы используем broadcasting для создания 2D сетки указателей
- # Input Ptrs [BLOCK_H, BLOCK_W]
- src_ptr_base = input_ptr + batch_idx * stride_in_n + \
- (offs_h[:, None] * stride_in_h) + \
- (offs_w[None, :] * stride_in_w)
-
- # Weight Ptr Base: Channel Offset
- wei_ptr_base = weight_ptr + out_ch * stride_w_out
+ # Output Pointer [BLOCK_H, BLOCK_W] (Broadcasting)
+ # Base + Batch + Channel + H_offset + W_offset
+ ptr_out = output_ptr + \
+ batch_idx * stride_out_n + \
+ out_ch * stride_out_c + \
+ (offs_h[:, None] * stride_out_h) + \
+ (offs_w[None, :] * stride_out_w)
+
+ # Input Pointer Base [BLOCK_H, BLOCK_W]
+ # Мы начинаем с позиции, соответствующей верхнему левому углу окна для первого пикселя блока.
+ # Так как stride=1, input_h == output_h
+ ptr_in_base = input_ptr + \
+ batch_idx * stride_in_n + \
+ (offs_h[:, None] * stride_in_h) + \
+ (offs_w[None, :] * stride_in_w)
+
+ # Weight Pointer Base
+ ptr_wei_base = weight_ptr + out_ch * stride_w_out
- # 5. Accumulator
+ # Accumulator
acc = tl.zeros([BLOCK_H, BLOCK_W], dtype=tl.float32)
- # 6. Main Loop
+ # --- 4. Main Loop (Pointer Chasing) ---
+
+ # Текущие указатели для начала канала
+ curr_in_ch = ptr_in_base
+ curr_wei_ch = ptr_wei_base
+
for cin in range(C_IN):
- # Сдвигаем указатели каналов
- src_ch = src_ptr_base + cin * stride_in_c
- wei_ch = wei_ptr_base + cin * stride_w_in
+ # Временные указатели для Spatial Loop
+ curr_in_row = curr_in_ch
+ curr_wei_row = curr_wei_ch
for kh in range(K):
- # Смещение по вертикали ядра
- # Для входа: добавляем stride_in_h * kh
- # Для веса: добавляем stride_w_h * kh
- src_row = src_ch + kh * stride_in_h
- wei_row = wei_ch + kh * stride_w_h
+ # Смещение внутри строки (kw)
+ # Мы не меняем указатель строки, а вычисляем смещения от него,
+ # так как K обычно мал, и компилятор хорошо разворачивает это.
+ # Однако для строки мы делаем инкремент.
for kw in range(K):
- # --- A. Load Weight (Scalar) ---
- # Загружаем [1] скаляр и "размножаем" его неявно при умножении
- wei_val = tl.load(wei_row + kw * stride_w_w)
+ # Load Weight: Scalar -> Broadcast
+ # ptr + kw * stride_w
+ wei_val = tl.load(curr_wei_row + kw * stride_w_w)
- # --- B. Load Input (2D Block) ---
- # Указатель уже содержит offs_h и offs_w.
- # Нам нужно только добавить смещение текущего kw
- # src_row [BLOCK_H, BLOCK_W] + scalar offset
- src_ptrs = src_row + kw * stride_in_w
+ # Load Input: 2D Block
+ # ptr + kw * stride_in (т.к. contiguous по W, это просто смещение на kw)
+ # Input Stride W обычно равен 1, но используем переменную для универсальности.
+ val_in = tl.load(curr_in_row + kw * stride_in_w, mask=mask_block, other=0.0)
- # Используем пре-калькулированную маску!
- val_in = tl.load(src_ptrs, mask=mask_block, other=0.0)
-
- # --- C. FMA ---
+ # FMA
acc = acc + val_in * wei_val
+
+ # Инкремент указателей строк (сдвиг вниз по H)
+ curr_in_row += stride_in_h
+ curr_wei_row += stride_w_h
- # 7. Store Result
- # Вычисляем указатели назначения
- dst_ptrs = dst_ptr_base + \
- (offs_h[:, None] * stride_out_h) + \
- (offs_w[None, :] * stride_out_w)
-
- tl.store(dst_ptrs, acc, mask=mask_block)
+ # Инкремент указателей каналов (Pointer Induction)
+ # Это заменяет умножение `cin * stride` на сложение
+ curr_in_ch += stride_in_c
+ curr_wei_ch += stride_w_in
+ # --- 5. Store Result ---
+ tl.store(ptr_out, acc, mask=mask_block)
+
def custom_kernel(data):
+ """
+ Optimized Conv2D entry point.
+ """
input_tensor, kernel, output_tensor = data
- # Contiguous check - критично для Triton
+ # 1. Ensure contiguous layout (Critical for vectorization)
if not input_tensor.is_contiguous():
input_tensor = input_tensor.contiguous()
if not kernel.is_contiguous():
kernel = kernel.contiguous()
- # Dimensions
+ # 2. Extract shapes
batch, c_in, h_in, w_in = input_tensor.shape
c_out, _, k_h, k_w = kernel.shape
h_out = h_in - k_h + 1
w_out = w_in - k_w + 1
- # Grid: (W_tiles, H_tiles, Batch*OutCh)
+ # 3. Grid definition
grid = lambda META: (
triton.cdiv(w_out, META['BLOCK_W']),
triton.cdiv(h_out, META['BLOCK_H']),
batch * c_out
)
- conv2d_kernel_optimized[grid](
+ # 4. Launch
+ conv2d_kernel_ultimate[grid](
input_tensor, kernel, output_tensor,
# Strides
*input_tensor.stride(),
*kernel.stride(),
*output_tensor.stride(),
- # Dimensions
+ # Dims
h_in, w_in, h_out, w_out,
c_in, c_out, k_h,
)
scrolls · 229 diff lines total

Best evidence level for this revision: reported

JSON