gpt-5.5-priority · original · l123_single_gpt
correct 17_Conv2d_InstanceNorm_Divide.py
model
gpt-5.5-priority
turns / max
1 / 1
tool calls
1
tokens (total)
0
wall clock
—
truncated
no
backend
cuda fp32
variant
original
runtime
3.96 μs
ref runtime
4.99 μs
speedup
1.26x
started
2026-05-05T01:12:15Z
timingkernelbench.timing
kernel runtime
3.96 μs
ref runtime
4.99 μs
speedup
1.26x
kernel mean / median / std
3.96 / — / 0.46 μs
ref mean / median / std
4.99 / — / 0.38 μs
numerical precisioneval_kernel_against_ref
max abs error
8.34e-06
mean abs error
1.35e-07
max rel error
701034.25
mean rel error
0.01
gpu memoryextended_metrics.measure_memory
kernel peak
2530.06 MB
ref peak
2530.19 MB
kernel / ref
1.00x
kernel launches / fusiontorch.profiler
kernel launches
9
ref launches
24
fusion ratio (ref / kernel)
2.67x
total cuda time
11703 μs
energyNVML (pynvml)
kernel mJ / run
1682.76
ref mJ / run
481.22
ratio (ref / kernel)
0.29x
avg power
431.10 W
ref avg power
97.27 W
SOL (speed-of-light)nsight_hardware_counters
SOL score (0–1)
1.000
dram util %
100.0%
compute util %
64.5%
bottleneck
memory-bound
dominant pipe
tensor-core
arithmetic intensity
—
ridge point
295.22
roofline / occupancynsight_hardware_counters
dram bandwidth
9014.80 GB/s
dram util %
100.0%
fp32 tflops
—
fp32 util %
—
fp16 tflops
—
occupancy %
306.7%
bottleneck
memory-bound
dominant pipe %
64.5%
arithmetic intensity
—
ridge point
295.22
L1 hit %
—
L2 hit %
313.5%
ld sectors / req
39.83
st sectors / req
—
regs / thread
348
smem / block
81152 B
block size
1024
peak bw
3350.00 GB/s
peak fp32 tflops
67.00
peak fp16 tflops
1979.00
warp stalls (top 5)nsight
long_scoreboard
20189.5%
short_scoreboard
987.0%
mio_throttle
981.5%
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn

class Model(nn.Module):
    """
    Simple model that performs a convolution, applies Instance Normalization, and divides by a constant.
    """
    def __init__(self, in_channels, out_channels, kernel_size, divide_by):
        super(Model, self).__init__()
        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size)
        self.instance_norm = nn.InstanceNorm2d(out_channels)
        self.divide_by = divide_by

    def forward(self, x):
        x = self.conv(x)
        x = self.instance_norm(x)
        x = x / self.divide_by
        return x

batch_size = 128
in_channels  = 64  
out_channels = 128  
height = width = 128  
kernel_size = 3
divide_by = 2.0

def get_inputs():
    return [torch.rand(batch_size, in_channels, height, width)]

def get_init_inputs():
    return [in_channels, out_channels, kernel_size, divide_by]
