submission 99237
Petr_Rocoss · python · License unknown
Use it
Vendorable · source mirrored · license unknownView source →
No package. Vendor the mirrored source: 186 lines, June 9 Researcher Reciprocity License v1.0.
base.py
curl "https://kernelindex.com/api/v1/implementations/kernelbot-conv2d-v2-99237?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
Reported · How evidence levels are derived →
Source and license
sourceavailable
revision digestsha256:cceb32844c49f974b19f4884dd32b6282eedbc6e5bcc1ab915ccb843e5769e85
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 = 8
triton.Config({'BLOCK_H': 16, 'BLOCK_W': 128}, num_warps=8, num_stages=4),stages = 4
triton.Config({'BLOCK_H': 16, 'BLOCK_W': 128}, num_warps=8, num_stages=4),Kernel source
base.py186 lines
import torch
import triton
import triton.language as tl
@triton.autotune(
configs=[
# === A100 (Ampere) Specific Configs ===
# Ampere имеет меньше Shared Memory на SM, чем Hopper.
# num_stages > 5 часто снижают occupancy. Оптимум: 3-5.
# 1. Balanced Reuse & Vectorization (Золотой стандарт A100)
triton.Config({'BLOCK_H': 16, 'BLOCK_W': 128}, num_warps=8, num_stages=4),
triton.Config({'BLOCK_H': 16, 'BLOCK_W': 64}, num_warps=8, num_stages=4),
# 2. High Bandwidth (Широкие транзакции)
triton.Config({'BLOCK_H': 8, 'BLOCK_W': 256}, num_warps=8, num_stages=4),
triton.Config({'BLOCK_H': 8, 'BLOCK_W': 128}, num_warps=8, num_stages=5),
# 3. High Compute Density (Меньше загрузок весов)
triton.Config({'BLOCK_H': 32, 'BLOCK_W': 64}, num_warps=8, num_stages=3),
# === Fallback / L4 / T4 ===
triton.Config({'BLOCK_H': 8, 'BLOCK_W': 64}, num_warps=4, num_stages=3),
triton.Config({'BLOCK_H': 4, 'BLOCK_W': 128}, num_warps=4, num_stages=3),
],
key=['W_OUT', 'H_OUT', 'C_IN', 'K'],
)
@triton.jit
def conv2d_kernel_a100_ultra(
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
):
"""
Ultra-Optimized Conv2D for A100.
Focus: Pointer Chasing + High Weight Reuse + Optimal Stage count.
"""
# --- 1. Grid Layout ---
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. Static Coordinate & Mask Gen ---
# Генерация смещений
offs_h = pid_h * BLOCK_H + tl.arange(0, BLOCK_H)
offs_w = pid_w * BLOCK_W + tl.arange(0, BLOCK_W)
# Предварительный расчет масок.
# Вычисляем 1 раз и используем маскированное сохранение только в конце.
# Для загрузок используем маску, если нужно, но boundary check вынесен.
mask_h = offs_h < H_OUT
mask_w = offs_w < W_OUT
mask_block = mask_h[:, None] & mask_w[None, :]
# --- 3. Smart Pointer Setup ---
# Output Ptr [BLOCK_H, BLOCK_W]
# Используем broadcasting для создания 2D сетки адресов
# Base + Batch + Channel + Height offset + Width 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 Ptr Base [BLOCK_H, BLOCK_W]
# Начало окна свертки для тайла
ptr_in_base = input_ptr + \
batch_idx * stride_in_n + \
(offs_h[:, None] * stride_in_h) + \
(offs_w[None, :] * stride_in_w)
# Weight Ptr Base (Scalar)
ptr_wei_base = weight_ptr + out_ch * stride_w_out
# Accumulator (Registers)
# fp32 accumulate is standard for A100 (TF32 ops used underneath)
acc = tl.zeros([BLOCK_H, BLOCK_W], dtype=tl.float32)
# --- 4. Hot Loop (Pointer Chasing) ---
# Локальные переменные для указателей, чтобы избежать memory traffic
curr_in_ch = ptr_in_base
curr_wei_ch = ptr_wei_base
# Внешний цикл по каналам (Reduction)
for cin in range(C_IN):
# Временные указатели для Spatial Dimensions
curr_in_row = curr_in_ch
curr_wei_row = curr_wei_ch
# Проход по высоте ядра
for kh in range(K):
# Входим в inner-most loop.
# Копируем указатели. Компилятор развернет это в регистры.
curr_in_ptr = curr_in_row
curr_wei_ptr = curr_wei_row
# Проход по ширине ядра
# Если K известно (например 3), компилятор полностью развернет этот цикл.
for kw in range(K):
# 1. Load Weight (Scalar -> Broadcast)
# Загружаем 1 вес. A100 L1 кэш отлично справляется с этим.
# Адрес уже посчитан инкрементом.
wei_val = tl.load(curr_wei_ptr)
# 2. Load Input (Vectorized Block)
# Загружаем [BLOCK_H, BLOCK_W] значений.
# В A100 это идет через L1/Tex кэш.
in_val = tl.load(curr_in_ptr, mask=mask_block, other=0.0)
# 3. FMA (Fused Multiply Add)
acc = acc + in_val * wei_val
# 4. Pointer Increment (Cheap ALU op)
# Вместо умножения `idx * stride`, делаем `ptr += stride`.
# stride_w_w и stride_in_w обычно равны 1,
# но мы используем переменные для универсальности.
curr_wei_ptr += stride_w_w
curr_in_ptr += stride_in_w
# Сдвигаем строку ядра вниз
curr_in_row += stride_in_h
curr_wei_row += stride_w_h
# Переходим к следующему каналу
curr_in_ch += stride_in_c
curr_wei_ch += stride_w_in
# --- 5. Writeback ---
tl.store(ptr_out, acc, mask=mask_block)
def custom_kernel(data):
"""
A100 Optimized Entry Point.
"""
input_tensor, kernel, output_tensor = data
# 1. Memory layout check
# Triton векторизация работает x4 быстрее на contiguous данных
if not input_tensor.is_contiguous():
input_tensor = input_tensor.contiguous()
if not kernel.is_contiguous():
kernel = kernel.contiguous()
# 2. Shape extraction
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 strategy
# Делим выходное изображение на блоки.
# Z-измерение объединяет Batch и Output Channels для максимального параллелизма.
grid = lambda META: (
triton.cdiv(w_out, META['BLOCK_W']),
triton.cdiv(h_out, META['BLOCK_H']),
batch * c_out
)
# 4. Launch
conv2d_kernel_a100_ultra[grid](
input_tensor, kernel, output_tensor,
# Pass strides directly from tensors
*input_tensor.stride(),
*kernel.stride(),
*output_tensor.stride(),
# Pass dimensions
h_in, w_in, h_out, w_out,
c_in, c_out, k_h,
# META params (BLOCK_H, BLOCK_W) handled by autotuner
)
return output_tensor
scrolls · 186 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 99219.
⋯ 3 unchanged lines@triton.autotune(configs=[- # === H100/B200 Hopper Architecture ===- # Максимальный prefetch (num_stages=7) для HBM3- triton.Config({'BLOCK_H': 8, 'BLOCK_W': 256}, num_warps=8, num_stages=7),- triton.Config({'BLOCK_H': 16, 'BLOCK_W': 128}, num_warps=8, num_stages=6),- triton.Config({'BLOCK_H': 8, 'BLOCK_W': 128}, num_warps=8, num_stages=6),+ # === A100 (Ampere) Specific Configs ===+ # Ampere имеет меньше Shared Memory на SM, чем Hopper.+ # num_stages > 5 часто снижают occupancy. Оптимум: 3-5.- # === A100 Ampere ===- triton.Config({'BLOCK_H': 16, 'BLOCK_W': 64}, num_warps=8, num_stages=5),- triton.Config({'BLOCK_H': 4, 'BLOCK_W': 256}, num_warps=8, num_stages=5),+ # 1. Balanced Reuse & Vectorization (Золотой стандарт A100)+ triton.Config({'BLOCK_H': 16, 'BLOCK_W': 128}, num_warps=8, num_stages=4),+ triton.Config({'BLOCK_H': 16, 'BLOCK_W': 64}, num_warps=8, num_stages=4),- # === L4 / Balanced ===- triton.Config({'BLOCK_H': 4, 'BLOCK_W': 128}, num_warps=4, num_stages=4),- triton.Config({'BLOCK_H': 8, 'BLOCK_W': 64}, num_warps=4, num_stages=4),+ # 2. High Bandwidth (Широкие транзакции)+ triton.Config({'BLOCK_H': 8, 'BLOCK_W': 256}, num_warps=8, num_stages=4),+ triton.Config({'BLOCK_H': 8, 'BLOCK_W': 128}, num_warps=8, num_stages=5),++ # 3. High Compute Density (Меньше загрузок весов)+ triton.Config({'BLOCK_H': 32, 'BLOCK_W': 64}, num_warps=8, num_stages=3),- # === Fallback для малых размеров ===- triton.Config({'BLOCK_H': 2, 'BLOCK_W': 64}, num_warps=4, num_stages=3),+ # === Fallback / L4 / T4 ===+ triton.Config({'BLOCK_H': 8, 'BLOCK_W': 64}, num_warps=4, num_stages=3),+ triton.Config({'BLOCK_H': 4, 'BLOCK_W': 128}, num_warps=4, num_stages=3),],key=['W_OUT', 'H_OUT', 'C_IN', 'K'],)@triton.jit- def conv2d_kernel_ultimate(+ def conv2d_kernel_a100_ultra(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 linesBLOCK_H: tl.constexpr, BLOCK_W: tl.constexpr):"""- Ultimate Conv2D Kernel для A100/H100/B200/L4.-- Ключевые оптимизации:- 1. Incremental pointer updates (избегаем умножений в цикле)- 2. Aggressive prefetch через num_stages=6-7- 3. 2D tiling с adaptive block sizes- 4. Mask hoisting (маски вычисляются один раз)- 5. Coalesced memory access через broadcasting+ Ultra-Optimized Conv2D for A100.+ Focus: Pointer Chasing + High Weight Reuse + Optimal Stage count."""- # === 1. Grid Decoding ===+ # --- 1. Grid Layout ---pid_w = tl.program_id(0)pid_h = tl.program_id(1)pid_z = tl.program_id(2)-+batch_idx = pid_z // C_OUTout_ch = pid_z % C_OUT-- # === 2. Coordinate Generation ===++ # --- 2. Static Coordinate & Mask Gen ---+ # Генерация смещенийoffs_h = pid_h * BLOCK_H + tl.arange(0, BLOCK_H)offs_w = pid_w * BLOCK_W + tl.arange(0, BLOCK_W)-- # === 3. Mask Hoisting (вычисляем один раз) ===++ # Предварительный расчет масок.+ # Вычисляем 1 раз и используем маскированное сохранение только в конце.+ # Для загрузок используем маску, если нужно, но boundary check вынесен.mask_h = offs_h < H_OUTmask_w = offs_w < W_OUT- mask_2d = mask_h[:, None] & mask_w[None, :]+ mask_block = mask_h[:, None] & mask_w[None, :]++ # --- 3. Smart Pointer Setup ---++ # Output Ptr [BLOCK_H, BLOCK_W]+ # Используем broadcasting для создания 2D сетки адресов+ # Base + Batch + Channel + Height offset + Width 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)- # === 4. Base Pointers (2D Broadcasting) ===- # Output [batch, out_ch, h, w]- 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 Ptr Base [BLOCK_H, BLOCK_W]+ # Начало окна свертки для тайла+ ptr_in_base = input_ptr + \+ batch_idx * stride_in_n + \+ (offs_h[:, None] * stride_in_h) + \+ (offs_w[None, :] * stride_in_w)- # Input base [batch, ?, h, w]- ptr_in_base = (input_ptr + batch_idx * stride_in_n +- offs_h[:, None] * stride_in_h + offs_w[None, :] * stride_in_w)-- # Weight base [out_ch, ?, ?, ?]+ # Weight Ptr Base (Scalar)ptr_wei_base = weight_ptr + out_ch * stride_w_out-- # === 5. Accumulator ===++ # Accumulator (Registers)+ # fp32 accumulate is standard for A100 (TF32 ops used underneath)acc = tl.zeros([BLOCK_H, BLOCK_W], dtype=tl.float32)-- # === 6. Main Loop (Pointer Chasing Optimization) ===- # Текущие указатели для каналов- ptr_in_ch = ptr_in_base- ptr_wei_ch = ptr_wei_base-++ # --- 4. Hot Loop (Pointer Chasing) ---++ # Локальные переменные для указателей, чтобы избежать memory traffic+ curr_in_ch = ptr_in_base+ curr_wei_ch = ptr_wei_base++ # Внешний цикл по каналам (Reduction)for cin in range(C_IN):- # Локальные указатели для spatial loops- ptr_in_kh = ptr_in_ch- ptr_wei_kh = ptr_wei_ch+ # Временные указатели для Spatial Dimensions+ curr_in_row = curr_in_ch+ curr_wei_row = curr_wei_ch++ # Проход по высоте ядраfor kh in range(K):- # Еще более локальные указатели для kw loop- ptr_in_kw = ptr_in_kh- ptr_wei_kw = ptr_wei_kh+ # Входим в inner-most loop.+ # Копируем указатели. Компилятор развернет это в регистры.+ curr_in_ptr = curr_in_row+ curr_wei_ptr = curr_wei_row++ # Проход по ширине ядра+ # Если K известно (например 3), компилятор полностью развернет этот цикл.for kw in range(K):- # === A. Load Weight (scalar broadcast) ===- w_val = tl.load(ptr_wei_kw)+ # 1. Load Weight (Scalar -> Broadcast)+ # Загружаем 1 вес. A100 L1 кэш отлично справляется с этим.+ # Адрес уже посчитан инкрементом.+ wei_val = tl.load(curr_wei_ptr)- # === B. Load Input (vectorized 2D block) ===- in_val = tl.load(ptr_in_kw, mask=mask_2d, other=0.0)+ # 2. Load Input (Vectorized Block)+ # Загружаем [BLOCK_H, BLOCK_W] значений.+ # В A100 это идет через L1/Tex кэш.+ in_val = tl.load(curr_in_ptr, mask=mask_block, other=0.0)- # === C. FMA ===- acc += in_val * w_val+ # 3. FMA (Fused Multiply Add)+ acc = acc + in_val * wei_val- # Increment по ширине (kw)- ptr_in_kw += stride_in_w- ptr_wei_kw += stride_w_w+ # 4. Pointer Increment (Cheap ALU op)+ # Вместо умножения `idx * stride`, делаем `ptr += stride`.+ # stride_w_w и stride_in_w обычно равны 1,+ # но мы используем переменные для универсальности.+ curr_wei_ptr += stride_w_w+ curr_in_ptr += stride_in_w++ # Сдвигаем строку ядра вниз+ curr_in_row += stride_in_h+ curr_wei_row += stride_w_h- # Increment по высоте (kh)- ptr_in_kh += stride_in_h- ptr_wei_kh += stride_w_h-- # Increment по каналам (cin)- ptr_in_ch += stride_in_c- ptr_wei_ch += stride_w_in+ # Переходим к следующему каналу+ curr_in_ch += stride_in_c+ curr_wei_ch += stride_w_in- # === 7. Store Result ===- tl.store(ptr_out, acc, mask=mask_2d)+ # --- 5. Writeback ---+ tl.store(ptr_out, acc, mask=mask_block)def custom_kernel(data):"""- Production-ready wrapper для Conv2D kernel.+ A100 Optimized Entry Point."""input_tensor, kernel, output_tensor = data- # Гарантируем contiguous layout для coalesced access- input_tensor = input_tensor.contiguous()- kernel = kernel.contiguous()+ # 1. Memory layout check+ # Triton векторизация работает x4 быстрее на contiguous данных+ if not input_tensor.is_contiguous():+ input_tensor = input_tensor.contiguous()+ if not kernel.is_contiguous():+ kernel = kernel.contiguous()- # Размеры+ # 2. Shape extractionbatch, c_in, h_in, w_in = input_tensor.shapec_out, _, k_h, k_w = kernel.shapeh_out = h_in - k_h + 1w_out = w_in - k_w + 1- # Grid configuration+ # 3. Grid strategy+ # Делим выходное изображение на блоки.+ # Z-измерение объединяет Batch и Output Channels для максимального параллелизма.grid = lambda META: (triton.cdiv(w_out, META['BLOCK_W']),triton.cdiv(h_out, META['BLOCK_H']),batch * c_out)- # Launch kernel- conv2d_kernel_ultimate[grid](+ # 4. Launch+ conv2d_kernel_a100_ultra[grid](input_tensor, kernel, output_tensor,+ # Pass strides directly from tensors*input_tensor.stride(),*kernel.stride(),*output_tensor.stride(),+ # Pass dimensionsh_in, w_in, h_out, w_out,c_in, c_out, k_h,+ # META params (BLOCK_H, BLOCK_W) handled by autotuner)return output_tensor-
scrolls · 261 diff lines total
Best evidence level for this revision: reported
JSON