call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_src = r'''\n#include <torch/extension.h>\ntorch::Tensor groupnorm_silu_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, int64_t num_groups, double eps, bool affine);\n'''\n\ncuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__inline__ __device__ float warp_reduce_sum(float v) {\n #pragma unroll\n for (int offset = 16; offset > 0; offset >>= 1) v += __shfl_down_sync(0xffffffff, v, offset);\n return v;\n}\n\ntemplate<int BLOCK>\n__inline__ __device__ float block_reduce_sum(float v) {\n __shared__ float shared[32];\n int lane = threadIdx.x & 31;\n int wid = threadIdx.x >> 5;\n v = warp_reduce_sum(v);\n if (lane == 0) shared[wid] = v;\n __syncthreads();\n float val = (threadIdx.x < (BLOCK >> 5)) ? shared[lane] : 0.0f;\n if (wid == 0) val = warp_reduce_sum(val);\n if (threadIdx.x == 0) shared[0] = val;\n __syncthreads();\n val = shared[0];\n __syncthreads();\n return val;\n}\n\n__device__ __forceinline__ float silu_f(float v) {\n return v / (1.0f + expf(-v));\n}\n\ntemplate<int BLOCK, bool AFFINE>\n__global__ void gn_silu_vec4_kernel(const float* __restrict__ x, const float* __restrict__ weight, const float* __restrict__ bias,\n float* __restrict__ y, int C, int H, int W, int G,\n int elems_per_group, int channels_per_group, float eps) {\n int group_id = blockIdx.x;\n int n = group_id / G;\n int g = group_id - n * G;\n int HW = H * W;\n int c_start = g * channels_per_group;\n int base = ((n * C + c_start) * H) * W;\n int base4 = base >> 2;\n int e4 = elems_per_group >> 2;\n const float4* __restrict__ x4 = reinterpret_cast<const float4*>(x);\n float4* __restrict__ y4 = reinterpret_cast<float4*>(y);\n\n float sum = 0.0f, sumsq = 0.0f;\n for (int i = threadIdx.x; i < e4; i += BLOCK) {\n float4 r = x4[base4 + i];\n sum += r.x + r.y + r.z + r.w;\n sumsq = fmaf(r.x, r.x, sumsq);\n sumsq = fmaf(r.y, r.y, sumsq);\n sumsq = fmaf(r.z, r.z, sumsq);\n sumsq = fmaf(r.w, r.w, sumsq);\n }\n float total = block_reduce_sum<BLOCK>(sum);\n float total2 = block_reduce_sum<BLOCK>(sumsq);\n float mean = total / (float)elems_per_group;\n float var = total2 / (float)elems_per_group - mean * mean;\n float invstd = rsqrtf(fmaxf(var, 0.0f) + eps);\n\n int HW4 = HW >> 2;\n for (int cl = 0; cl < channels_per_group; ++cl) {\n float ww = 1.0f, bb = 0.0f;\n if (AFFINE) { ww = weight[c_start + cl]; bb = bias[c_start + cl]; }\n int off4 = base4 + cl * HW4;\n for (int j = threadIdx.x; j < HW4; j += BLOCK) {\n float4 r = x4[off4 + j];\n r.x = fmaf((r.x - mean) * invstd, ww, bb);\n r.y = fmaf((r.y - mean) * invstd, ww, bb);\n r.z = fmaf((r.z - mean) * invstd, ww, bb);\n r.w = fmaf((r.w - mean) * invstd, ww, bb);\n r.x = silu_f(r.x); r.y = silu_f(r.y); r.z = silu_f(r.z); r.w = silu_f(r.w);\n y4[off4 + j] = r;\n }\n }\n}\n\ntemplate<int BLOCK, bool AFFINE>\n__global__ void gn_silu_scalar_kernel(const float* __restrict__ x, const float* __restrict__ weight, const float* __restrict__ bias,\n float* __restrict__ y, int C, int H, int W, int G,\n int elems_per_group, int channels_per_group, float eps) {\n int group_id = blockIdx.x;\n int n = group_id / G;\n int g = group_id - n * G;\n int HW = H * W;\n int c_start = g * channels_per_group;\n int base = ((n * C + c_start) * H) * W;\n float sum = 0.0f, sumsq = 0.0f;\n for (int i = threadIdx.x; i < elems_per_group; i += BLOCK) {\n float v = x[base + i]; sum += v; sumsq = fmaf(v, v, sumsq);\n }\n float total = block_reduce_sum<BLOCK>(sum);\n float total2 = block_reduce_sum<BLOCK>(sumsq);\n float mean = total / (float)elems_per_group;\n float invstd = rsqrtf(fmaxf(total2 / (float)elems_per_group - mean * mean, 0.0f) + eps);\n for (int cl = 0; cl < channels_per_group; ++cl) {\n float ww = 1.0f, bb = 0.0f;\n if (AFFINE) { ww = weight[c_start + cl]; bb = bias[c_start + cl]; }\n int off = base + cl * HW;\n for (int s = threadIdx.x; s < HW; s += BLOCK) {\n float v = fmaf((x[off + s] - mean) * invstd, ww, bb);\n y[off + s] = silu_f(v);\n }\n }\n}\n\ntorch::Tensor groupnorm_silu_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, int64_t num_groups, double eps, bool affine) {\n auto y = torch::empty_like(x);\n int N = (int)x.size(0), C = (int)x.size(1), H = (int)x.size(2), W = (int)x.size(3);\n int G = (int)num_groups;\n int channels_per_group = C / G;\n int elems_per_group = channels_per_group * H * W;\n const int BLOCK = 256;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n const float* w = affine ? weight.data_ptr<float>() : nullptr;\n const float* b = affine ? bias.data_ptr<float>() : nullptr;\n if (((H * W) & 3) == 0) {\n if (affine) gn_silu_vec4_kernel<BLOCK, true><<<N * G, BLOCK, 0, stream>>>(x.data_ptr<float>(), w, b, y.data_ptr<float>(), C, H, W, G, elems_per_group, channels_per_group, (float)eps);\n else gn_silu_vec4_kernel<BLOCK, false><<<N * G, BLOCK, 0, stream>>>(x.data_ptr<float>(), w, b, y.data_ptr<float>(), C, H, W, G, elems_per_group, channels_per_group, (float)eps);\n } else {\n if (affine) gn_silu_scalar_kernel<BLOCK, true><<<N * G, BLOCK, 0, stream>>>(x.data_ptr<float>(), w, b, y.data_ptr<float>(), C, H, W, G, elems_per_group, channels_per_group, (float)eps);\n else gn_silu_scalar_kernel<BLOCK, false><<<N * G, BLOCK, 0, stream>>>(x.data_ptr<float>(), w, b, y.data_ptr<float>(), C, H, W, G, elems_per_group, channels_per_group, (float)eps);\n }\n return y;\n}\n'''\n\n_ext = load_inline(name='gn_silu_ext_v5c', cpp_sources=cpp_src, cuda_sources=cuda_src,\n functions=['groupnorm_silu_forward'], verbose=False,\n extra_cuda_cflags=['-O3', '--use_fast_math'], extra_cflags=['-O3'])\n\nclass ModelNew(nn.Module):\n def __init__(self, num_channels: int, num_groups: int, eps: float = 1e-5, affine: bool = True):\n super().__init__()\n assert num_channels % num_groups == 0\n self.num_channels = num_channels\n self.num_groups = num_groups\n self.eps = eps\n self.affine = affine\n self.norm = nn.GroupNorm(num_groups=num_groups, num_channels=num_channels, eps=eps, affine=affine)\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n if self.affine:\n return _ext.groupnorm_silu_forward(x, self.norm.weight, self.norm.bias, self.num_groups, self.eps, True)\n dummy = torch.empty(0, device=x.device, dtype=x.dtype)\n return _ext.groupnorm_silu_forward(x, dummy, dummy, self.num_groups, self.eps, False)\n"
}