turn 0 · FINAL · 1 tool call(s) · 42.6s turn · 42.6s LLM · 6,732 chars (click to expand)
turn 042.6s turn · 42.6s LLM · 0.0s tools · FINAL
call → submit_kernel
callsubmit_kernel { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n\ntorch::Tensor instance_norm_div(torch::Tensor input, double divide_by);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAException.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#ifndef BLOCK_SIZE\n#define BLOCK_SIZE 256\n#endif\n\n__global__ void inst_norm_div_vec4_kernel(const float* __restrict__ x,\n float* __restrict__ y,\n int m4,\n float div_by) {\n const int nc = blockIdx.x;\n const float4* __restrict__ x4 = reinterpret_cast<const float4*>(x + ((long long)nc) * ((long long)m4) * 4LL);\n float4* __restrict__ y4 = reinterpret_cast<float4*>(y + ((long long)nc) * ((long long)m4) * 4LL);\n\n float sum = 0.0f;\n float sumsq = 0.0f;\n\n for (int i = threadIdx.x; i < m4; i += BLOCK_SIZE) {\n float4 v = x4[i];\n sum += v.x + v.y + v.z + v.w;\n sumsq = fmaf(v.x, v.x, sumsq);\n sumsq = fmaf(v.y, v.y, sumsq);\n sumsq = fmaf(v.z, v.z, sumsq);\n sumsq = fmaf(v.w, v.w, sumsq);\n }\n\n __shared__ float s_sum[BLOCK_SIZE];\n __shared__ float s_sumsq[BLOCK_SIZE];\n s_sum[threadIdx.x] = sum;\n s_sumsq[threadIdx.x] = sumsq;\n __syncthreads();\n\n #pragma unroll\n for (int stride = BLOCK_SIZE / 2; stride > 0; stride >>= 1) {\n if (threadIdx.x < stride) {\n s_sum[threadIdx.x] += s_sum[threadIdx.x + stride];\n s_sumsq[threadIdx.x] += s_sumsq[threadIdx.x + stride];\n }\n __syncthreads();\n }\n\n const float inv_m = 1.0f / (float)(m4 * 4);\n const float mean = s_sum[0] * inv_m;\n float var = s_sumsq[0] * inv_m - mean * mean;\n var = var > 0.0f ? var : 0.0f;\n const float scale = rsqrtf(var + 1.0e-5f) / div_by;\n\n for (int i = threadIdx.x; i < m4; i += BLOCK_SIZE) {\n float4 v = x4[i];\n v.x = (v.x - mean) * scale;\n v.y = (v.y - mean) * scale;\n v.z = (v.z - mean) * scale;\n v.w = (v.w - mean) * scale;\n y4[i] = v;\n }\n}\n\n__global__ void inst_norm_div_scalar_kernel(const float* __restrict__ x,\n float* __restrict__ y,\n int m,\n float div_by) {\n const int nc = blockIdx.x;\n const long long base = ((long long)nc) * (long long)m;\n\n float sum = 0.0f;\n float sumsq = 0.0f;\n for (int i = threadIdx.x; i < m; i += BLOCK_SIZE) {\n float v = x[base + i];\n sum += v;\n sumsq = fmaf(v, v, sumsq);\n }\n\n __shared__ float s_sum[BLOCK_SIZE];\n __shared__ float s_sumsq[BLOCK_SIZE];\n s_sum[threadIdx.x] = sum;\n s_sumsq[threadIdx.x] = sumsq;\n __syncthreads();\n\n #pragma unroll\n for (int stride = BLOCK_SIZE / 2; stride > 0; stride >>= 1) {\n if (threadIdx.x < stride) {\n s_sum[threadIdx.x] += s_sum[threadIdx.x + stride];\n s_sumsq[threadIdx.x] += s_sumsq[threadIdx.x + stride];\n }\n __syncthreads();\n }\n\n const float inv_m = 1.0f / (float)m;\n const float mean = s_sum[0] * inv_m;\n float var = s_sumsq[0] * inv_m - mean * mean;\n var = var > 0.0f ? var : 0.0f;\n const float scale = rsqrtf(var + 1.0e-5f) / div_by;\n\n for (int i = threadIdx.x; i < m; i += BLOCK_SIZE) {\n y[base + i] = (x[base + i] - mean) * scale;\n }\n}\n\ntorch::Tensor instance_norm_div(torch::Tensor input, double divide_by) {\n TORCH_CHECK(input.is_cuda(), \"input must be CUDA\");\n TORCH_CHECK(input.scalar_type() == at::kFloat, \"only float32 is supported\");\n TORCH_CHECK(input.dim() == 4, \"expected NCHW tensor\");\n TORCH_CHECK(input.is_contiguous(), \"input must be contiguous\");\n\n auto output = torch::empty_like(input);\n const int n = (int)input.size(0);\n const int c = (int)input.size(1);\n const int h = (int)input.size(2);\n const int w = (int)input.size(3);\n const int m = h * w;\n const int blocks = n * c;\n const float div = (float)divide_by;\n\n if (blocks > 0 && m > 0) {\n const float* x = input.data_ptr<float>();\n float* y = output.data_ptr<float>();\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n if ((m & 3) == 0) {\n inst_norm_div_vec4_kernel<<<blocks, BLOCK_SIZE, 0, stream>>>(x, y, m >> 2, div);\n } else {\n inst_norm_div_scalar_kernel<<<blocks, BLOCK_SIZE, 0, stream>>>(x, y, m, div);\n }\n C10_CUDA_KERNEL_LAUNCH_CHECK();\n }\n return output;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"modelnew_instnorm_div_ext_v1\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"instance_norm_div\"],\n extra_cflags=[\"-O3\"],\n extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"],\n verbose=False,\n)\n\n\nclass ModelNew(nn.Module):\n def __init__(self, in_channels, out_channels, kernel_size, divide_by):\n super(ModelNew, self).__init__()\n self.conv = nn.Conv2d(in_channels, out_channels, kernel_size)\n self.instance_norm = nn.InstanceNorm2d(out_channels)\n self.divide_by = float(divide_by)\n\n def forward(self, x):\n y = self.conv(x)\n return _ext.instance_norm_div(y, self.divide_by)\n" }
result ← submit_kernel (ok)
oksubmit_kernel submit_kernel PASSED: (5 / 5) correctness trials all passed. Kernel runtime: 3.96 μs Runtime stats: mean=3.96μs median=?μs std=0.46μs Numerical precision: max_abs_err=8.34e-06 mean_abs_err=1.35e-07 max_rel_err=7.01e+05 Memory: 2530.06 MB peak (ref: 2530.19 MB, ratio: 1.0x) Kernel launches: 9 (ref: 24, fusion ratio: 2.6667) Energy: 1682.76 mJ/run (ref: 481.22 mJ, ratio: 0.286x) SOL score: 1.0
final submitted kernel (165 lines, 5,334 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline

_cpp_src = r"""
#include <torch/extension.h>

torch::Tensor instance_norm_div(torch::Tensor input, double divide_by);
"""

_cuda_src = r"""
#include <torch/extension.h>
#include <ATen/cuda/CUDAContext.h>
#include <c10/cuda/CUDAException.h>
#include <cuda.h>
#include <cuda_runtime.h>

#ifndef BLOCK_SIZE
#define BLOCK_SIZE 256
#endif

__global__ void inst_norm_div_vec4_kernel(const float* __restrict__ x,
                                          float* __restrict__ y,
                                          int m4,
                                          float div_by) {
    const int nc = blockIdx.x;
    const float4* __restrict__ x4 = reinterpret_cast<const float4*>(x + ((long long)nc) * ((long long)m4) * 4LL);
    float4* __restrict__ y4 = reinterpret_cast<float4*>(y + ((long long)nc) * ((long long)m4) * 4LL);

    float sum = 0.0f;
    float sumsq = 0.0f;

    for (int i = threadIdx.x; i < m4; i += BLOCK_SIZE) {
        float4 v = x4[i];
        sum += v.x + v.y + v.z + v.w;
        sumsq = fmaf(v.x, v.x, sumsq);
        sumsq = fmaf(v.y, v.y, sumsq);
        sumsq = fmaf(v.z, v.z, sumsq);
        sumsq = fmaf(v.w, v.w, sumsq);
    }

    __shared__ float s_sum[BLOCK_SIZE];
    __shared__ float s_sumsq[BLOCK_SIZE];
    s_sum[threadIdx.x] = sum;
    s_sumsq[threadIdx.x] = sumsq;
    __syncthreads();

    #pragma unroll
    for (int stride = BLOCK_SIZE / 2; stride > 0; stride >>= 1) {
        if (threadIdx.x < stride) {
            s_sum[threadIdx.x] += s_sum[threadIdx.x + stride];
            s_sumsq[threadIdx.x] += s_sumsq[threadIdx.x + stride];
        }
        __syncthreads();
    }

    const float inv_m = 1.0f / (float)(m4 * 4);
    const float mean = s_sum[0] * inv_m;
    float var = s_sumsq[0] * inv_m - mean * mean;
    var = var > 0.0f ? var : 0.0f;
    const float scale = rsqrtf(var + 1.0e-5f) / div_by;

    for (int i = threadIdx.x; i < m4; i += BLOCK_SIZE) {
        float4 v = x4[i];
        v.x = (v.x - mean) * scale;
        v.y = (v.y - mean) * scale;
        v.z = (v.z - mean) * scale;
        v.w = (v.w - mean) * scale;
        y4[i] = v;
    }
}

__global__ void inst_norm_div_scalar_kernel(const float* __restrict__ x,
                                            float* __restrict__ y,
                                            int m,
                                            float div_by) {
    const int nc = blockIdx.x;
    const long long base = ((long long)nc) * (long long)m;

    float sum = 0.0f;
    float sumsq = 0.0f;
    for (int i = threadIdx.x; i < m; i += BLOCK_SIZE) {
        float v = x[base + i];
        sum += v;
        sumsq = fmaf(v, v, sumsq);
    }

    __shared__ float s_sum[BLOCK_SIZE];
    __shared__ float s_sumsq[BLOCK_SIZE];
    s_sum[threadIdx.x] = sum;
    s_sumsq[threadIdx.x] = sumsq;
    __syncthreads();

    #pragma unroll
    for (int stride = BLOCK_SIZE / 2; stride > 0; stride >>= 1) {
        if (threadIdx.x < stride) {
            s_sum[threadIdx.x] += s_sum[threadIdx.x + stride];
            s_sumsq[threadIdx.x] += s_sumsq[threadIdx.x + stride];
        }
        __syncthreads();
    }

    const float inv_m = 1.0f / (float)m;
    const float mean = s_sum[0] * inv_m;
    float var = s_sumsq[0] * inv_m - mean * mean;
    var = var > 0.0f ? var : 0.0f;
    const float scale = rsqrtf(var + 1.0e-5f) / div_by;

    for (int i = threadIdx.x; i < m; i += BLOCK_SIZE) {
        y[base + i] = (x[base + i] - mean) * scale;
    }
}

torch::Tensor instance_norm_div(torch::Tensor input, double divide_by) {
    TORCH_CHECK(input.is_cuda(), "input must be CUDA");
    TORCH_CHECK(input.scalar_type() == at::kFloat, "only float32 is supported");
    TORCH_CHECK(input.dim() == 4, "expected NCHW tensor");
    TORCH_CHECK(input.is_contiguous(), "input must be contiguous");

    auto output = torch::empty_like(input);
    const int n = (int)input.size(0);
    const int c = (int)input.size(1);
    const int h = (int)input.size(2);
    const int w = (int)input.size(3);
    const int m = h * w;
    const int blocks = n * c;
    const float div = (float)divide_by;

    if (blocks > 0 && m > 0) {
        const float* x = input.data_ptr<float>();
        float* y = output.data_ptr<float>();
        cudaStream_t stream = at::cuda::getCurrentCUDAStream();
        if ((m & 3) == 0) {
            inst_norm_div_vec4_kernel<<<blocks, BLOCK_SIZE, 0, stream>>>(x, y, m >> 2, div);
        } else {
            inst_norm_div_scalar_kernel<<<blocks, BLOCK_SIZE, 0, stream>>>(x, y, m, div);
        }
        C10_CUDA_KERNEL_LAUNCH_CHECK();
    }
    return output;
}
"""

_ext = load_inline(
    name="modelnew_instnorm_div_ext_v1",
    cpp_sources=_cpp_src,
    cuda_sources=_cuda_src,
    functions=["instance_norm_div"],
    extra_cflags=["-O3"],
    extra_cuda_cflags=["-O3", "--use_fast_math"],
    verbose=False,
)


class ModelNew(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size, divide_by):
        super(ModelNew, self).__init__()
        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size)
        self.instance_norm = nn.InstanceNorm2d(out_channels)
        self.divide_by = float(divide_by)

    def forward(self, x):
        y = self.conv(x)
        return _ext.instance_norm_div(y, self.divide_by)