Skip to content
KernelIndex
Search⌘K

submission 99063

Petr_Rocoss · python · License unknown

Use it

Vendorable · source mirrored · license unknownView source →

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

submission_elite_v1.py
curl "https://kernelindex.com/api/v1/implementations/kernelbot-conv2d-v2-99063?include=source"
interfacepython
Compatibility
measured onNVIDIA L4
declared hardwareNVIDIA L4
architecturessm_89
dtypesfp32

Benchmark evidence

1 measurement across 1 GPU, fastest first.

Operation / workload
Hardware
Latency
Rank
Observed
2D convolutionsuite of 5 cases
NVIDIA L4
1.14s
#15 of 21
2025-11-23

Reported · How evidence levels are derived →

Source and license

sourceavailable
revision digestsha256:ab32f294f769a171618dcce56af30f17c69684d72c2e781366873d8c029fdbae
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': 4, 'BLOCK_W': 128}, num_warps=8, num_stages=4),
stages = 4triton.Config({'BLOCK_H': 4, 'BLOCK_W': 128}, num_warps=8, num_stages=4),

Kernel source

submission_elite_v1.py150 lines
import torch
import triton
import triton.language as tl

# Добавляем BLOCK_H в конфигурации автотюнинга
@triton.autotune(
    configs=[
        # Конфигурации для больших тензоров (A100/H100)
        triton.Config({'BLOCK_H': 4, 'BLOCK_W': 128}, num_warps=8, num_stages=4),
        triton.Config({'BLOCK_H': 8, 'BLOCK_W': 64},  num_warps=8, num_stages=4),
        triton.Config({'BLOCK_H': 2, 'BLOCK_W': 256}, num_warps=8, num_stages=3),
        
        # Конфигурации для средних размеров / L4
        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),
        
        # Fallback для маленьких размеров
        triton.Config({'BLOCK_H': 1, 'BLOCK_W': 32},  num_warps=2, num_stages=2),
    ],
    key=['W_OUT', 'H_OUT', 'C_IN', 'K'],
)
@triton.jit
def conv2d_kernel_tiled(
    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
):
    """
    Супер-оптимизированное ядро с 2D-блокировкой (H x W).
    Обрабатывает прямоугольный тайл выхода за один раз.
    """
    
    # Grid IDs
    pid_w = tl.program_id(0)
    pid_h = tl.program_id(1)
    pid_z = tl.program_id(2)
    
    # Декодируем Batch и Output Channel
    batch_idx = pid_z // C_OUT
    out_ch = pid_z % C_OUT
    
    # --- 1. Координаты и маски (2D) ---
    
    # Output Height offsets: [BLOCK_H, 1]
    offs_h = pid_h * BLOCK_H + tl.arange(0, BLOCK_H)
    mask_h = offs_h < H_OUT
    
    # Output Width offsets: [1, BLOCK_W]
    offs_w = pid_w * BLOCK_W + tl.arange(0, BLOCK_W)
    mask_w = offs_w < W_OUT
    
    # --- 2. Базовые указатели ---
    
    # Указатель на начало Output для текущего Batch/Channel
    # output[b, c, h, w] -> используем 2D broadcasting для записи
    dst_base = output_ptr + batch_idx * stride_out_n + out_ch * stride_out_c
    
    # Указатель на начало Input для текущего Batch
    # Input: [batch, cin, h, w]
    src_base = input_ptr + batch_idx * stride_in_n
    
    # Указатель на начало Weights для текущего Out Channel
    # Weight: [cout, cin, kh, kw]
    wei_base = weight_ptr + out_ch * stride_w_out
    
    # --- 3. Аккумулятор (Register File) ---
    # Теперь это 2D массив [BLOCK_H, BLOCK_W]
    acc = tl.zeros([BLOCK_H, BLOCK_W], dtype=tl.float32)
    
    # --- 4. Основной цикл ---
    for cin in range(C_IN):
        # Сдвигаем указатели на текущий входной канал
        src_ch = src_base + cin * stride_in_c
        wei_ch = wei_base + cin * stride_w_in
        
        for kh in range(K):
            # Pre-calc смещения по вертикали для входа
            # Input H index = (offs_h + kh)
            # Broadcasting: (BLOCK_H, 1)
            curr_h_in = offs_h[:, None] + kh
            src_row_ptr = src_ch + curr_h_in * stride_in_h
            
            # Смещение веса по высоте
            wei_row_ptr = wei_ch + kh * stride_w_h
            
            for kw in range(K):
                # --- A. Загрузка Веса (Scalar broadcast) ---
                # Загружаем 1 скаляр, используем для всего блока [BLOCK_H, BLOCK_W]
                wei_val = tl.load(wei_row_ptr + kw * stride_w_w)
                
                # --- B. Загрузка Входа (2D Block Load) ---
                # Input W index = (offs_w + kw)
                # Ptr = src_row_ptr (зависит от H) + (W смещение)
                # Размерность: [BLOCK_H, 1] + [1, BLOCK_W] -> [BLOCK_H, BLOCK_W]
                src_ptrs = src_row_ptr + (offs_w[None, :] + kw) * stride_in_w
                
                # Маска: проверяем валидность H (выхода) и W (выхода)
                # Примечание: padding=0, stride=1 гарантируют, что если output внутри границ,
                # то input (out + k) тоже внутри границ (при валидных размерах тензоров).
                # Используем комбинированную маску mask_h & mask_w
                val_in = tl.load(src_ptrs, mask=(mask_h[:, None] & mask_w[None, :]), other=0.0)
                
                # --- C. FMA ---
                acc = acc + val_in * wei_val

    # --- 5. Запись результата ---
    # Output Ptr: dst_base + h * stride_h + w * stride_w
    offs_out = dst_base + offs_h[:, None] * stride_out_h + offs_w[None, :] * stride_out_w
    tl.store(offs_out, acc, mask=(mask_h[:, None] & mask_w[None, :]))


