gpt-5.5-priority · original · l12_default_gpt
correct 39_Gemm_Scale_BatchNorm.py
model
gpt-5.5-priority
turns / max
8 / 10
tool calls
8
tokens (total)
0
wall clock
—
truncated
no
backend
cuda fp32
variant
original
runtime
11.20 μs
ref runtime
11.50 μs
speedup
1.03x
started
2026-05-02T08:55:48Z
timingkernelbench.timing
kernel runtime
11.20 μs
ref runtime
11.50 μs
speedup
1.03x
kernel mean / median / std
11.20 / — / 0.34 μs
ref mean / median / std
11.50 / — / 0.35 μs
numerical precisioneval_kernel_against_ref
max abs error
1.96e-05
mean abs error
1.61e-07
max rel error
478570.72
mean rel error
0.01
gpu memoryextended_metrics.measure_memory
kernel peak
931.22 MB
ref peak
933.22 MB
kernel / ref
1.00x
kernel launches / fusiontorch.profiler
kernel launches
12
ref launches
20
fusion ratio (ref / kernel)
1.67x
total cuda time
22082 μs
energyNVML (pynvml)
kernel mJ / run
1447.74
ref mJ / run
1447.92
ratio (ref / kernel)
1.00x
avg power
129.33 W
ref avg power
124.88 W
SOL (speed-of-light)nsight_hardware_counters
SOL score (0–1)
1.000
dram util %
100.0%
compute util %
100.0%
bottleneck
compute-bound
dominant pipe
FP32
arithmetic intensity
—
ridge point
20.00
roofline / occupancynsight_hardware_counters
dram bandwidth
6296.79 GB/s
dram util %
100.0%
fp32 tflops
—
fp32 util %
—
fp16 tflops
—
occupancy %
263.7%
bottleneck
compute-bound
dominant pipe %
100.8%
arithmetic intensity
—
ridge point
20.00
L1 hit %
—
L2 hit %
275.0%
ld sectors / req
27.71
st sectors / req
—
regs / thread
372
smem / block
41984 B
block size
896
peak bw
3350.00 GB/s
peak fp32 tflops
67.00
peak fp16 tflops
1979.00
warp stalls (top 5)nsight
long_scoreboard
9584.7%
short_scoreboard
1045.9%
mio_throttle
764.8%
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn

class Model(nn.Module):
    """
    Simple model that performs a matrix multiplication, scales the result, and applies batch normalization.
    """
    def __init__(self, in_features, out_features, scale_shape, eps=1e-5, momentum=0.1):
        super(Model, self).__init__()
        self.gemm = nn.Linear(in_features, out_features)
        self.scale = nn.Parameter(torch.randn(scale_shape))
        self.bn = nn.BatchNorm1d(out_features, eps=eps, momentum=momentum)

    def forward(self, x):
        x = self.gemm(x)
        x = x * self.scale
        x = self.bn(x)
        return x

batch_size = 16384
in_features = 4096
out_features = 4096
scale_shape = (out_features,)

def get_inputs():
    return [torch.rand(batch_size, in_features)]

def get_init_inputs():
    return [in_features, out_features, scale_shape]
