incorrect
38_L1Norm_.py
started
2026-05-05T00:29:34Z
correctness issue:
timingkernelbench.timing
kernel mean / median / std
—
ref mean / median / std
15.90 / — / 0.25 μs
SOL (speed-of-light)nsight_hardware_counters
roofline / occupancynsight_hardware_counters
dram bandwidth
2081.72 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):
"""
Simple model that performs L1 normalization.
"""
def __init__(self):
"""
Initializes the L1 normalization layer.
"""
super(Model, self).__init__()
def forward(self, x: torch.Tensor) -> torch.Tensor:
"""
Applies L1 normalization to the input tensor.
Args:
x (torch.Tensor): Input tensor of shape (..., dim, ...).
Returns:
torch.Tensor: Output tensor with L1 normalization applied, same shape as input.
"""
return x / torch.mean(torch.abs(x), dim=1, keepdim=True)
batch_size = 32768
# choose dim so total <2^31
dim = 65535
def get_inputs():
x = torch.rand(batch_size, dim)
return [x]
def get_init_inputs():
return []turn 018.2s turn · 18.2s 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\nvoid l1_norm_cuda(torch::Tensor x, torch::Tensor out);\n\ntorch::Tensor l1_norm(torch::Tensor x) {\n auto out = torch::empty_like(x);\n l1_norm_cuda(x, out);\n return out;\n}\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 <stdint.h>\n\n#ifndef __CUDA_ARCH__\n#define __CUDA_ARCH__ 0\n#endif\n\n__global__ __launch_bounds__(256, 2)\nvoid l1_norm_kernel_f32(const float* __restrict__ x, float* __restrict__ out, int rows, int cols) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n const float* __restrict__ xr = x + (int64_t)row * cols;\n float* __restrict__ yr = out + (int64_t)row * cols;\n\n float sum = 0.0f;\n // Unroll the strided load loop to reduce loop overhead. For the benchmark\n // cols=65535 and blockDim=256, so each thread handles about 256 elements.\n int i = tid;\n int stride = blockDim.x;\n for (; i + 3 * stride < cols; i += 4 * stride) {\n float v0 = xr[i];\n float v1 = xr[i + stride];\n float v2 = xr[i + 2 * stride];\n float v3 = xr[i + 3 * stride];\n sum += fabsf(v0) + fabsf(v1) + fabsf(v2) + fabsf(v3);\n }\n for (; i < cols; i += stride) {\n sum += fabsf(xr[i]);\n }\n\n // Warp reductions, then one warp reduces the warp sums.\n sum += __shfl_down_sync(0xffffffff, sum, 16);\n sum += __shfl_down_sync(0xffffffff, sum, 8);\n sum += __shfl_down_sync(0xffffffff, sum, 4);\n sum += __shfl_down_sync(0xffffffff, sum, 2);\n sum += __shfl_down_sync(0xffffffff, sum, 1);\n\n __shared__ float warp_sums[8];\n int lane = tid & 31;\n int warp = tid >> 5;\n if (lane == 0) warp_sums[warp] = sum;\n __syncthreads();\n\n float total = 0.0f;\n if (tid < 8) total = warp_sums[tid];\n if (warp == 0) {\n total += __shfl_down_sync(0xffffffff, total, 4);\n total += __shfl_down_sync(0xffffffff, total, 2);\n total += __shfl_down_sync(0xffffffff, total, 1);\n }\n __shared__ float scale_s;\n if (tid == 0) {\n // x / mean(abs(x)) == x * cols / sum(abs(x)). PyTorch will produce\n // inf/nan in the zero-sum case; division here mirrors that behavior.\n scale_s = ((float)cols) / total;\n }\n __syncthreads();\n float scale = scale_s;\n\n i = tid;\n for (; i + 3 * stride < cols; i += 4 * stride) {\n float v0 = xr[i];\n float v1 = xr[i + stride];\n float v2 = xr[i + 2 * stride];\n float v3 = xr[i + 3 * stride];\n yr[i] = v0 * scale;\n yr[i + stride] = v1 * scale;\n yr[i + 2 * stride] = v2 * scale;\n yr[i + 3 * stride] = v3 * scale;\n }\n for (; i < cols; i += stride) {\n yr[i] = xr[i] * scale;\n }\n}\n\nvoid l1_norm_cuda(torch::Tensor x, torch::Tensor out) {\n const int64_t rows64 = x.size(0);\n const int64_t cols64 = x.size(1);\n const int rows = (int)rows64;\n const int cols = (int)cols64;\n const dim3 grid(rows);\n const dim3 block(256);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n l1_norm_kernel_f32<<<grid, block, 0, stream>>>(x.data_ptr<float>(), out.data_ptr<float>(), rows, cols);\n}\n'''\n\n_ext = load_inline(\n name='l1_norm_ext_fast',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['l1_norm'],\n extra_cflags=['-O3'],\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super(ModelNew, self).__init__()\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.l1_norm(x)\n"
}
result ← submit_kernel (fail)
failsubmit_kernel
submit_kernel FAILED: correctness check did not pass (? trials).
runtime_error: CUDA out of memory. Tried to allocate 2.00 GiB. GPU 0 has a total capacity of 79.10 GiB of which 4.06 MiB is free. Process 1468150 has 726.00 MiB memory in use. Process 1054625 has 516.00 MiB memor...
final submitted kernel (124 lines, 3,673 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>
void l1_norm_cuda(torch::Tensor x, torch::Tensor out);
torch::Tensor l1_norm(torch::Tensor x) {
auto out = torch::empty_like(x);
l1_norm_cuda(x, out);
return out;
}
'''
_cuda_src = r'''
#include <torch/extension.h>
#include <ATen/cuda/CUDAContext.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <stdint.h>
#ifndef __CUDA_ARCH__
#define __CUDA_ARCH__ 0
#endif
__global__ __launch_bounds__(256, 2)
void l1_norm_kernel_f32(const float* __restrict__ x, float* __restrict__ out, int rows, int cols) {
int row = blockIdx.x;
int tid = threadIdx.x;
const float* __restrict__ xr = x + (int64_t)row * cols;
float* __restrict__ yr = out + (int64_t)row * cols;
float sum = 0.0f;
// Unroll the strided load loop to reduce loop overhead. For the benchmark
// cols=65535 and blockDim=256, so each thread handles about 256 elements.
int i = tid;
int stride = blockDim.x;
for (; i + 3 * stride < cols; i += 4 * stride) {
float v0 = xr[i];
float v1 = xr[i + stride];
float v2 = xr[i + 2 * stride];
float v3 = xr[i + 3 * stride];
sum += fabsf(v0) + fabsf(v1) + fabsf(v2) + fabsf(v3);
}
for (; i < cols; i += stride) {
sum += fabsf(xr[i]);
}
// Warp reductions, then one warp reduces the warp sums.
sum += __shfl_down_sync(0xffffffff, sum, 16);
sum += __shfl_down_sync(0xffffffff, sum, 8);
sum += __shfl_down_sync(0xffffffff, sum, 4);
sum += __shfl_down_sync(0xffffffff, sum, 2);
sum += __shfl_down_sync(0xffffffff, sum, 1);
__shared__ float warp_sums[8];
int lane = tid & 31;
int warp = tid >> 5;
if (lane == 0) warp_sums[warp] = sum;
__syncthreads();
float total = 0.0f;
if (tid < 8) total = warp_sums[tid];
if (warp == 0) {
total += __shfl_down_sync(0xffffffff, total, 4);
total += __shfl_down_sync(0xffffffff, total, 2);
total += __shfl_down_sync(0xffffffff, total, 1);
}
__shared__ float scale_s;
if (tid == 0) {
// x / mean(abs(x)) == x * cols / sum(abs(x)). PyTorch will produce
// inf/nan in the zero-sum case; division here mirrors that behavior.
scale_s = ((float)cols) / total;
}
__syncthreads();
float scale = scale_s;
i = tid;
for (; i + 3 * stride < cols; i += 4 * stride) {
float v0 = xr[i];
float v1 = xr[i + stride];
float v2 = xr[i + 2 * stride];
float v3 = xr[i + 3 * stride];
yr[i] = v0 * scale;
yr[i + stride] = v1 * scale;
yr[i + 2 * stride] = v2 * scale;
yr[i + 3 * stride] = v3 * scale;
}
for (; i < cols; i += stride) {
yr[i] = xr[i] * scale;
}
}
void l1_norm_cuda(torch::Tensor x, torch::Tensor out) {
const int64_t rows64 = x.size(0);
const int64_t cols64 = x.size(1);
const int rows = (int)rows64;
const int cols = (int)cols64;
const dim3 grid(rows);
const dim3 block(256);
cudaStream_t stream = at::cuda::getCurrentCUDAStream();
l1_norm_kernel_f32<<<grid, block, 0, stream>>>(x.data_ptr<float>(), out.data_ptr<float>(), rows, cols);
}
'''
_ext = load_inline(
name='l1_norm_ext_fast',
cpp_sources=_cpp_src,
cuda_sources=_cuda_src,
functions=['l1_norm'],
extra_cflags=['-O3'],
extra_cuda_cflags=['-O3', '--use_fast_math'],
verbose=False,
)
class ModelNew(nn.Module):
def __init__(self):
super(ModelNew, self).__init__()
def forward(self, x: torch.Tensor) -> torch.Tensor:
return _ext.l1_norm(x)