correct
7_Conv3d_ReLU_LeakyReLU_GELU_Sigmoid_BiasAdd.py
started
2026-05-05T01:04:17Z
timingkernelbench.timing
kernel mean / median / std
4.53 / — / 0.46 μs
ref mean / median / std
6.45 / — / 0.09 μs
numerical precisioneval_kernel_against_ref
gpu memoryextended_metrics.measure_memory
kernel launches / fusiontorch.profiler
fusion ratio (ref / kernel)
1.86x
energyNVML (pynvml)
ratio (ref / kernel)
2.50x
SOL (speed-of-light)nsight_hardware_counters
roofline / occupancynsight_hardware_counters
dram bandwidth
9460.35 GB/s
warp stalls (top 5)nsight
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn
class Model(nn.Module):
"""
Model that performs a 3D convolution, applies ReLU, LeakyReLU, GELU, Sigmoid activations, and bias in sequence.
"""
def __init__(self, in_channels, out_channels, kernel_size, bias_shape):
super(Model, self).__init__()
self.conv = nn.Conv3d(in_channels, out_channels, kernel_size)
self.bias = nn.Parameter(torch.randn(bias_shape))
def forward(self, x):
x = self.conv(x)
x = torch.relu(x)
x = torch.nn.functional.leaky_relu(x, negative_slope=0.01)
x = torch.nn.functional.gelu(x)
x = torch.sigmoid(x)
x = x + self.bias
return x
batch_size = 64
in_channels = 8
out_channels = 32
depth, height, width = 32, 64, 64
kernel_size = 3
bias_shape = (out_channels, 1, 1, 1)
def get_inputs():
return [torch.rand(batch_size, in_channels, depth, height, width)]
def get_init_inputs():
return [in_channels, out_channels, kernel_size, bias_shape]turn 029.9s turn · 29.9s LLM · 0.0s tools · FINAL
call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n\ntorch::Tensor fused_post_act_bias(torch::Tensor x, torch::Tensor bias);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\n__global__ void post_kernel(float* __restrict__ x,\n const float* __restrict__ bias,\n long long n_elem,\n int channels,\n int spatial) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n const float inv_sqrt2 = 0.70710678118654752440f;\n\n for (; idx < n_elem; idx += stride) {\n float v = x[idx];\n // ReLU followed by leaky_relu(negative_slope=0.01) is just ReLU.\n v = v > 0.0f ? v : 0.0f;\n // Exact GELU, matching torch.nn.functional.gelu default (approximate='none').\n float g = 0.5f * v * (1.0f + erff(v * inv_sqrt2));\n float s = 1.0f / (1.0f + expf(-g));\n int c = (int)((idx / spatial) % channels);\n x[idx] = s + bias[c];\n }\n}\n\ntorch::Tensor fused_post_act_bias(torch::Tensor x, torch::Tensor bias) {\n const long long n_elem = x.numel();\n if (n_elem == 0) return x;\n const int channels = (int)x.size(1);\n const int spatial = (int)(x.size(2) * x.size(3) * x.size(4));\n\n const int threads = 256;\n int blocks = (int)((n_elem + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n post_kernel<<<blocks, threads, 0, stream>>>(x.data_ptr<float>(),\n bias.data_ptr<float>(),\n n_elem,\n channels,\n spatial);\n return x;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"fused_conv3d_post_act_bias_ext_v1\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"fused_post_act_bias\"],\n extra_cflags=[\"-O3\"],\n extra_cuda_cflags=[\"-O3\"],\n verbose=False,\n)\n\n\nclass ModelNew(nn.Module):\n \"\"\"\n Conv3d followed by fused ReLU/LeakyReLU/GELU/Sigmoid/channel-bias.\n \"\"\"\n def __init__(self, in_channels, out_channels, kernel_size, bias_shape):\n super(ModelNew, self).__init__()\n self.conv = nn.Conv3d(in_channels, out_channels, kernel_size)\n self.bias = nn.Parameter(torch.randn(bias_shape))\n\n def forward(self, x):\n y = F.conv3d(x, self.conv.weight, self.conv.bias, self.conv.stride,\n self.conv.padding, self.conv.dilation, self.conv.groups)\n return _ext.fused_post_act_bias(y, self.bias)\n"
}
result ← submit_kernel (ok)
oksubmit_kernel
submit_kernel PASSED: (5 / 5) correctness trials all passed.
Kernel runtime: 4.53 μs
Runtime stats: mean=4.53μs median=?μs std=0.46μs
Numerical precision: max_abs_err=0.00e+00 mean_abs_err=0.00e+00 max_rel_err=0.00e+00
Memory: 2346.96 MB peak (ref: 2346.96 MB, ratio: 1.0x)
Kernel launches: 7 (ref: 13, fusion ratio: 1.8571)
Energy: 481.14 mJ/run (ref: 1201.28 mJ, ratio: 2.4967x)
SOL score: 1.0
final submitted kernel (83 lines, 2,870 chars) — full source, untruncated
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.cpp_extension import load_inline
_cpp_src = r"""
#include <torch/extension.h>
torch::Tensor fused_post_act_bias(torch::Tensor x, torch::Tensor bias);
"""
_cuda_src = r"""
#include <torch/extension.h>
#include <ATen/cuda/CUDAContext.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <math.h>
__global__ void post_kernel(float* __restrict__ x,
const float* __restrict__ bias,
long long n_elem,
int channels,
int spatial) {
long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;
long long stride = (long long)blockDim.x * gridDim.x;
const float inv_sqrt2 = 0.70710678118654752440f;
for (; idx < n_elem; idx += stride) {
float v = x[idx];
// ReLU followed by leaky_relu(negative_slope=0.01) is just ReLU.
v = v > 0.0f ? v : 0.0f;
// Exact GELU, matching torch.nn.functional.gelu default (approximate='none').
float g = 0.5f * v * (1.0f + erff(v * inv_sqrt2));
float s = 1.0f / (1.0f + expf(-g));
int c = (int)((idx / spatial) % channels);
x[idx] = s + bias[c];
}
}
torch::Tensor fused_post_act_bias(torch::Tensor x, torch::Tensor bias) {
const long long n_elem = x.numel();
if (n_elem == 0) return x;
const int channels = (int)x.size(1);
const int spatial = (int)(x.size(2) * x.size(3) * x.size(4));
const int threads = 256;
int blocks = (int)((n_elem + threads - 1) / threads);
if (blocks > 65535) blocks = 65535;
cudaStream_t stream = at::cuda::getCurrentCUDAStream();
post_kernel<<<blocks, threads, 0, stream>>>(x.data_ptr<float>(),
bias.data_ptr<float>(),
n_elem,
channels,
spatial);
return x;
}
"""
_ext = load_inline(
name="fused_conv3d_post_act_bias_ext_v1",
cpp_sources=_cpp_src,
cuda_sources=_cuda_src,
functions=["fused_post_act_bias"],
extra_cflags=["-O3"],
extra_cuda_cflags=["-O3"],
verbose=False,
)
class ModelNew(nn.Module):
"""
Conv3d followed by fused ReLU/LeakyReLU/GELU/Sigmoid/channel-bias.
"""
def __init__(self, in_channels, out_channels, kernel_size, bias_shape):
super(ModelNew, self).__init__()
self.conv = nn.Conv3d(in_channels, out_channels, kernel_size)
self.bias = nn.Parameter(torch.randn(bias_shape))
def forward(self, x):
y = F.conv3d(x, self.conv.weight, self.conv.bias, self.conv.stride,
self.conv.padding, self.conv.dilation, self.conv.groups)
return _ext.fused_post_act_bias(y, self.bias)