def custom_kernel(data):
    input_tensor, kernel, output_tensor = data
    
    # Обеспечиваем memory layout
    if not input_tensor.is_contiguous():
        input_tensor = input_tensor.contiguous()
    if not kernel.is_contiguous():
        kernel = kernel.contiguous()
    
    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 Calculation
    # X: Тайлы по ширине
    # Y: Тайлы по высоте (теперь делим на BLOCK_H!)
    # Z: Batch * OutChannels
    grid = lambda META: (
        triton.cdiv(w_out, META['BLOCK_W']),
        triton.cdiv(h_out, META['BLOCK_H']),
        batch * c_out
    )
    
    conv2d_kernel_tiled[grid](
        input_tensor, kernel, output_tensor,
        *input_tensor.stride(),
        *kernel.stride(),
        *output_tensor.stride(),
        h_in, w_in, h_out, w_out,
        c_in, c_out, k_h,
    )
    
    return output_tensor
scrolls · 150 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 99054.

⋯ 1 unchanged lines
import triton
import triton.language as tl
+ # Добавляем BLOCK_H в конфигурации автотюнинга
@triton.autotune(
configs=[
- triton.Config({'BLOCK_W': 256}, num_warps=8, num_stages=4),
- triton.Config({'BLOCK_W': 128}, num_warps=8, num_stages=4),
- triton.Config({'BLOCK_W': 512}, num_warps=8, num_stages=3),
- triton.Config({'BLOCK_W': 64}, num_warps=4, num_stages=4),
+ # Конфигурации для больших тензоров (A100/H100)
+ triton.Config({'BLOCK_H': 4, 'BLOCK_W': 128}, num_warps=8, num_stages=4),
+ triton.Config({'BLOCK_H': 8, 'BLOCK_W': 64}, num_warps=8, num_stages=4),
+ triton.Config({'BLOCK_H': 2, 'BLOCK_W': 256}, num_warps=8, num_stages=3),
+
+ # Конфигурации для средних размеров / L4
+ 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),
+
+ # Fallback для маленьких размеров
+ triton.Config({'BLOCK_H': 1, 'BLOCK_W': 32}, num_warps=2, num_stages=2),
],
- key=['w_out', 'c_in', 'k_size'],
+ key=['W_OUT', 'H_OUT', 'C_IN', 'K'],
)
@triton.jit
- def conv2d_kernel(
+ def conv2d_kernel_tiled(
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_W: tl.constexpr
+ BLOCK_H: tl.constexpr, BLOCK_W: tl.constexpr
):
- """Оптимизированное ядро Conv2D с правильным порядком циклов."""
+ """
+ Супер-оптимизированное ядро с 2D-блокировкой (H x W).
+ Обрабатывает прямоугольный тайл выхода за один раз.
+ """
+ # Grid IDs
pid_w = tl.program_id(0)
pid_h = tl.program_id(1)
pid_z = tl.program_id(2)
+ # Декодируем Batch и Output Channel
batch_idx = pid_z // C_OUT
out_ch = pid_z % C_OUT
- out_h = pid_h
- # Width offsets
+ # --- 1. Координаты и маски (2D) ---
+
+ # Output Height offsets: [BLOCK_H, 1]
+ offs_h = pid_h * BLOCK_H + tl.arange(0, BLOCK_H)
+ mask_h = offs_h < H_OUT
+
+ # Output Width offsets: [1, BLOCK_W]
offs_w = pid_w * BLOCK_W + tl.arange(0, BLOCK_W)
mask_w = offs_w < W_OUT
- # Base pointers
- out_base = output_ptr + batch_idx * stride_out_n + out_ch * stride_out_c + out_h * stride_out_h
- in_base = input_ptr + batch_idx * stride_in_n + out_h * stride_in_h
+ # --- 2. Базовые указатели ---
+
+ # Указатель на начало Output для текущего Batch/Channel
+ # output[b, c, h, w] -> используем 2D broadcasting для записи
+ dst_base = output_ptr + batch_idx * stride_out_n + out_ch * stride_out_c
+
+ # Указатель на начало Input для текущего Batch
+ # Input: [batch, cin, h, w]
+ src_base = input_ptr + batch_idx * stride_in_n
+
+ # Указатель на начало Weights для текущего Out Channel
+ # Weight: [cout, cin, kh, kw]
wei_base = weight_ptr + out_ch * stride_w_out
- acc = tl.zeros([BLOCK_W], dtype=tl.float32)
+ # --- 3. Аккумулятор (Register File) ---
+ # Теперь это 2D массив [BLOCK_H, BLOCK_W]
+ acc = tl.zeros([BLOCK_H, BLOCK_W], dtype=tl.float32)
- # === ОПТИМИЗИРОВАННЫЙ ПОРЯДОК ЦИКЛОВ ===
- # cin (внешний) -> kh, kw (внутренние) для лучшей локальности памяти
+ # --- 4. Основной цикл ---
for cin in range(C_IN):
- in_ch_ptr = in_base + cin * stride_in_c
- wei_ch_ptr = wei_base + cin * stride_w_in
+ # Сдвигаем указатели на текущий входной канал
+ src_ch = src_base + cin * stride_in_c
+ wei_ch = wei_base + cin * stride_w_in
for kh in range(K):
- in_row_ptr = in_ch_ptr + kh * stride_in_h
- wei_row_ptr = wei_ch_ptr + kh * stride_w_h
+ # Pre-calc смещения по вертикали для входа
+ # Input H index = (offs_h + kh)
+ # Broadcasting: (BLOCK_H, 1)
+ curr_h_in = offs_h[:, None] + kh
+ src_row_ptr = src_ch + curr_h_in * stride_in_h
+ # Смещение веса по высоте
+ wei_row_ptr = wei_ch + kh * stride_w_h
+
for kw in range(K):
- # Загрузка веса - минимальный overhead
+ # --- A. Загрузка Веса (Scalar broadcast) ---
+ # Загружаем 1 скаляр, используем для всего блока [BLOCK_H, BLOCK_W]
wei_val = tl.load(wei_row_ptr + kw * stride_w_w)
- # Загрузка входа - правильные индексы
- # Input: [batch, cin, out_h+kh, out_w+kw]
- in_ptrs = in_row_ptr + (offs_w + kw) * stride_in_w
- in_val = tl.load(in_ptrs, mask=mask_w, other=0.0)
+ # --- B. Загрузка Входа (2D Block Load) ---
+ # Input W index = (offs_w + kw)
+ # Ptr = src_row_ptr (зависит от H) + (W смещение)
+ # Размерность: [BLOCK_H, 1] + [1, BLOCK_W] -> [BLOCK_H, BLOCK_W]
+ src_ptrs = src_row_ptr + (offs_w[None, :] + kw) * stride_in_w
- # Аккумуляция
- acc = acc + in_val * wei_val
-
- # Запись
- tl.store(out_base + offs_w * stride_out_w, acc, mask=mask_w)
+ # Маска: проверяем валидность H (выхода) и W (выхода)
+ # Примечание: padding=0, stride=1 гарантируют, что если output внутри границ,
+ # то input (out + k) тоже внутри границ (при валидных размерах тензоров).
+ # Используем комбинированную маску mask_h & mask_w
+ val_in = tl.load(src_ptrs, mask=(mask_h[:, None] & mask_w[None, :]), other=0.0)
+
+ # --- C. FMA ---
+ acc = acc + val_in * wei_val
+ # --- 5. Запись результата ---
+ # Output Ptr: dst_base + h * stride_h + w * stride_w
+ offs_out = dst_base + offs_h[:, None] * stride_out_h + offs_w[None, :] * stride_out_w
+ tl.store(offs_out, acc, mask=(mask_h[:, None] & mask_w[None, :]))
+
def custom_kernel(data):
- """Вход: (input_tensor, kernel, output_tensor)."""
-
input_tensor, kernel, output_tensor = data
- input_tensor = input_tensor.contiguous()
- kernel = kernel.contiguous()
+ # Обеспечиваем memory layout
+ if not input_tensor.is_contiguous():
+ input_tensor = input_tensor.contiguous()
+ if not kernel.is_contiguous():
+ kernel = kernel.contiguous()
batch, c_in, h_in, w_in = input_tensor.shape
c_out, _, k_h, k_w = kernel.shape
⋯ 1 unchanged lines
h_out = h_in - k_h + 1
w_out = w_in - k_w + 1
+ # Grid Calculation
+ # X: Тайлы по ширине
+ # Y: Тайлы по высоте (теперь делим на BLOCK_H!)
+ # Z: Batch * OutChannels
grid = lambda META: (
triton.cdiv(w_out, META['BLOCK_W']),
- h_out,
+ triton.cdiv(h_out, META['BLOCK_H']),
batch * c_out
)
- conv2d_kernel[grid](
+ conv2d_kernel_tiled[grid](
input_tensor, kernel, output_tensor,
*input_tensor.stride(),
*kernel.stride(),
⋯ 3 unchanged lines
)
return output_tensor
-
scrolls · 184 diff lines total

Best evidence level for this revision: reported

JSON