turn 011.2s turn · 11.2s LLM · 0.0s tools
call → get_gpu_specs
callget_gpu_specs {}
result ← get_gpu_specs (ok)
okget_gpu_specs GPU specs for NVIDIA H100 80GB HBM3: total memory (runtime): 79.1 GB spec entry: H100 GPU Architecture: Hopper GPU Memory: 80GB Memory Bandwidth: 3.35 TB/s FP64 TFLOPS: 34 FP64 Tensor Core TFLOPS: 67 FP32 TFLOPS: 67 TF32 Tensor Core TFLOPS: 989 with sparsity BFLOAT16 Tensore Core TFLOPS: 1979 with sparsity FP16 Tensor Core TFLOPS: 1979 with sparsity FP8 Tensor Core TFLOPS: 3958 with sparsity INT8 Tensor Core TOPS: 3958 with sparsity Register File Size: 64K 32-bit registers per SM Maximum number of registers per thread: 255 Maximum number of thread blocks per SM: 32 Shared memory capacity per SM: 228 KB Maximum shared memory per thread block: 227 KB
turn 1 · 1 tool call(s) · 73.1s turn · 73.1s LLM · 17,727 chars (click to expand)
turn 173.1s turn · 73.1s LLM · 0.0s tools
reasoning
**Improving computation efficiency** I'm thinking about how to optimize my approach for block threads. Right now, loading rows with a terrible stride on columns isn’t working well for coalescing. It seems more efficient to compute reductions row-wise and cover tile columns appropriately. Plus, I need an efficient batch normalization reduction for N x M. I realize that PyTorch is already optimized, but my naive column-wise method is pretty awful, so better alternatives for training are essential. **Considering optimization strategies** I'm thinking about using evaluation optimization. The correctness tool can help reveal insights. I should implement both training using PyTorch functional methods and perhaps a custom naive approach, although it might be slower. If I benchmark training, slower performance may result from a focus on improving awful aspects. I could use torch.ops.aten.native_batch_norm too. After multiplying, I'll evaluate under default training settings. Testing the output will help inspect any mismatches or failures. Let's dive into that!
call → compile_kernel
callcompile_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 = r'''\n#include <torch/extension.h>\n#include <vector>\n\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be a CUDA tensor\")\n#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x \" must be contiguous\")\n#define CHECK_FLOAT(x) TORCH_CHECK(x.scalar_type() == at::kFloat, #x \" must be float32\")\n\nvoid eval_kernel_launch(const float* lin, const float* scale, const float* mean, const float* var,\n const float* gamma, const float* beta, float* out,\n long long total, int M, float eps, cudaStream_t stream);\nvoid train_stats_launch(const float* lin, const float* scale, const float* running_mean, const float* running_var,\n float* mean, float* invstd, int N, int M, float eps, float momentum, cudaStream_t stream);\nvoid train_norm_launch(const float* lin, const float* scale, const float* mean, const float* invstd,\n const float* gamma, const float* beta, float* out, long long total, int M, cudaStream_t stream);\n\ntorch::Tensor eval_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var,\n torch::Tensor gamma, torch::Tensor beta, double eps) {\n CHECK_CUDA(lin); CHECK_CUDA(scale); CHECK_CUDA(running_mean); CHECK_CUDA(running_var); CHECK_CUDA(gamma); CHECK_CUDA(beta);\n CHECK_CONTIGUOUS(lin); CHECK_CONTIGUOUS(scale); CHECK_CONTIGUOUS(running_mean); CHECK_CONTIGUOUS(running_var); CHECK_CONTIGUOUS(gamma); CHECK_CONTIGUOUS(beta);\n CHECK_FLOAT(lin); CHECK_FLOAT(scale); CHECK_FLOAT(running_mean); CHECK_FLOAT(running_var); CHECK_FLOAT(gamma); CHECK_FLOAT(beta);\n auto out = torch::empty_like(lin);\n int M = (int)lin.size(1);\n long long total = lin.numel();\n eval_kernel_launch(lin.data_ptr<float>(), scale.data_ptr<float>(), running_mean.data_ptr<float>(), running_var.data_ptr<float>(),\n gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>(), total, M, (float)eps, at::cuda::getCurrentCUDAStream());\n return out;\n}\n\ntorch::Tensor train_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var,\n torch::Tensor gamma, torch::Tensor beta, double eps, double momentum) {\n CHECK_CUDA(lin); CHECK_CUDA(scale); CHECK_CUDA(running_mean); CHECK_CUDA(running_var); CHECK_CUDA(gamma); CHECK_CUDA(beta);\n CHECK_CONTIGUOUS(lin); CHECK_CONTIGUOUS(scale); CHECK_CONTIGUOUS(running_mean); CHECK_CONTIGUOUS(running_var); CHECK_CONTIGUOUS(gamma); CHECK_CONTIGUOUS(beta);\n int N = (int)lin.size(0); int M = (int)lin.size(1);\n auto opts = lin.options();\n auto mean = torch::empty({M}, opts);\n auto invstd = torch::empty({M}, opts);\n auto out = torch::empty_like(lin);\n auto stream = at::cuda::getCurrentCUDAStream();\n train_stats_launch(lin.data_ptr<float>(), scale.data_ptr<float>(), running_mean.data_ptr<float>(), running_var.data_ptr<float>(),\n mean.data_ptr<float>(), invstd.data_ptr<float>(), N, M, (float)eps, (float)momentum, stream);\n train_norm_launch(lin.data_ptr<float>(), scale.data_ptr<float>(), mean.data_ptr<float>(), invstd.data_ptr<float>(),\n gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>(), lin.numel(), M, stream);\n return out;\n}\n'''\n\n_cuda = r'''\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\n__global__ void eval_kernel(const float* __restrict__ lin, const float* __restrict__ scale,\n const float* __restrict__ mean, const float* __restrict__ var,\n const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ out, long long n4, long long total, int M, float eps) {\n long long i4 = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n if (i4 < n4) {\n long long base = i4 * 4;\n int c = (int)(base % M);\n float4 v = reinterpret_cast<const float4*>(lin)[i4];\n float vals[4] = {v.x, v.y, v.z, v.w};\n float res[4];\n #pragma unroll\n for (int k=0;k<4;k++) {\n int j = c + k;\n float t = vals[k] * __ldg(scale + j);\n t = (t - __ldg(mean + j)) * rsqrtf(__ldg(var + j) + eps);\n t = t * __ldg(gamma + j) + __ldg(beta + j);\n res[k] = t;\n }\n reinterpret_cast<float4*>(out)[i4] = make_float4(res[0], res[1], res[2], res[3]);\n }\n long long idx = n4 * 4 + (long long)blockIdx.x * blockDim.x + threadIdx.x;\n if (idx < total) {\n int j = (int)(idx % M);\n float t = lin[idx] * __ldg(scale + j);\n t = (t - __ldg(mean + j)) * rsqrtf(__ldg(var + j) + eps);\n out[idx] = t * __ldg(gamma + j) + __ldg(beta + j);\n }\n}\n\n__global__ void train_stats_kernel(const float* __restrict__ lin, const float* __restrict__ scale,\n float* __restrict__ running_mean, float* __restrict__ running_var,\n float* __restrict__ mean, float* __restrict__ invstd,\n int N, int M, float eps, float momentum) {\n int j = blockIdx.x;\n float sum = 0.0f, sumsq = 0.0f;\n for (int r = threadIdx.x; r < N; r += blockDim.x) {\n float v = lin[(long long)r * M + j];\n sum += v;\n sumsq += v * v;\n }\n __shared__ float ssum[256];\n __shared__ float ssq[256];\n ssum[threadIdx.x] = sum; ssq[threadIdx.x] = sumsq;\n __syncthreads();\n for (int stride = blockDim.x/2; stride > 0; stride >>= 1) {\n if (threadIdx.x < stride) { ssum[threadIdx.x] += ssum[threadIdx.x+stride]; ssq[threadIdx.x] += ssq[threadIdx.x+stride]; }\n __syncthreads();\n }\n if (threadIdx.x == 0) {\n float sc = scale[j];\n float m = (ssum[0] / (float)N) * sc;\n float ex2 = (ssq[0] / (float)N) * sc * sc;\n float varb = fmaxf(ex2 - m*m, 0.0f);\n mean[j] = m;\n invstd[j] = rsqrtf(varb + eps);\n if (running_mean != nullptr) {\n running_mean[j] = running_mean[j] * (1.0f - momentum) + momentum * m;\n float unb = varb * ((float)N / (float)(N - 1));\n running_var[j] = running_var[j] * (1.0f - momentum) + momentum * unb;\n }\n }\n}\n\n__global__ void train_norm_kernel(const float* __restrict__ lin, const float* __restrict__ scale,\n const float* __restrict__ mean, const float* __restrict__ invstd,\n const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ out, long long n4, long long total, int M) {\n long long i4 = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n if (i4 < n4) {\n long long base = i4 * 4;\n int c = (int)(base % M);\n float4 v = reinterpret_cast<const float4*>(lin)[i4];\n float vals[4] = {v.x,v.y,v.z,v.w};\n float res[4];\n #pragma unroll\n for (int k=0;k<4;k++) {\n int j = c+k;\n float t = vals[k] * __ldg(scale+j);\n t = (t - __ldg(mean+j)) * __ldg(invstd+j);\n res[k] = t * __ldg(gamma+j) + __ldg(beta+j);\n }\n reinterpret_cast<float4*>(out)[i4] = make_float4(res[0],res[1],res[2],res[3]);\n }\n}\n\nvoid eval_kernel_launch(const float* lin, const float* scale, const float* mean, const float* var,\n const float* gamma, const float* beta, float* out,\n long long total, int M, float eps, cudaStream_t stream) {\n int threads = 256;\n long long n4 = total / 4;\n int blocks = (int)((n4 + threads - 1) / threads);\n eval_kernel<<<blocks, threads, 0, stream>>>(lin, scale, mean, var, gamma, beta, out, n4, total, M, eps);\n}\nvoid train_stats_launch(const float* lin, const float* scale, const float* running_mean, const float* running_var,\n float* mean, float* invstd, int N, int M, float eps, float momentum, cudaStream_t stream) {\n train_stats_kernel<<<M, 256, 0, stream>>>(lin, scale, const_cast<float*>(running_mean), const_cast<float*>(running_var), mean, invstd, N, M, eps, momentum);\n}\nvoid train_norm_launch(const float* lin, const float* scale, const float* mean, const float* invstd,\n const float* gamma, const float* beta, float* out, long long total, int M, cudaStream_t stream) {\n int threads = 256; long long n4 = total/4; int blocks = (int)((n4+threads-1)/threads);\n train_norm_kernel<<<blocks, threads, 0, stream>>>(lin, scale, mean, invstd, gamma, beta, out, n4, total, M);\n}\n'''\n\n_ext = load_inline(name='fused_linear_scale_bn_ext', cpp_sources=[_cpp], cuda_sources=[_cuda], functions=['eval_forward','train_forward'], extra_cuda_cflags=['-O3','--use_fast_math'], extra_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, scale_shape, eps=1e-5, momentum=0.1):\n super(ModelNew, self).__init__()\n self.gemm = nn.Linear(in_features, out_features)\n self.scale = nn.Parameter(torch.randn(scale_shape))\n self.bn = nn.BatchNorm1d(out_features, eps=eps, momentum=momentum)\n\n def forward(self, x):\n lin = F.linear(x, self.gemm.weight, self.gemm.bias)\n if self.bn.training:\n # match BatchNorm training path; increment counter like PyTorch does\n if self.bn.track_running_stats:\n self.bn.num_batches_tracked.add_(1)\n mom = self.bn.momentum if self.bn.momentum is not None else 0.1\n return _ext.train_forward(lin.contiguous(), self.scale.contiguous(), self.bn.running_mean.contiguous(), self.bn.running_var.contiguous(), self.bn.weight.contiguous(), self.bn.bias.contiguous(), float(self.bn.eps), float(mom))\n else:\n return _ext.eval_forward(lin.contiguous(), self.scale.contiguous(), self.bn.running_mean.contiguous(), self.bn.running_var.contiguous(), self.bn.weight.contiguous(), self.bn.bias.contiguous(), float(self.bn.eps))\n" }
result ← compile_kernel (fail)
failcompile_kernel compile_kernel FAILED: RuntimeError. RuntimeError: Error building extension 'fused_linear_scale_bn_ext': [1/3] /opt/conda/bin/x86_64-conda-linux-gnu-c++ -MMD -MF main.o.d -DTORCH_EXTENSION_NAME=fused_linear_scale_bn_ext -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /home/prabhune/.local/share/uv/python/cpython-3.10-linux-x86_64-gnu/include/python3.10 -fPIC -std=c++17 -O3 -c /scratch/tejas/PopcornBench/runs/l12_default/original/gpt-5.5-priority/level_2_problem_39_cache/k_e8d94cf49a4d/fused_linear_scale_bn_ext/main.cpp -o main.o FAILED: [code=1] main.o /opt/conda/bin/x86_64-conda-linux-gnu-c++ -MMD -MF main.o.d -DTORCH_EXTENSION_NAME=fused_linear_scale_bn_ext -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /home/prabhune/.local/share/uv/python/cpython-3.10-linux-x86_64-gnu/include/python3.10 -fPIC -std=c++17 -O3 -c /scratch/tejas/PopcornBench/runs/l12_default/original/gpt-5.5-priority/level_2_problem_39_cache/k_e8d94cf49a4d/fused_linear_scale_bn_ext/main.cpp -o main.o /scratch/tejas/PopcornBench/runs/l12_default/original/gpt-5.5-priority/level_2_problem_39_cache/k_e8d94cf49a4d/fused_linear_scale_bn_ext/main.cpp:12:60: error: 'cudaStream_t' has not been declared 12 | long long total, int M, float eps, cudaStream_t stream); | ^~~~~~~~~~~~ /scratch/tejas/PopcornBench/runs/l12_default/original/gpt-5.5-priority/level_2_problem_39_cache/k_e8d94cf49a4d/fused_linear_scale_bn_ext/main.cpp:14:94: error: 'cudaStream_t' has not been declared 14 | float* mean, float* invstd, int N, int M, float eps, float momentum, cudaStream_t stream); | ^~~~~~~~~~~~ /scratch/tejas/PopcornBench/runs/l12_default/original/gpt-5.5-priority/level_2_problem_39_cache/k_e8d94cf49a4d/fused_linear_scale_bn_ext/main.cpp:16:99: error: 'cudaStream_t' has not been declared 16 | const float* gamma, const float* beta, float* out, long long total, int M, cudaStream_t stream); | ^~~~~~~~~~~~ /scratch/tejas/PopcornBench/runs/l12_default/original/gpt-5.5-priority/level_2_problem_39_cache/k_e8d94cf49a4d/fused_linear_scale_bn_ext/main.cpp: In function 'at::Tensor eval_forward(at::Tensor, at::Tensor, at::Tensor, at::Tensor, at::Tensor, at::Tensor, double)': /scratch/tejas/PopcornBench/runs/l12_default/original/gpt-5.5-priority/level_2_problem_39_cache/k_e8d94cf49a4d/fused_linear_scale_bn_ext/main.cpp:27:128: error: 'getCurrentCUDAStream' is not a member of 'at::cuda' 27 | gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>(), total, M, (float)eps, at::cuda::getCurrentCUDAStream()); | ^~~~~~~~~~~~~~~~~~~~ /scratch/tejas/PopcornBench/runs/l12_default/original/gpt-5.5-priority/level_2_problem_39_cache/k_e8d94cf49a4d/fused_linear_scale_bn_ext/main.cpp: In function 'at::Tensor train_forward(at::Tensor, at::Tensor, at::Tensor, at::Tensor, at::Tensor, at::Tensor, double, double)': /scratch/tejas/PopcornBench/runs/l12_default/original/gpt-5.5-priority/level_2_problem_39_cache/k_e8d94cf49a4d/fused_linear_scale_bn_ext/main.cpp:40:29: error: 'getCurrentCUDAStream' is not a member of 'at::cuda' 40 | auto stream = at::cuda::getCurrentCUDAStream(); | ^~~~~~~~~~~~~~~~~~~~ [2/3] /usr/local/cuda/bin/nvcc -MD -MF cuda.cuda.o.d -ccbin /opt/conda/bin/x86_64-conda-linux-gnu-cc -DTORCH_EXTENSION_NAME=fused_linear_scale_bn_ext -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /home/prabhune/.local/share/uv/python/cpython-3.10-linux-x86_64-gnu/include/python3.10 -D__CUDA_NO_HALF_OPERATORS__ -D__CUDA_NO_HALF_CONVERSIONS__ -D__CUDA_NO_BFLOAT16_CONVERSIONS__ -D__CUDA_NO_HALF2_OPERATORS__ --expt-relaxed-constexpr -gencode=arch=compute_90,code=compute_90 -gencode=arch=compute_90,code=sm_90 --compiler-options '-fPIC' -O3 --use_fast_math -std=c++17 -c /scratch/tejas/PopcornBench/runs/l12_default/original/gpt-5.5-priority/level_2_problem_39_cache/k_e8d94cf49a4d/fused_linear_scale_bn_ext/cuda.cu -o cuda.cuda.o nvcc warning : incompatible redefinition for option 'compiler-bindir', the last value of this option was used ninja: build stopped: subcommand failed.
turn 2 · 1 tool call(s) · 16.6s turn · 16.6s LLM · 9,931 chars (click to expand)
turn 216.6s turn · 16.6s LLM · 0.0s tools
call → run_correctness
callrun_correctness { "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 = r'''\n#include <torch/extension.h>\n#include <c10/cuda/CUDAStream.h>\n#include <cuda_runtime_api.h>\n\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be a CUDA tensor\")\n#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x \" must be contiguous\")\n#define CHECK_FLOAT(x) TORCH_CHECK(x.scalar_type() == at::kFloat, #x \" must be float32\")\n\nvoid eval_kernel_launch(const float* lin, const float* scale, const float* mean, const float* var,\n const float* gamma, const float* beta, float* out,\n long long total, int M, float eps, cudaStream_t stream);\nvoid train_stats_launch(const float* lin, const float* scale, float* running_mean, float* running_var,\n float* mean, float* invstd, int N, int M, float eps, float momentum, cudaStream_t stream);\nvoid train_norm_launch(const float* lin, const float* scale, const float* mean, const float* invstd,\n const float* gamma, const float* beta, float* out, long long total, int M, cudaStream_t stream);\n\ntorch::Tensor eval_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var,\n torch::Tensor gamma, torch::Tensor beta, double eps) {\n CHECK_CUDA(lin); CHECK_CUDA(scale); CHECK_CUDA(running_mean); CHECK_CUDA(running_var); CHECK_CUDA(gamma); CHECK_CUDA(beta);\n auto out = torch::empty_like(lin);\n int M = (int)lin.size(1); long long total = lin.numel();\n eval_kernel_launch(lin.data_ptr<float>(), scale.data_ptr<float>(), running_mean.data_ptr<float>(), running_var.data_ptr<float>(),\n gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>(), total, M, (float)eps, c10::cuda::getCurrentCUDAStream());\n return out;\n}\n\ntorch::Tensor train_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var,\n torch::Tensor gamma, torch::Tensor beta, double eps, double momentum) {\n int N = (int)lin.size(0); int M = (int)lin.size(1);\n auto opts = lin.options(); auto mean = torch::empty({M}, opts); auto invstd = torch::empty({M}, opts); auto out = torch::empty_like(lin);\n auto stream = c10::cuda::getCurrentCUDAStream();\n train_stats_launch(lin.data_ptr<float>(), scale.data_ptr<float>(), running_mean.data_ptr<float>(), running_var.data_ptr<float>(),\n mean.data_ptr<float>(), invstd.data_ptr<float>(), N, M, (float)eps, (float)momentum, stream);\n train_norm_launch(lin.data_ptr<float>(), scale.data_ptr<float>(), mean.data_ptr<float>(), invstd.data_ptr<float>(),\n gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>(), lin.numel(), M, stream);\n return out;\n}\n'''\n\n_cuda = r'''\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\n__global__ void eval_kernel(const float* __restrict__ lin, const float* __restrict__ scale,\n const float* __restrict__ mean, const float* __restrict__ var,\n const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ out, long long n4, long long total, int M, float eps) {\n long long i4 = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n if (i4 < n4) {\n long long base = i4 * 4;\n int c = (int)(base % M);\n float4 v = reinterpret_cast<const float4*>(lin)[i4];\n float vals[4] = {v.x, v.y, v.z, v.w};\n float res[4];\n #pragma unroll\n for (int k=0;k<4;k++) {\n int j = c + k;\n float t = vals[k] * __ldg(scale + j);\n t = (t - __ldg(mean + j)) * rsqrtf(__ldg(var + j) + eps);\n t = t * __ldg(gamma + j) + __ldg(beta + j);\n res[k] = t;\n }\n reinterpret_cast<float4*>(out)[i4] = make_float4(res[0], res[1], res[2], res[3]);\n }\n}\n\n__global__ void train_stats_kernel(const float* __restrict__ lin, const float* __restrict__ scale,\n float* __restrict__ running_mean, float* __restrict__ running_var,\n float* __restrict__ mean, float* __restrict__ invstd,\n int N, int M, float eps, float momentum) {\n int j = blockIdx.x;\n float sum = 0.0f, sumsq = 0.0f;\n for (int r = threadIdx.x; r < N; r += blockDim.x) {\n float v = lin[(long long)r * M + j];\n sum += v; sumsq += v * v;\n }\n __shared__ float ssum[256], ssq[256];\n ssum[threadIdx.x] = sum; ssq[threadIdx.x] = sumsq; __syncthreads();\n for (int stride = 128; stride > 0; stride >>= 1) {\n if (threadIdx.x < stride) { ssum[threadIdx.x] += ssum[threadIdx.x+stride]; ssq[threadIdx.x] += ssq[threadIdx.x+stride]; }\n __syncthreads();\n }\n if (threadIdx.x == 0) {\n float sc = scale[j];\n float m = (ssum[0] / (float)N) * sc;\n float ex2 = (ssq[0] / (float)N) * sc * sc;\n float varb = fmaxf(ex2 - m*m, 0.0f);\n mean[j] = m; invstd[j] = rsqrtf(varb + eps);\n running_mean[j] = running_mean[j] * (1.0f - momentum) + momentum * m;\n running_var[j] = running_var[j] * (1.0f - momentum) + momentum * (varb * ((float)N / (float)(N - 1)));\n }\n}\n\n__global__ void train_norm_kernel(const float* __restrict__ lin, const float* __restrict__ scale,\n const float* __restrict__ mean, const float* __restrict__ invstd,\n const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ out, long long n4, long long total, int M) {\n long long i4 = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n if (i4 < n4) {\n long long base = i4 * 4; int c = (int)(base % M);\n float4 v = reinterpret_cast<const float4*>(lin)[i4];\n float vals[4] = {v.x,v.y,v.z,v.w}; float res[4];\n #pragma unroll\n for (int k=0;k<4;k++) { int j=c+k; float t=vals[k]*__ldg(scale+j); t=(t-__ldg(mean+j))*__ldg(invstd+j); res[k]=t*__ldg(gamma+j)+__ldg(beta+j); }\n reinterpret_cast<float4*>(out)[i4] = make_float4(res[0],res[1],res[2],res[3]);\n }\n}\n\nvoid eval_kernel_launch(const float* lin, const float* scale, const float* mean, const float* var,\n const float* gamma, const float* beta, float* out,\n long long total, int M, float eps, cudaStream_t stream) {\n int threads = 256; long long n4 = total / 4; int blocks = (int)((n4 + threads - 1) / threads);\n eval_kernel<<<blocks, threads, 0, stream>>>(lin, scale, mean, var, gamma, beta, out, n4, total, M, eps);\n}\nvoid train_stats_launch(const float* lin, const float* scale, float* running_mean, float* running_var,\n float* mean, float* invstd, int N, int M, float eps, float momentum, cudaStream_t stream) {\n train_stats_kernel<<<M, 256, 0, stream>>>(lin, scale, running_mean, running_var, mean, invstd, N, M, eps, momentum);\n}\nvoid train_norm_launch(const float* lin, const float* scale, const float* mean, const float* invstd,\n const float* gamma, const float* beta, float* out, long long total, int M, cudaStream_t stream) {\n int threads = 256; long long n4 = total/4; int blocks = (int)((n4+threads-1)/threads);\n train_norm_kernel<<<blocks, threads, 0, stream>>>(lin, scale, mean, invstd, gamma, beta, out, n4, total, M);\n}\n'''\n\n_ext = load_inline(name='fused_linear_scale_bn_ext2', cpp_sources=[_cpp], cuda_sources=[_cuda], functions=['eval_forward','train_forward'], extra_cuda_cflags=['-O3','--use_fast_math'], extra_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, scale_shape, eps=1e-5, momentum=0.1):\n super(ModelNew, self).__init__()\n self.gemm = nn.Linear(in_features, out_features)\n self.scale = nn.Parameter(torch.randn(scale_shape))\n self.bn = nn.BatchNorm1d(out_features, eps=eps, momentum=momentum)\n\n def forward(self, x):\n lin = F.linear(x, self.gemm.weight, self.gemm.bias)\n if self.bn.training:\n if self.bn.track_running_stats:\n self.bn.num_batches_tracked.add_(1)\n mom = self.bn.momentum if self.bn.momentum is not None else 0.1\n return _ext.train_forward(lin, self.scale, self.bn.running_mean, self.bn.running_var, self.bn.weight, self.bn.bias, float(self.bn.eps), float(mom))\n else:\n return _ext.eval_forward(lin, self.scale, self.bn.running_mean, self.bn.running_var, self.bn.weight, self.bn.bias, float(self.bn.eps))\n" }
result ← run_correctness (ok)
okrun_correctness run_correctness PASSED: (5 / 5) trials all matched the reference. Numerical precision: max_abs_err=2.38e-05 mean_abs_err=1.59e-07 max_rel_err=4.27e+05
turn 3 · 1 tool call(s) · 30.1s turn · 30.1s LLM · 9,711 chars (click to expand)
turn 330.1s turn · 30.1s LLM · 0.0s tools
reasoning
**Calculating and updating code** I'm looking to compute the sum across chunks and the sum of squares, which could improve the speed of the process. I think it’s time to update the code to reflect this change. There's also the consideration of evaluating whether anything has changed. I want to avoid unnecessary checks, but it's crucial to ensure that the code compiles correctly. Using a unique extension name might be a good approach too!
call → run_correctness
callrun_correctness { "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 = r'''\n#include <torch/extension.h>\n#include <c10/cuda/CUDAStream.h>\n#include <cuda_runtime_api.h>\n\nvoid eval_kernel_launch(const float*, const float*, const float*, const float*, const float*, const float*, float*, long long, int, float, cudaStream_t);\nvoid partial_stats_launch(const float*, float*, float*, int, int, int, cudaStream_t);\nvoid finalize_stats_launch(const float*, const float*, const float*, float*, float*, float*, float*, int, int, float, float, cudaStream_t);\nvoid train_norm_launch(const float*, const float*, const float*, const float*, const float*, const float*, float*, long long, int, cudaStream_t);\n\ntorch::Tensor eval_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var,\n torch::Tensor gamma, torch::Tensor beta, double eps) {\n auto out = torch::empty_like(lin);\n eval_kernel_launch(lin.data_ptr<float>(), scale.data_ptr<float>(), running_mean.data_ptr<float>(), running_var.data_ptr<float>(),\n gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>(), lin.numel(), (int)lin.size(1), (float)eps, c10::cuda::getCurrentCUDAStream());\n return out;\n}\n\ntorch::Tensor train_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var,\n torch::Tensor gamma, torch::Tensor beta, double eps, double momentum) {\n int N=(int)lin.size(0), M=(int)lin.size(1); const int ROWS=256; int chunks=(N+ROWS-1)/ROWS;\n auto opts=lin.options();\n auto ps=torch::empty({M, chunks}, opts); auto psq=torch::empty({M, chunks}, opts);\n auto mean=torch::empty({M}, opts); auto invstd=torch::empty({M}, opts); auto out=torch::empty_like(lin);\n auto stream=c10::cuda::getCurrentCUDAStream();\n partial_stats_launch(lin.data_ptr<float>(), ps.data_ptr<float>(), psq.data_ptr<float>(), N, M, chunks, stream);\n finalize_stats_launch(ps.data_ptr<float>(), psq.data_ptr<float>(), scale.data_ptr<float>(), running_mean.data_ptr<float>(), running_var.data_ptr<float>(), mean.data_ptr<float>(), invstd.data_ptr<float>(), N, M, (float)eps, (float)momentum, stream);\n train_norm_launch(lin.data_ptr<float>(), scale.data_ptr<float>(), mean.data_ptr<float>(), invstd.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>(), lin.numel(), M, stream);\n return out;\n}\n'''\n_cuda = r'''\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\n__global__ void eval_kernel(const float* __restrict__ lin,const float* __restrict__ scale,const float* __restrict__ mean,const float* __restrict__ var,const float* __restrict__ gamma,const float* __restrict__ beta,float* __restrict__ out,long long n4,int M,float eps){\n long long i4=(long long)blockIdx.x*blockDim.x+threadIdx.x; if(i4<n4){ long long base=i4*4; int c=(int)(base%M); float4 v=reinterpret_cast<const float4*>(lin)[i4]; float a[4]={v.x,v.y,v.z,v.w}; float r[4];\n#pragma unroll\n for(int k=0;k<4;k++){int j=c+k; float t=a[k]*__ldg(scale+j); t=(t-__ldg(mean+j))*rsqrtf(__ldg(var+j)+eps); r[k]=t*__ldg(gamma+j)+__ldg(beta+j);} reinterpret_cast<float4*>(out)[i4]=make_float4(r[0],r[1],r[2],r[3]); }}\n\n__global__ void partial_stats_kernel(const float* __restrict__ lin, float* __restrict__ ps, float* __restrict__ psq, int N, int M, int chunks){\n const int tx=threadIdx.x, ty=threadIdx.y; int j=blockIdx.x*32+tx; int row0=blockIdx.y*256; float sum=0.f, sumq=0.f;\n if(j<M){ int end=min(row0+256,N); for(int r=row0+ty; r<end; r+=8){ float v=lin[(long long)r*M+j]; sum+=v; sumq+=v*v; }}\n __shared__ float ss[8][32]; __shared__ float sq[8][32]; ss[ty][tx]=sum; sq[ty][tx]=sumq; __syncthreads();\n if(ty==0 && j<M){ float s=0.f, q=0.f; #pragma unroll for(int k=0;k<8;k++){s+=ss[k][tx]; q+=sq[k][tx];} ps[(long long)j*chunks+blockIdx.y]=s; psq[(long long)j*chunks+blockIdx.y]=q; }\n}\n\n__global__ void finalize_stats_kernel(const float* __restrict__ ps,const float* __restrict__ psq,const float* __restrict__ scale,float* __restrict__ running_mean,float* __restrict__ running_var,float* __restrict__ mean,float* __restrict__ invstd,int N,int M,int chunks,float eps,float momentum){\n int j=blockIdx.x; float s=0.f,q=0.f; for(int c=threadIdx.x;c<chunks;c+=blockDim.x){ s+=ps[(long long)j*chunks+c]; q+=psq[(long long)j*chunks+c]; }\n __shared__ float ss[128], sq[128]; ss[threadIdx.x]=s; sq[threadIdx.x]=q; __syncthreads(); for(int stride=64; stride>0; stride>>=1){ if(threadIdx.x<stride){ss[threadIdx.x]+=ss[threadIdx.x+stride]; sq[threadIdx.x]+=sq[threadIdx.x+stride];} __syncthreads(); }\n if(threadIdx.x==0){ float sc=scale[j]; float m=(ss[0]/(float)N)*sc; float ex2=(sq[0]/(float)N)*sc*sc; float varb=fmaxf(ex2-m*m,0.f); mean[j]=m; invstd[j]=rsqrtf(varb+eps); running_mean[j]=running_mean[j]*(1.f-momentum)+momentum*m; running_var[j]=running_var[j]*(1.f-momentum)+momentum*(varb*((float)N/(float)(N-1))); }}\n\n__global__ void train_norm_kernel(const float* __restrict__ lin,const float* __restrict__ scale,const float* __restrict__ mean,const float* __restrict__ invstd,const float* __restrict__ gamma,const float* __restrict__ beta,float* __restrict__ out,long long n4,int M){\n long long i4=(long long)blockIdx.x*blockDim.x+threadIdx.x; if(i4<n4){ long long base=i4*4; int c=(int)(base%M); float4 v=reinterpret_cast<const float4*>(lin)[i4]; float a[4]={v.x,v.y,v.z,v.w}; float r[4];\n#pragma unroll\n for(int k=0;k<4;k++){int j=c+k; float t=a[k]*__ldg(scale+j); t=(t-__ldg(mean+j))*__ldg(invstd+j); r[k]=t*__ldg(gamma+j)+__ldg(beta+j);} reinterpret_cast<float4*>(out)[i4]=make_float4(r[0],r[1],r[2],r[3]); }}\n\nvoid eval_kernel_launch(const float* lin,const float* scale,const float* mean,const float* var,const float* gamma,const float* beta,float* out,long long total,int M,float eps,cudaStream_t stream){int th=256; long long n4=total/4; int bl=(int)((n4+th-1)/th); eval_kernel<<<bl,th,0,stream>>>(lin,scale,mean,var,gamma,beta,out,n4,M,eps);} \nvoid partial_stats_launch(const float* lin,float* ps,float* psq,int N,int M,int chunks,cudaStream_t stream){dim3 block(32,8); dim3 grid((M+31)/32,chunks); partial_stats_kernel<<<grid,block,0,stream>>>(lin,ps,psq,N,M,chunks);} \nvoid finalize_stats_launch(const float* ps,const float* psq,const float* scale,float* running_mean,float* running_var,float* mean,float* invstd,int N,int M,float eps,float momentum,cudaStream_t stream){int chunks=(N+255)/256; finalize_stats_kernel<<<M,128,0,stream>>>(ps,psq,scale,running_mean,running_var,mean,invstd,N,M,chunks,eps,momentum);} \nvoid train_norm_launch(const float* lin,const float* scale,const float* mean,const float* invstd,const float* gamma,const float* beta,float* out,long long total,int M,cudaStream_t stream){int th=256; long long n4=total/4; int bl=(int)((n4+th-1)/th); train_norm_kernel<<<bl,th,0,stream>>>(lin,scale,mean,invstd,gamma,beta,out,n4,M);} \n'''\n_ext=load_inline(name='fused_linear_scale_bn_ext3',cpp_sources=[_cpp],cuda_sources=[_cuda],functions=['eval_forward','train_forward'],extra_cuda_cflags=['-O3','--use_fast_math'],extra_cflags=['-O3'],verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, scale_shape, eps=1e-5, momentum=0.1):\n super(ModelNew,self).__init__(); self.gemm=nn.Linear(in_features,out_features); self.scale=nn.Parameter(torch.randn(scale_shape)); self.bn=nn.BatchNorm1d(out_features,eps=eps,momentum=momentum)\n def forward(self,x):\n lin=F.linear(x,self.gemm.weight,self.gemm.bias)\n if self.bn.training:\n if self.bn.track_running_stats: self.bn.num_batches_tracked.add_(1)\n mom=self.bn.momentum if self.bn.momentum is not None else 0.1\n return _ext.train_forward(lin,self.scale,self.bn.running_mean,self.bn.running_var,self.bn.weight,self.bn.bias,float(self.bn.eps),float(mom))\n return _ext.eval_forward(lin,self.scale,self.bn.running_mean,self.bn.running_var,self.bn.weight,self.bn.bias,float(self.bn.eps))\n" }
result ← run_correctness (fail)
failrun_correctness run_correctness FAILED: persistent build/lock contention after retries. Please try a different kernel.
turn 4 · 1 tool call(s) · 15.4s turn · 15.4s LLM · 9,366 chars (click to expand)
turn 415.4s turn · 15.4s LLM · 0.0s tools
reasoning
**Troubleshooting compile issues** I think I might be facing a compile syntax issue here. It mentions lock contention, which could be due to a previous extension build. I wonder if trying a compile with a unique name would help. Oh, I remember we used #pragma unroll inside the same line after the # token and not at the line's start—could that be the error? Maybe I should correct the pragma lines and check if the extension build timed out. Time to call compile!
call → compile_kernel
callcompile_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 = r'''\n#include <torch/extension.h>\n#include <c10/cuda/CUDAStream.h>\n#include <cuda_runtime_api.h>\nvoid eval_kernel_launch(const float*, const float*, const float*, const float*, const float*, const float*, float*, long long, int, float, cudaStream_t);\nvoid partial_stats_launch(const float*, float*, float*, int, int, int, cudaStream_t);\nvoid finalize_stats_launch(const float*, const float*, const float*, float*, float*, float*, float*, int, int, float, float, cudaStream_t);\nvoid train_norm_launch(const float*, const float*, const float*, const float*, const float*, const float*, float*, long long, int, cudaStream_t);\ntorch::Tensor eval_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var, torch::Tensor gamma, torch::Tensor beta, double eps){auto out=torch::empty_like(lin); eval_kernel_launch(lin.data_ptr<float>(),scale.data_ptr<float>(),running_mean.data_ptr<float>(),running_var.data_ptr<float>(),gamma.data_ptr<float>(),beta.data_ptr<float>(),out.data_ptr<float>(),lin.numel(),(int)lin.size(1),(float)eps,c10::cuda::getCurrentCUDAStream()); return out;}\ntorch::Tensor train_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var, torch::Tensor gamma, torch::Tensor beta, double eps, double momentum){int N=(int)lin.size(0), M=(int)lin.size(1); const int ROWS=256; int chunks=(N+ROWS-1)/ROWS; auto opts=lin.options(); auto ps=torch::empty({M,chunks},opts); auto psq=torch::empty({M,chunks},opts); auto mean=torch::empty({M},opts); auto invstd=torch::empty({M},opts); auto out=torch::empty_like(lin); auto stream=c10::cuda::getCurrentCUDAStream(); partial_stats_launch(lin.data_ptr<float>(),ps.data_ptr<float>(),psq.data_ptr<float>(),N,M,chunks,stream); finalize_stats_launch(ps.data_ptr<float>(),psq.data_ptr<float>(),scale.data_ptr<float>(),running_mean.data_ptr<float>(),running_var.data_ptr<float>(),mean.data_ptr<float>(),invstd.data_ptr<float>(),N,M,(float)eps,(float)momentum,stream); train_norm_launch(lin.data_ptr<float>(),scale.data_ptr<float>(),mean.data_ptr<float>(),invstd.data_ptr<float>(),gamma.data_ptr<float>(),beta.data_ptr<float>(),out.data_ptr<float>(),lin.numel(),M,stream); return out;}\n'''\n_cuda = r'''\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n__global__ void eval_kernel(const float* __restrict__ lin,const float* __restrict__ scale,const float* __restrict__ mean,const float* __restrict__ var,const float* __restrict__ gamma,const float* __restrict__ beta,float* __restrict__ out,long long n4,int M,float eps){\n long long i4=(long long)blockIdx.x*blockDim.x+threadIdx.x; if(i4<n4){ long long base=i4*4; int c=(int)(base%M); float4 v=reinterpret_cast<const float4*>(lin)[i4]; float a[4]={v.x,v.y,v.z,v.w}; float r[4];\n#pragma unroll\n for(int k=0;k<4;k++){int j=c+k; float t=a[k]*__ldg(scale+j); t=(t-__ldg(mean+j))*rsqrtf(__ldg(var+j)+eps); r[k]=t*__ldg(gamma+j)+__ldg(beta+j);} reinterpret_cast<float4*>(out)[i4]=make_float4(r[0],r[1],r[2],r[3]); }}\n__global__ void partial_stats_kernel(const float* __restrict__ lin,float* __restrict__ ps,float* __restrict__ psq,int N,int M,int chunks){\n const int tx=threadIdx.x, ty=threadIdx.y; int j=blockIdx.x*32+tx; int row0=blockIdx.y*256; float sum=0.f,sumq=0.f; if(j<M){ int end=min(row0+256,N); for(int r=row0+ty;r<end;r+=8){ float v=lin[(long long)r*M+j]; sum+=v; sumq+=v*v; }} __shared__ float ss[8][32]; __shared__ float sq[8][32]; ss[ty][tx]=sum; sq[ty][tx]=sumq; __syncthreads(); if(ty==0&&j<M){ float s=0.f,q=0.f;\n#pragma unroll\n for(int k=0;k<8;k++){s+=ss[k][tx]; q+=sq[k][tx];} ps[(long long)j*chunks+blockIdx.y]=s; psq[(long long)j*chunks+blockIdx.y]=q; }}\n__global__ void finalize_stats_kernel(const float* __restrict__ ps,const float* __restrict__ psq,const float* __restrict__ scale,float* __restrict__ running_mean,float* __restrict__ running_var,float* __restrict__ mean,float* __restrict__ invstd,int N,int M,int chunks,float eps,float momentum){int j=blockIdx.x; float s=0.f,q=0.f; for(int c=threadIdx.x;c<chunks;c+=blockDim.x){s+=ps[(long long)j*chunks+c]; q+=psq[(long long)j*chunks+c];} __shared__ float ss[128]; __shared__ float sq[128]; ss[threadIdx.x]=s; sq[threadIdx.x]=q; __syncthreads(); for(int stride=64;stride>0;stride>>=1){if(threadIdx.x<stride){ss[threadIdx.x]+=ss[threadIdx.x+stride]; sq[threadIdx.x]+=sq[threadIdx.x+stride];} __syncthreads();} if(threadIdx.x==0){float sc=scale[j]; float m=(ss[0]/(float)N)*sc; float ex2=(sq[0]/(float)N)*sc*sc; float varb=fmaxf(ex2-m*m,0.f); mean[j]=m; invstd[j]=rsqrtf(varb+eps); running_mean[j]=running_mean[j]*(1.f-momentum)+momentum*m; running_var[j]=running_var[j]*(1.f-momentum)+momentum*(varb*((float)N/(float)(N-1)));}}\n__global__ void train_norm_kernel(const float* __restrict__ lin,const float* __restrict__ scale,const float* __restrict__ mean,const float* __restrict__ invstd,const float* __restrict__ gamma,const float* __restrict__ beta,float* __restrict__ out,long long n4,int M){long long i4=(long long)blockIdx.x*blockDim.x+threadIdx.x; if(i4<n4){long long base=i4*4; int c=(int)(base%M); float4 v=reinterpret_cast<const float4*>(lin)[i4]; float a[4]={v.x,v.y,v.z,v.w}; float r[4];\n#pragma unroll\n for(int k=0;k<4;k++){int j=c+k; float t=a[k]*__ldg(scale+j); t=(t-__ldg(mean+j))*__ldg(invstd+j); r[k]=t*__ldg(gamma+j)+__ldg(beta+j);} reinterpret_cast<float4*>(out)[i4]=make_float4(r[0],r[1],r[2],r[3]);}}\nvoid eval_kernel_launch(const float* lin,const float* scale,const float* mean,const float* var,const float* gamma,const float* beta,float* out,long long total,int M,float eps,cudaStream_t stream){int th=256; long long n4=total/4; int bl=(int)((n4+th-1)/th); eval_kernel<<<bl,th,0,stream>>>(lin,scale,mean,var,gamma,beta,out,n4,M,eps);} \nvoid partial_stats_launch(const float* lin,float* ps,float* psq,int N,int M,int chunks,cudaStream_t stream){dim3 block(32,8); dim3 grid((M+31)/32,chunks); partial_stats_kernel<<<grid,block,0,stream>>>(lin,ps,psq,N,M,chunks);} \nvoid finalize_stats_launch(const float* ps,const float* psq,const float* scale,float* running_mean,float* running_var,float* mean,float* invstd,int N,int M,float eps,float momentum,cudaStream_t stream){int chunks=(N+255)/256; finalize_stats_kernel<<<M,128,0,stream>>>(ps,psq,scale,running_mean,running_var,mean,invstd,N,M,chunks,eps,momentum);} \nvoid train_norm_launch(const float* lin,const float* scale,const float* mean,const float* invstd,const float* gamma,const float* beta,float* out,long long total,int M,cudaStream_t stream){int th=256; long long n4=total/4; int bl=(int)((n4+th-1)/th); train_norm_kernel<<<bl,th,0,stream>>>(lin,scale,mean,invstd,gamma,beta,out,n4,M);} \n'''\n_ext=load_inline(name='fused_linear_scale_bn_ext4',cpp_sources=[_cpp],cuda_sources=[_cuda],functions=['eval_forward','train_forward'],extra_cuda_cflags=['-O3','--use_fast_math'],extra_cflags=['-O3'],verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self,in_features,out_features,scale_shape,eps=1e-5,momentum=0.1):\n super(ModelNew,self).__init__(); self.gemm=nn.Linear(in_features,out_features); self.scale=nn.Parameter(torch.randn(scale_shape)); self.bn=nn.BatchNorm1d(out_features,eps=eps,momentum=momentum)\n def forward(self,x):\n lin=F.linear(x,self.gemm.weight,self.gemm.bias)\n if self.bn.training:\n if self.bn.track_running_stats: self.bn.num_batches_tracked.add_(1)\n mom=self.bn.momentum if self.bn.momentum is not None else 0.1\n return _ext.train_forward(lin,self.scale,self.bn.running_mean,self.bn.running_var,self.bn.weight,self.bn.bias,float(self.bn.eps),float(mom))\n return _ext.eval_forward(lin,self.scale,self.bn.running_mean,self.bn.running_var,self.bn.weight,self.bn.bias,float(self.bn.eps))\n" }
result ← compile_kernel (ok)
okcompile_kernel compile_kernel PASSED: kernel compiled without errors.
turn 5 · 1 tool call(s) · 16.2s turn · 16.2s LLM · 8,910 chars (click to expand)
turn 516.2s turn · 16.2s LLM · 0.0s tools
call → run_correctness
callrun_correctness { "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 = r'''\n#include <torch/extension.h>\n#include <c10/cuda/CUDAStream.h>\n#include <cuda_runtime_api.h>\nvoid eval_kernel_launch(const float*, const float*, const float*, const float*, const float*, const float*, float*, long long, int, float, cudaStream_t);\nvoid partial_stats_launch(const float*, float*, float*, int, int, int, cudaStream_t);\nvoid finalize_stats_launch(const float*, const float*, const float*, float*, float*, float*, float*, int, int, float, float, cudaStream_t);\nvoid train_norm_launch(const float*, const float*, const float*, const float*, const float*, const float*, float*, long long, int, cudaStream_t);\ntorch::Tensor eval_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var, torch::Tensor gamma, torch::Tensor beta, double eps){auto out=torch::empty_like(lin); eval_kernel_launch(lin.data_ptr<float>(),scale.data_ptr<float>(),running_mean.data_ptr<float>(),running_var.data_ptr<float>(),gamma.data_ptr<float>(),beta.data_ptr<float>(),out.data_ptr<float>(),lin.numel(),(int)lin.size(1),(float)eps,c10::cuda::getCurrentCUDAStream()); return out;}\ntorch::Tensor train_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var, torch::Tensor gamma, torch::Tensor beta, double eps, double momentum){int N=(int)lin.size(0), M=(int)lin.size(1); const int ROWS=256; int chunks=(N+ROWS-1)/ROWS; auto opts=lin.options(); auto ps=torch::empty({M,chunks},opts); auto psq=torch::empty({M,chunks},opts); auto mean=torch::empty({M},opts); auto invstd=torch::empty({M},opts); auto out=torch::empty_like(lin); auto stream=c10::cuda::getCurrentCUDAStream(); partial_stats_launch(lin.data_ptr<float>(),ps.data_ptr<float>(),psq.data_ptr<float>(),N,M,chunks,stream); finalize_stats_launch(ps.data_ptr<float>(),psq.data_ptr<float>(),scale.data_ptr<float>(),running_mean.data_ptr<float>(),running_var.data_ptr<float>(),mean.data_ptr<float>(),invstd.data_ptr<float>(),N,M,(float)eps,(float)momentum,stream); train_norm_launch(lin.data_ptr<float>(),scale.data_ptr<float>(),mean.data_ptr<float>(),invstd.data_ptr<float>(),gamma.data_ptr<float>(),beta.data_ptr<float>(),out.data_ptr<float>(),lin.numel(),M,stream); return out;}\n'''\n_cuda = r'''\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n__global__ void eval_kernel(const float* __restrict__ lin,const float* __restrict__ scale,const float* __restrict__ mean,const float* __restrict__ var,const float* __restrict__ gamma,const float* __restrict__ beta,float* __restrict__ out,long long n4,int M,float eps){\n long long i4=(long long)blockIdx.x*blockDim.x+threadIdx.x; if(i4<n4){ long long base=i4*4; int c=(int)(base%M); float4 v=reinterpret_cast<const float4*>(lin)[i4]; float a[4]={v.x,v.y,v.z,v.w}; float r[4];\n#pragma unroll\n for(int k=0;k<4;k++){int j=c+k; float t=a[k]*__ldg(scale+j); t=(t-__ldg(mean+j))*rsqrtf(__ldg(var+j)+eps); r[k]=t*__ldg(gamma+j)+__ldg(beta+j);} reinterpret_cast<float4*>(out)[i4]=make_float4(r[0],r[1],r[2],r[3]); }}\n__global__ void partial_stats_kernel(const float* __restrict__ lin,float* __restrict__ ps,float* __restrict__ psq,int N,int M,int chunks){\n const int tx=threadIdx.x, ty=threadIdx.y; int j=blockIdx.x*32+tx; int row0=blockIdx.y*256; float sum=0.f,sumq=0.f; if(j<M){ int end=min(row0+256,N); for(int r=row0+ty;r<end;r+=8){ float v=lin[(long long)r*M+j]; sum+=v; sumq+=v*v; }} __shared__ float ss[8][32]; __shared__ float sq[8][32]; ss[ty][tx]=sum; sq[ty][tx]=sumq; __syncthreads(); if(ty==0&&j<M){ float s=0.f,q=0.f;\n#pragma unroll\n for(int k=0;k<8;k++){s+=ss[k][tx]; q+=sq[k][tx];} ps[(long long)j*chunks+blockIdx.y]=s; psq[(long long)j*chunks+blockIdx.y]=q; }}\n__global__ void finalize_stats_kernel(const float* __restrict__ ps,const float* __restrict__ psq,const float* __restrict__ scale,float* __restrict__ running_mean,float* __restrict__ running_var,float* __restrict__ mean,float* __restrict__ invstd,int N,int M,int chunks,float eps,float momentum){int j=blockIdx.x; float s=0.f,q=0.f; for(int c=threadIdx.x;c<chunks;c+=blockDim.x){s+=ps[(long long)j*chunks+c]; q+=psq[(long long)j*chunks+c];} __shared__ float ss[128]; __shared__ float sq[128]; ss[threadIdx.x]=s; sq[threadIdx.x]=q; __syncthreads(); for(int stride=64;stride>0;stride>>=1){if(threadIdx.x<stride){ss[threadIdx.x]+=ss[threadIdx.x+stride]; sq[threadIdx.x]+=sq[threadIdx.x+stride];} __syncthreads();} if(threadIdx.x==0){float sc=scale[j]; float m=(ss[0]/(float)N)*sc; float ex2=(sq[0]/(float)N)*sc*sc; float varb=fmaxf(ex2-m*m,0.f); mean[j]=m; invstd[j]=rsqrtf(varb+eps); running_mean[j]=running_mean[j]*(1.f-momentum)+momentum*m; running_var[j]=running_var[j]*(1.f-momentum)+momentum*(varb*((float)N/(float)(N-1)));}}\n__global__ void train_norm_kernel(const float* __restrict__ lin,const float* __restrict__ scale,const float* __restrict__ mean,const float* __restrict__ invstd,const float* __restrict__ gamma,const float* __restrict__ beta,float* __restrict__ out,long long n4,int M){long long i4=(long long)blockIdx.x*blockDim.x+threadIdx.x; if(i4<n4){long long base=i4*4; int c=(int)(base%M); float4 v=reinterpret_cast<const float4*>(lin)[i4]; float a[4]={v.x,v.y,v.z,v.w}; float r[4];\n#pragma unroll\n for(int k=0;k<4;k++){int j=c+k; float t=a[k]*__ldg(scale+j); t=(t-__ldg(mean+j))*__ldg(invstd+j); r[k]=t*__ldg(gamma+j)+__ldg(beta+j);} reinterpret_cast<float4*>(out)[i4]=make_float4(r[0],r[1],r[2],r[3]);}}\nvoid eval_kernel_launch(const float* lin,const float* scale,const float* mean,const float* var,const float* gamma,const float* beta,float* out,long long total,int M,float eps,cudaStream_t stream){int th=256; long long n4=total/4; int bl=(int)((n4+th-1)/th); eval_kernel<<<bl,th,0,stream>>>(lin,scale,mean,var,gamma,beta,out,n4,M,eps);} \nvoid partial_stats_launch(const float* lin,float* ps,float* psq,int N,int M,int chunks,cudaStream_t stream){dim3 block(32,8); dim3 grid((M+31)/32,chunks); partial_stats_kernel<<<grid,block,0,stream>>>(lin,ps,psq,N,M,chunks);} \nvoid finalize_stats_launch(const float* ps,const float* psq,const float* scale,float* running_mean,float* running_var,float* mean,float* invstd,int N,int M,float eps,float momentum,cudaStream_t stream){int chunks=(N+255)/256; finalize_stats_kernel<<<M,128,0,stream>>>(ps,psq,scale,running_mean,running_var,mean,invstd,N,M,chunks,eps,momentum);} \nvoid train_norm_launch(const float* lin,const float* scale,const float* mean,const float* invstd,const float* gamma,const float* beta,float* out,long long total,int M,cudaStream_t stream){int th=256; long long n4=total/4; int bl=(int)((n4+th-1)/th); train_norm_kernel<<<bl,th,0,stream>>>(lin,scale,mean,invstd,gamma,beta,out,n4,M);} \n'''\n_ext=load_inline(name='fused_linear_scale_bn_ext4',cpp_sources=[_cpp],cuda_sources=[_cuda],functions=['eval_forward','train_forward'],extra_cuda_cflags=['-O3','--use_fast_math'],extra_cflags=['-O3'],verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self,in_features,out_features,scale_shape,eps=1e-5,momentum=0.1):\n super(ModelNew,self).__init__(); self.gemm=nn.Linear(in_features,out_features); self.scale=nn.Parameter(torch.randn(scale_shape)); self.bn=nn.BatchNorm1d(out_features,eps=eps,momentum=momentum)\n def forward(self,x):\n lin=F.linear(x,self.gemm.weight,self.gemm.bias)\n if self.bn.training:\n if self.bn.track_running_stats: self.bn.num_batches_tracked.add_(1)\n mom=self.bn.momentum if self.bn.momentum is not None else 0.1\n return _ext.train_forward(lin,self.scale,self.bn.running_mean,self.bn.running_var,self.bn.weight,self.bn.bias,float(self.bn.eps),float(mom))\n return _ext.eval_forward(lin,self.scale,self.bn.running_mean,self.bn.running_var,self.bn.weight,self.bn.bias,float(self.bn.eps))\n" }
result ← run_correctness (ok)
okrun_correctness run_correctness PASSED: (5 / 5) trials all matched the reference. Numerical precision: max_abs_err=1.96e-05 mean_abs_err=1.61e-07 max_rel_err=4.79e+05
turn 6 · 1 tool call(s) · 16.5s turn · 16.5s LLM · 9,429 chars (click to expand)
turn 616.5s turn · 16.5s LLM · 0.0s tools
reasoning
**Evaluating performance optimization** I need to assess performance before submitting the final version. However, there's a possibility I could optimize things further. I'm considering using `torch.addmm` instead of `F.linear` since it might offer benefits. But first, I need to perform a static check to ensure that everything is functioning as expected. It's essential to get this right before moving forward!
call → static_check
callstatic_check { "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 = r'''\n#include <torch/extension.h>\n#include <c10/cuda/CUDAStream.h>\n#include <cuda_runtime_api.h>\nvoid eval_kernel_launch(const float*, const float*, const float*, const float*, const float*, const float*, float*, long long, int, float, cudaStream_t);\nvoid partial_stats_launch(const float*, float*, float*, int, int, int, cudaStream_t);\nvoid finalize_stats_launch(const float*, const float*, const float*, float*, float*, float*, float*, int, int, float, float, cudaStream_t);\nvoid train_norm_launch(const float*, const float*, const float*, const float*, const float*, const float*, float*, long long, int, cudaStream_t);\ntorch::Tensor eval_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var, torch::Tensor gamma, torch::Tensor beta, double eps){auto out=torch::empty_like(lin); eval_kernel_launch(lin.data_ptr<float>(),scale.data_ptr<float>(),running_mean.data_ptr<float>(),running_var.data_ptr<float>(),gamma.data_ptr<float>(),beta.data_ptr<float>(),out.data_ptr<float>(),lin.numel(),(int)lin.size(1),(float)eps,c10::cuda::getCurrentCUDAStream()); return out;}\ntorch::Tensor train_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var, torch::Tensor gamma, torch::Tensor beta, double eps, double momentum){int N=(int)lin.size(0), M=(int)lin.size(1); const int ROWS=256; int chunks=(N+ROWS-1)/ROWS; auto opts=lin.options(); auto ps=torch::empty({M,chunks},opts); auto psq=torch::empty({M,chunks},opts); auto mean=torch::empty({M},opts); auto invstd=torch::empty({M},opts); auto out=torch::empty_like(lin); auto stream=c10::cuda::getCurrentCUDAStream(); partial_stats_launch(lin.data_ptr<float>(),ps.data_ptr<float>(),psq.data_ptr<float>(),N,M,chunks,stream); finalize_stats_launch(ps.data_ptr<float>(),psq.data_ptr<float>(),scale.data_ptr<float>(),running_mean.data_ptr<float>(),running_var.data_ptr<float>(),mean.data_ptr<float>(),invstd.data_ptr<float>(),N,M,(float)eps,(float)momentum,stream); train_norm_launch(lin.data_ptr<float>(),scale.data_ptr<float>(),mean.data_ptr<float>(),invstd.data_ptr<float>(),gamma.data_ptr<float>(),beta.data_ptr<float>(),out.data_ptr<float>(),lin.numel(),M,stream); return out;}\n'''\n_cuda = r'''\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n__global__ void eval_kernel(const float* __restrict__ lin,const float* __restrict__ scale,const float* __restrict__ mean,const float* __restrict__ var,const float* __restrict__ gamma,const float* __restrict__ beta,float* __restrict__ out,long long n4,int M,float eps){\n long long i4=(long long)blockIdx.x*blockDim.x+threadIdx.x; if(i4<n4){ long long base=i4*4; int c=(int)(base%M); float4 v=reinterpret_cast<const float4*>(lin)[i4]; float a[4]={v.x,v.y,v.z,v.w}; float r[4];\n#pragma unroll\n for(int k=0;k<4;k++){int j=c+k; float t=a[k]*__ldg(scale+j); t=(t-__ldg(mean+j))*rsqrtf(__ldg(var+j)+eps); r[k]=t*__ldg(gamma+j)+__ldg(beta+j);} reinterpret_cast<float4*>(out)[i4]=make_float4(r[0],r[1],r[2],r[3]); }}\n__global__ void partial_stats_kernel(const float* __restrict__ lin,float* __restrict__ ps,float* __restrict__ psq,int N,int M,int chunks){\n const int tx=threadIdx.x, ty=threadIdx.y; int j=blockIdx.x*32+tx; int row0=blockIdx.y*256; float sum=0.f,sumq=0.f; if(j<M){ int end=min(row0+256,N); for(int r=row0+ty;r<end;r+=8){ float v=lin[(long long)r*M+j]; sum+=v; sumq+=v*v; }} __shared__ float ss[8][32]; __shared__ float sq[8][32]; ss[ty][tx]=sum; sq[ty][tx]=sumq; __syncthreads(); if(ty==0&&j<M){ float s=0.f,q=0.f;\n#pragma unroll\n for(int k=0;k<8;k++){s+=ss[k][tx]; q+=sq[k][tx];} ps[(long long)j*chunks+blockIdx.y]=s; psq[(long long)j*chunks+blockIdx.y]=q; }}\n__global__ void finalize_stats_kernel(const float* __restrict__ ps,const float* __restrict__ psq,const float* __restrict__ scale,float* __restrict__ running_mean,float* __restrict__ running_var,float* __restrict__ mean,float* __restrict__ invstd,int N,int M,int chunks,float eps,float momentum){int j=blockIdx.x; float s=0.f,q=0.f; for(int c=threadIdx.x;c<chunks;c+=blockDim.x){s+=ps[(long long)j*chunks+c]; q+=psq[(long long)j*chunks+c];} __shared__ float ss[128]; __shared__ float sq[128]; ss[threadIdx.x]=s; sq[threadIdx.x]=q; __syncthreads(); for(int stride=64;stride>0;stride>>=1){if(threadIdx.x<stride){ss[threadIdx.x]+=ss[threadIdx.x+stride]; sq[threadIdx.x]+=sq[threadIdx.x+stride];} __syncthreads();} if(threadIdx.x==0){float sc=scale[j]; float m=(ss[0]/(float)N)*sc; float ex2=(sq[0]/(float)N)*sc*sc; float varb=fmaxf(ex2-m*m,0.f); mean[j]=m; invstd[j]=rsqrtf(varb+eps); running_mean[j]=running_mean[j]*(1.f-momentum)+momentum*m; running_var[j]=running_var[j]*(1.f-momentum)+momentum*(varb*((float)N/(float)(N-1)));}}\n__global__ void train_norm_kernel(const float* __restrict__ lin,const float* __restrict__ scale,const float* __restrict__ mean,const float* __restrict__ invstd,const float* __restrict__ gamma,const float* __restrict__ beta,float* __restrict__ out,long long n4,int M){long long i4=(long long)blockIdx.x*blockDim.x+threadIdx.x; if(i4<n4){long long base=i4*4; int c=(int)(base%M); float4 v=reinterpret_cast<const float4*>(lin)[i4]; float a[4]={v.x,v.y,v.z,v.w}; float r[4];\n#pragma unroll\n for(int k=0;k<4;k++){int j=c+k; float t=a[k]*__ldg(scale+j); t=(t-__ldg(mean+j))*__ldg(invstd+j); r[k]=t*__ldg(gamma+j)+__ldg(beta+j);} reinterpret_cast<float4*>(out)[i4]=make_float4(r[0],r[1],r[2],r[3]);}}\nvoid eval_kernel_launch(const float* lin,const float* scale,const float* mean,const float* var,const float* gamma,const float* beta,float* out,long long total,int M,float eps,cudaStream_t stream){int th=256; long long n4=total/4; int bl=(int)((n4+th-1)/th); eval_kernel<<<bl,th,0,stream>>>(lin,scale,mean,var,gamma,beta,out,n4,M,eps);} \nvoid partial_stats_launch(const float* lin,float* ps,float* psq,int N,int M,int chunks,cudaStream_t stream){dim3 block(32,8); dim3 grid((M+31)/32,chunks); partial_stats_kernel<<<grid,block,0,stream>>>(lin,ps,psq,N,M,chunks);} \nvoid finalize_stats_launch(const float* ps,const float* psq,const float* scale,float* running_mean,float* running_var,float* mean,float* invstd,int N,int M,float eps,float momentum,cudaStream_t stream){int chunks=(N+255)/256; finalize_stats_kernel<<<M,128,0,stream>>>(ps,psq,scale,running_mean,running_var,mean,invstd,N,M,chunks,eps,momentum);} \nvoid train_norm_launch(const float* lin,const float* scale,const float* mean,const float* invstd,const float* gamma,const float* beta,float* out,long long total,int M,cudaStream_t stream){int th=256; long long n4=total/4; int bl=(int)((n4+th-1)/th); train_norm_kernel<<<bl,th,0,stream>>>(lin,scale,mean,invstd,gamma,beta,out,n4,M);} \n'''\n_ext=load_inline(name='fused_linear_scale_bn_ext4',cpp_sources=[_cpp],cuda_sources=[_cuda],functions=['eval_forward','train_forward'],extra_cuda_cflags=['-O3','--use_fast_math'],extra_cflags=['-O3'],verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self,in_features,out_features,scale_shape,eps=1e-5,momentum=0.1):\n super(ModelNew,self).__init__(); self.gemm=nn.Linear(in_features,out_features); self.scale=nn.Parameter(torch.randn(scale_shape)); self.bn=nn.BatchNorm1d(out_features,eps=eps,momentum=momentum)\n def forward(self,x):\n lin=F.linear(x,self.gemm.weight,self.gemm.bias)\n if self.bn.training:\n if self.bn.track_running_stats: self.bn.num_batches_tracked.add_(1)\n mom=self.bn.momentum if self.bn.momentum is not None else 0.1\n return _ext.train_forward(lin,self.scale,self.bn.running_mean,self.bn.running_var,self.bn.weight,self.bn.bias,float(self.bn.eps),float(mom))\n return _ext.eval_forward(lin,self.scale,self.bn.running_mean,self.bn.running_var,self.bn.weight,self.bn.bias,float(self.bn.eps))\n" }
result ← static_check (ok)
okstatic_check static_check PASSED (with warnings): WARNING: Uses torch.nn.functional op: F.linear WARNING: Uses torch.nn compute layer (only containers, Parameter, init allowed)
turn 7 · FINAL · 1 tool call(s) · 20.7s turn · 20.7s LLM · 9,170 chars (click to expand)
turn 720.7s turn · 20.7s 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 = r'''\n#include <torch/extension.h>\n#include <c10/cuda/CUDAStream.h>\n#include <cuda_runtime_api.h>\nvoid eval_kernel_launch(const float*, const float*, const float*, const float*, const float*, const float*, float*, long long, int, float, cudaStream_t);\nvoid partial_stats_launch(const float*, float*, float*, int, int, int, cudaStream_t);\nvoid finalize_stats_launch(const float*, const float*, const float*, float*, float*, float*, float*, int, int, float, float, cudaStream_t);\nvoid train_norm_launch(const float*, const float*, const float*, const float*, const float*, const float*, float*, long long, int, cudaStream_t);\ntorch::Tensor eval_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var, torch::Tensor gamma, torch::Tensor beta, double eps){auto out=torch::empty_like(lin); eval_kernel_launch(lin.data_ptr<float>(),scale.data_ptr<float>(),running_mean.data_ptr<float>(),running_var.data_ptr<float>(),gamma.data_ptr<float>(),beta.data_ptr<float>(),out.data_ptr<float>(),lin.numel(),(int)lin.size(1),(float)eps,c10::cuda::getCurrentCUDAStream()); return out;}\ntorch::Tensor train_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var, torch::Tensor gamma, torch::Tensor beta, double eps, double momentum){int N=(int)lin.size(0), M=(int)lin.size(1); const int ROWS=256; int chunks=(N+ROWS-1)/ROWS; auto opts=lin.options(); auto ps=torch::empty({M,chunks},opts); auto psq=torch::empty({M,chunks},opts); auto mean=torch::empty({M},opts); auto invstd=torch::empty({M},opts); auto out=torch::empty_like(lin); auto stream=c10::cuda::getCurrentCUDAStream(); partial_stats_launch(lin.data_ptr<float>(),ps.data_ptr<float>(),psq.data_ptr<float>(),N,M,chunks,stream); finalize_stats_launch(ps.data_ptr<float>(),psq.data_ptr<float>(),scale.data_ptr<float>(),running_mean.data_ptr<float>(),running_var.data_ptr<float>(),mean.data_ptr<float>(),invstd.data_ptr<float>(),N,M,(float)eps,(float)momentum,stream); train_norm_launch(lin.data_ptr<float>(),scale.data_ptr<float>(),mean.data_ptr<float>(),invstd.data_ptr<float>(),gamma.data_ptr<float>(),beta.data_ptr<float>(),out.data_ptr<float>(),lin.numel(),M,stream); return out;}\n'''\n_cuda = r'''\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n__global__ void eval_kernel(const float* __restrict__ lin,const float* __restrict__ scale,const float* __restrict__ mean,const float* __restrict__ var,const float* __restrict__ gamma,const float* __restrict__ beta,float* __restrict__ out,long long n4,int M,float eps){\n long long i4=(long long)blockIdx.x*blockDim.x+threadIdx.x; if(i4<n4){ long long base=i4*4; int c=(int)(base%M); float4 v=reinterpret_cast<const float4*>(lin)[i4]; float a[4]={v.x,v.y,v.z,v.w}; float r[4];\n#pragma unroll\n for(int k=0;k<4;k++){int j=c+k; float t=a[k]*__ldg(scale+j); t=(t-__ldg(mean+j))*rsqrtf(__ldg(var+j)+eps); r[k]=t*__ldg(gamma+j)+__ldg(beta+j);} reinterpret_cast<float4*>(out)[i4]=make_float4(r[0],r[1],r[2],r[3]); }}\n__global__ void partial_stats_kernel(const float* __restrict__ lin,float* __restrict__ ps,float* __restrict__ psq,int N,int M,int chunks){\n const int tx=threadIdx.x, ty=threadIdx.y; int j=blockIdx.x*32+tx; int row0=blockIdx.y*256; float sum=0.f,sumq=0.f; if(j<M){ int end=min(row0+256,N); for(int r=row0+ty;r<end;r+=8){ float v=lin[(long long)r*M+j]; sum+=v; sumq+=v*v; }} __shared__ float ss[8][32]; __shared__ float sq[8][32]; ss[ty][tx]=sum; sq[ty][tx]=sumq; __syncthreads(); if(ty==0&&j<M){ float s=0.f,q=0.f;\n#pragma unroll\n for(int k=0;k<8;k++){s+=ss[k][tx]; q+=sq[k][tx];} ps[(long long)j*chunks+blockIdx.y]=s; psq[(long long)j*chunks+blockIdx.y]=q; }}\n__global__ void finalize_stats_kernel(const float* __restrict__ ps,const float* __restrict__ psq,const float* __restrict__ scale,float* __restrict__ running_mean,float* __restrict__ running_var,float* __restrict__ mean,float* __restrict__ invstd,int N,int M,int chunks,float eps,float momentum){int j=blockIdx.x; float s=0.f,q=0.f; for(int c=threadIdx.x;c<chunks;c+=blockDim.x){s+=ps[(long long)j*chunks+c]; q+=psq[(long long)j*chunks+c];} __shared__ float ss[128]; __shared__ float sq[128]; ss[threadIdx.x]=s; sq[threadIdx.x]=q; __syncthreads(); for(int stride=64;stride>0;stride>>=1){if(threadIdx.x<stride){ss[threadIdx.x]+=ss[threadIdx.x+stride]; sq[threadIdx.x]+=sq[threadIdx.x+stride];} __syncthreads();} if(threadIdx.x==0){float sc=scale[j]; float m=(ss[0]/(float)N)*sc; float ex2=(sq[0]/(float)N)*sc*sc; float varb=fmaxf(ex2-m*m,0.f); mean[j]=m; invstd[j]=rsqrtf(varb+eps); running_mean[j]=running_mean[j]*(1.f-momentum)+momentum*m; running_var[j]=running_var[j]*(1.f-momentum)+momentum*(varb*((float)N/(float)(N-1)));}}\n__global__ void train_norm_kernel(const float* __restrict__ lin,const float* __restrict__ scale,const float* __restrict__ mean,const float* __restrict__ invstd,const float* __restrict__ gamma,const float* __restrict__ beta,float* __restrict__ out,long long n4,int M){long long i4=(long long)blockIdx.x*blockDim.x+threadIdx.x; if(i4<n4){long long base=i4*4; int c=(int)(base%M); float4 v=reinterpret_cast<const float4*>(lin)[i4]; float a[4]={v.x,v.y,v.z,v.w}; float r[4];\n#pragma unroll\n for(int k=0;k<4;k++){int j=c+k; float t=a[k]*__ldg(scale+j); t=(t-__ldg(mean+j))*__ldg(invstd+j); r[k]=t*__ldg(gamma+j)+__ldg(beta+j);} reinterpret_cast<float4*>(out)[i4]=make_float4(r[0],r[1],r[2],r[3]);}}\nvoid eval_kernel_launch(const float* lin,const float* scale,const float* mean,const float* var,const float* gamma,const float* beta,float* out,long long total,int M,float eps,cudaStream_t stream){int th=256; long long n4=total/4; int bl=(int)((n4+th-1)/th); eval_kernel<<<bl,th,0,stream>>>(lin,scale,mean,var,gamma,beta,out,n4,M,eps);} \nvoid partial_stats_launch(const float* lin,float* ps,float* psq,int N,int M,int chunks,cudaStream_t stream){dim3 block(32,8); dim3 grid((M+31)/32,chunks); partial_stats_kernel<<<grid,block,0,stream>>>(lin,ps,psq,N,M,chunks);} \nvoid finalize_stats_launch(const float* ps,const float* psq,const float* scale,float* running_mean,float* running_var,float* mean,float* invstd,int N,int M,float eps,float momentum,cudaStream_t stream){int chunks=(N+255)/256; finalize_stats_kernel<<<M,128,0,stream>>>(ps,psq,scale,running_mean,running_var,mean,invstd,N,M,chunks,eps,momentum);} \nvoid train_norm_launch(const float* lin,const float* scale,const float* mean,const float* invstd,const float* gamma,const float* beta,float* out,long long total,int M,cudaStream_t stream){int th=256; long long n4=total/4; int bl=(int)((n4+th-1)/th); train_norm_kernel<<<bl,th,0,stream>>>(lin,scale,mean,invstd,gamma,beta,out,n4,M);} \n'''\n_ext=load_inline(name='fused_linear_scale_bn_final',cpp_sources=[_cpp],cuda_sources=[_cuda],functions=['eval_forward','train_forward'],extra_cuda_cflags=['-O3','--use_fast_math'],extra_cflags=['-O3'],verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self,in_features,out_features,scale_shape,eps=1e-5,momentum=0.1):\n super(ModelNew,self).__init__(); self.gemm=nn.Linear(in_features,out_features); self.scale=nn.Parameter(torch.randn(scale_shape)); self.bn=nn.BatchNorm1d(out_features,eps=eps,momentum=momentum)\n def forward(self,x):\n lin=F.linear(x,self.gemm.weight,self.gemm.bias)\n if self.bn.training:\n if self.bn.track_running_stats: self.bn.num_batches_tracked.add_(1)\n mom=self.bn.momentum if self.bn.momentum is not None else 0.1\n return _ext.train_forward(lin,self.scale,self.bn.running_mean,self.bn.running_var,self.bn.weight,self.bn.bias,float(self.bn.eps),float(mom))\n return _ext.eval_forward(lin,self.scale,self.bn.running_mean,self.bn.running_var,self.bn.weight,self.bn.bias,float(self.bn.eps))\n" }
result ← submit_kernel (ok)
oksubmit_kernel submit_kernel PASSED: (5 / 5) correctness trials all passed. Kernel runtime: 11.20 μs Runtime stats: mean=11.20μs median=?μs std=0.34μs Numerical precision: max_abs_err=1.96e-05 mean_abs_err=1.61e-07 max_rel_err=4.79e+05 Memory: 931.22 MB peak (ref: 933.22 MB, ratio: 0.9979x) Kernel launches: 12 (ref: 20, fusion ratio: 1.6667) Energy: 1447.74 mJ/run (ref: 1447.92 mJ, ratio: 1.0001x) SOL score: 1.0
final submitted kernel (49 lines, 7,781 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 = r'''
#include <torch/extension.h>
#include <c10/cuda/CUDAStream.h>
#include <cuda_runtime_api.h>
void eval_kernel_launch(const float*, const float*, const float*, const float*, const float*, const float*, float*, long long, int, float, cudaStream_t);
void partial_stats_launch(const float*, float*, float*, int, int, int, cudaStream_t);
void finalize_stats_launch(const float*, const float*, const float*, float*, float*, float*, float*, int, int, float, float, cudaStream_t);
void train_norm_launch(const float*, const float*, const float*, const float*, const float*, const float*, float*, long long, int, cudaStream_t);
torch::Tensor eval_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var, torch::Tensor gamma, torch::Tensor beta, double eps){auto out=torch::empty_like(lin); eval_kernel_launch(lin.data_ptr<float>(),scale.data_ptr<float>(),running_mean.data_ptr<float>(),running_var.data_ptr<float>(),gamma.data_ptr<float>(),beta.data_ptr<float>(),out.data_ptr<float>(),lin.numel(),(int)lin.size(1),(float)eps,c10::cuda::getCurrentCUDAStream()); return out;}
torch::Tensor train_forward(torch::Tensor lin, torch::Tensor scale, torch::Tensor running_mean, torch::Tensor running_var, torch::Tensor gamma, torch::Tensor beta, double eps, double momentum){int N=(int)lin.size(0), M=(int)lin.size(1); const int ROWS=256; int chunks=(N+ROWS-1)/ROWS; auto opts=lin.options(); auto ps=torch::empty({M,chunks},opts); auto psq=torch::empty({M,chunks},opts); auto mean=torch::empty({M},opts); auto invstd=torch::empty({M},opts); auto out=torch::empty_like(lin); auto stream=c10::cuda::getCurrentCUDAStream(); partial_stats_launch(lin.data_ptr<float>(),ps.data_ptr<float>(),psq.data_ptr<float>(),N,M,chunks,stream); finalize_stats_launch(ps.data_ptr<float>(),psq.data_ptr<float>(),scale.data_ptr<float>(),running_mean.data_ptr<float>(),running_var.data_ptr<float>(),mean.data_ptr<float>(),invstd.data_ptr<float>(),N,M,(float)eps,(float)momentum,stream); train_norm_launch(lin.data_ptr<float>(),scale.data_ptr<float>(),mean.data_ptr<float>(),invstd.data_ptr<float>(),gamma.data_ptr<float>(),beta.data_ptr<float>(),out.data_ptr<float>(),lin.numel(),M,stream); return out;}
'''
_cuda = r'''
#include <cuda.h>
#include <cuda_runtime.h>
#include <math.h>
__global__ void eval_kernel(const float* __restrict__ lin,const float* __restrict__ scale,const float* __restrict__ mean,const float* __restrict__ var,const float* __restrict__ gamma,const float* __restrict__ beta,float* __restrict__ out,long long n4,int M,float eps){
 long long i4=(long long)blockIdx.x*blockDim.x+threadIdx.x; if(i4<n4){ long long base=i4*4; int c=(int)(base%M); float4 v=reinterpret_cast<const float4*>(lin)[i4]; float a[4]={v.x,v.y,v.z,v.w}; float r[4];
#pragma unroll
 for(int k=0;k<4;k++){int j=c+k; float t=a[k]*__ldg(scale+j); t=(t-__ldg(mean+j))*rsqrtf(__ldg(var+j)+eps); r[k]=t*__ldg(gamma+j)+__ldg(beta+j);} reinterpret_cast<float4*>(out)[i4]=make_float4(r[0],r[1],r[2],r[3]); }}
__global__ void partial_stats_kernel(const float* __restrict__ lin,float* __restrict__ ps,float* __restrict__ psq,int N,int M,int chunks){
 const int tx=threadIdx.x, ty=threadIdx.y; int j=blockIdx.x*32+tx; int row0=blockIdx.y*256; float sum=0.f,sumq=0.f; if(j<M){ int end=min(row0+256,N); for(int r=row0+ty;r<end;r+=8){ float v=lin[(long long)r*M+j]; sum+=v; sumq+=v*v; }} __shared__ float ss[8][32]; __shared__ float sq[8][32]; ss[ty][tx]=sum; sq[ty][tx]=sumq; __syncthreads(); if(ty==0&&j<M){ float s=0.f,q=0.f;
#pragma unroll
 for(int k=0;k<8;k++){s+=ss[k][tx]; q+=sq[k][tx];} ps[(long long)j*chunks+blockIdx.y]=s; psq[(long long)j*chunks+blockIdx.y]=q; }}
__global__ void finalize_stats_kernel(const float* __restrict__ ps,const float* __restrict__ psq,const float* __restrict__ scale,float* __restrict__ running_mean,float* __restrict__ running_var,float* __restrict__ mean,float* __restrict__ invstd,int N,int M,int chunks,float eps,float momentum){int j=blockIdx.x; float s=0.f,q=0.f; for(int c=threadIdx.x;c<chunks;c+=blockDim.x){s+=ps[(long long)j*chunks+c]; q+=psq[(long long)j*chunks+c];} __shared__ float ss[128]; __shared__ float sq[128]; ss[threadIdx.x]=s; sq[threadIdx.x]=q; __syncthreads(); for(int stride=64;stride>0;stride>>=1){if(threadIdx.x<stride){ss[threadIdx.x]+=ss[threadIdx.x+stride]; sq[threadIdx.x]+=sq[threadIdx.x+stride];} __syncthreads();} if(threadIdx.x==0){float sc=scale[j]; float m=(ss[0]/(float)N)*sc; float ex2=(sq[0]/(float)N)*sc*sc; float varb=fmaxf(ex2-m*m,0.f); mean[j]=m; invstd[j]=rsqrtf(varb+eps); running_mean[j]=running_mean[j]*(1.f-momentum)+momentum*m; running_var[j]=running_var[j]*(1.f-momentum)+momentum*(varb*((float)N/(float)(N-1)));}}
__global__ void train_norm_kernel(const float* __restrict__ lin,const float* __restrict__ scale,const float* __restrict__ mean,const float* __restrict__ invstd,const float* __restrict__ gamma,const float* __restrict__ beta,float* __restrict__ out,long long n4,int M){long long i4=(long long)blockIdx.x*blockDim.x+threadIdx.x; if(i4<n4){long long base=i4*4; int c=(int)(base%M); float4 v=reinterpret_cast<const float4*>(lin)[i4]; float a[4]={v.x,v.y,v.z,v.w}; float r[4];
#pragma unroll
 for(int k=0;k<4;k++){int j=c+k; float t=a[k]*__ldg(scale+j); t=(t-__ldg(mean+j))*__ldg(invstd+j); r[k]=t*__ldg(gamma+j)+__ldg(beta+j);} reinterpret_cast<float4*>(out)[i4]=make_float4(r[0],r[1],r[2],r[3]);}}
void eval_kernel_launch(const float* lin,const float* scale,const float* mean,const float* var,const float* gamma,const float* beta,float* out,long long total,int M,float eps,cudaStream_t stream){int th=256; long long n4=total/4; int bl=(int)((n4+th-1)/th); eval_kernel<<<bl,th,0,stream>>>(lin,scale,mean,var,gamma,beta,out,n4,M,eps);} 
void partial_stats_launch(const float* lin,float* ps,float* psq,int N,int M,int chunks,cudaStream_t stream){dim3 block(32,8); dim3 grid((M+31)/32,chunks); partial_stats_kernel<<<grid,block,0,stream>>>(lin,ps,psq,N,M,chunks);} 
void finalize_stats_launch(const float* ps,const float* psq,const float* scale,float* running_mean,float* running_var,float* mean,float* invstd,int N,int M,float eps,float momentum,cudaStream_t stream){int chunks=(N+255)/256; finalize_stats_kernel<<<M,128,0,stream>>>(ps,psq,scale,running_mean,running_var,mean,invstd,N,M,chunks,eps,momentum);} 
void train_norm_launch(const float* lin,const float* scale,const float* mean,const float* invstd,const float* gamma,const float* beta,float* out,long long total,int M,cudaStream_t stream){int th=256; long long n4=total/4; int bl=(int)((n4+th-1)/th); train_norm_kernel<<<bl,th,0,stream>>>(lin,scale,mean,invstd,gamma,beta,out,n4,M);} 
'''
_ext=load_inline(name='fused_linear_scale_bn_final',cpp_sources=[_cpp],cuda_sources=[_cuda],functions=['eval_forward','train_forward'],extra_cuda_cflags=['-O3','--use_fast_math'],extra_cflags=['-O3'],verbose=False)
class ModelNew(nn.Module):
 def __init__(self,in_features,out_features,scale_shape,eps=1e-5,momentum=0.1):
  super(ModelNew,self).__init__(); self.gemm=nn.Linear(in_features,out_features); self.scale=nn.Parameter(torch.randn(scale_shape)); self.bn=nn.BatchNorm1d(out_features,eps=eps,momentum=momentum)
 def forward(self,x):
  lin=F.linear(x,self.gemm.weight,self.gemm.bias)
  if self.bn.training:
   if self.bn.track_running_stats: self.bn.num_batches_tracked.add_(1)
   mom=self.bn.momentum if self.bn.momentum is not None else 0.1
   return _ext.train_forward(lin,self.scale,self.bn.running_mean,self.bn.running_var,self.bn.weight,self.bn.bias,float(self.bn.eps),float(mom))
  return _ext.eval_forward(lin,self.scale,self.bn.running_mean,self.bn.running_var,self.bn.weight,self.bn.bias,float(self.bn.eps))