call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n\ntorch::Tensor fused_post(torch::Tensor conv,\n torch::Tensor bn_weight,\n torch::Tensor bn_bias,\n torch::Tensor running_mean,\n torch::Tensor running_var,\n torch::Tensor gn_weight,\n torch::Tensor gn_bias,\n bool bn_training,\n double bn_eps,\n int64_t num_groups,\n double gn_eps);\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 <vector>\n\n__inline__ __device__ float warp_reduce_sum(float v) {\n for (int offset = 16; offset > 0; offset >>= 1)\n v += __shfl_down_sync(0xffffffff, v, offset);\n return v;\n}\n\n__inline__ __device__ float block_reduce_sum(float v) {\n static __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 v = (threadIdx.x < (blockDim.x >> 5)) ? shared[lane] : 0.0f;\n if (wid == 0) v = warp_reduce_sum(v);\n return v;\n}\n\n__global__ void bn_stats_kernel(const float* __restrict__ x, float* __restrict__ mean, float* __restrict__ invstd,\n int N, int C, int H, int W, float eps) {\n int c = blockIdx.x;\n int HW = H * W;\n int M = N * HW;\n float sum = 0.0f;\n float sum2 = 0.0f;\n for (int i = threadIdx.x; i < M; i += blockDim.x) {\n int n = i / HW;\n int hw = i - n * HW;\n float v = x[((long long)n * C + c) * HW + hw];\n sum += v;\n sum2 = fmaf(v, v, sum2);\n }\n sum = block_reduce_sum(sum);\n sum2 = block_reduce_sum(sum2);\n if (threadIdx.x == 0) {\n float m = sum / (float)M;\n float var = sum2 / (float)M - m * m;\n var = var < 0.0f ? 0.0f : var;\n mean[c] = m;\n invstd[c] = rsqrtf(var + eps);\n }\n}\n\n__global__ void pool_bn_tanh_kernel(const float* __restrict__ x,\n const float* __restrict__ bn_weight,\n const float* __restrict__ bn_bias,\n const float* __restrict__ mean,\n const float* __restrict__ invstd,\n float* __restrict__ pooled,\n int total, int C, int H, int W, int PH, int PW) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int stride = blockDim.x * gridDim.x;\n int PHW = PH * PW;\n int HW = H * W;\n for (; idx < total; idx += stride) {\n int t = idx;\n int pw = t % PW; t /= PW;\n int ph = t % PH; t /= PH;\n int c = t % C;\n int n = t / C;\n int h0 = ph * 2;\n int w0 = pw * 2;\n float a = bn_weight[c] * invstd[c];\n float b = bn_bias[c] - mean[c] * a;\n long long base = ((long long)n * C + c) * HW + h0 * W + w0;\n float v0 = tanhf(fmaf(x[base], a, b));\n float v1 = tanhf(fmaf(x[base + 1], a, b));\n float v2 = tanhf(fmaf(x[base + W], a, b));\n float v3 = tanhf(fmaf(x[base + W + 1], a, b));\n float m = fmaxf(fmaxf(v0, v1), fmaxf(v2, v3));\n pooled[idx] = m;\n }\n}\n\n__global__ void group_stats_kernel(const float* __restrict__ pooled, float* __restrict__ gmean, float* __restrict__ grstd,\n int N, int C, int PH, int PW, int G, float eps) {\n int ng = blockIdx.x;\n int n = ng / G;\n int g = ng - n * G;\n int cpg = C / G;\n int PHW = PH * PW;\n int M = cpg * PHW;\n int c0 = g * cpg;\n float sum = 0.0f;\n float sum2 = 0.0f;\n long long nbase = (long long)n * C * PHW;\n for (int i = threadIdx.x; i < M; i += blockDim.x) {\n int lc = i / PHW;\n int hw = i - lc * PHW;\n float v = pooled[nbase + (long long)(c0 + lc) * PHW + hw];\n sum += v;\n sum2 = fmaf(v, v, sum2);\n }\n sum = block_reduce_sum(sum);\n sum2 = block_reduce_sum(sum2);\n if (threadIdx.x == 0) {\n float m = sum / (float)M;\n float var = sum2 / (float)M - m * m;\n var = var < 0.0f ? 0.0f : var;\n gmean[ng] = m;\n grstd[ng] = rsqrtf(var + eps);\n }\n}\n\n__global__ void group_apply_kernel(const float* __restrict__ pooled,\n const float* __restrict__ gmean,\n const float* __restrict__ grstd,\n const float* __restrict__ gn_weight,\n const float* __restrict__ gn_bias,\n float* __restrict__ out,\n int total, int C, int PH, int PW, int G) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int stride = blockDim.x * gridDim.x;\n int PHW = PH * PW;\n int cpg = C / G;\n for (; idx < total; idx += stride) {\n int t = idx;\n int hw = t % PHW; (void)hw;\n t /= PHW;\n int c = t % C;\n int n = t / C;\n int g = c / cpg;\n int ng = n * G + g;\n float v = (pooled[idx] - gmean[ng]) * grstd[ng];\n out[idx] = fmaf(v, gn_weight[c], gn_bias[c]);\n }\n}\n\ntorch::Tensor fused_post(torch::Tensor conv,\n torch::Tensor bn_weight,\n torch::Tensor bn_bias,\n torch::Tensor running_mean,\n torch::Tensor running_var,\n torch::Tensor gn_weight,\n torch::Tensor gn_bias,\n bool bn_training,\n double bn_eps_d,\n int64_t num_groups,\n double gn_eps_d) {\n TORCH_CHECK(conv.is_cuda(), \"conv must be CUDA\");\n TORCH_CHECK(conv.scalar_type() == at::kFloat, \"only float32 supported\");\n conv = conv.contiguous();\n int N = (int)conv.size(0);\n int C = (int)conv.size(1);\n int H = (int)conv.size(2);\n int W = (int)conv.size(3);\n int PH = (H - 2) / 2 + 1;\n int PW = (W - 2) / 2 + 1;\n float bn_eps = (float)bn_eps_d;\n float gn_eps = (float)gn_eps_d;\n auto opts = conv.options();\n auto mean = torch::empty({C}, opts);\n auto invstd = torch::empty({C}, opts);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n if (bn_training) {\n bn_stats_kernel<<<C, 256, 0, stream>>>(conv.data_ptr<float>(), mean.data_ptr<float>(), invstd.data_ptr<float>(), N, C, H, W, bn_eps);\n } else {\n // invstd from running variance; mean is running mean. Small one-block-per-channel kernel via bn_stats_kernel not suitable,\n // so use a simple lambda-like kernel implemented below by reusing group_apply? no: launch dedicated local kernel unavailable.\n // Fill using a tiny generic transform kernel defined inline as a separate launch below.\n int threads = 128;\n int blocks = (C + threads - 1) / threads;\n // use cuda kernel declared in this translation unit\n // placeholder replaced by actual kernel call\n \n // Direct copy/compute with at operations would add overhead; kernel below.\n extern void launch_bn_eval_params(const float*, const float*, float*, float*, int, float, cudaStream_t);\n launch_bn_eval_params(running_mean.data_ptr<float>(), running_var.data_ptr<float>(), mean.data_ptr<float>(), invstd.data_ptr<float>(), C, bn_eps, stream);\n }\n auto pooled = torch::empty({N, C, PH, PW}, opts);\n int total = N * C * PH * PW;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n if (blocks > 65535) blocks = 65535;\n pool_bn_tanh_kernel<<<blocks, threads, 0, stream>>>(conv.data_ptr<float>(), bn_weight.data_ptr<float>(), bn_bias.data_ptr<float>(), mean.data_ptr<float>(), invstd.data_ptr<float>(), pooled.data_ptr<float>(), total, C, H, W, PH, PW);\n int G = (int)num_groups;\n auto gmean = torch::empty({N, G}, opts);\n auto grstd = torch::empty({N, G}, opts);\n group_stats_kernel<<<N * G, 256, 0, stream>>>(pooled.data_ptr<float>(), gmean.data_ptr<float>(), grstd.data_ptr<float>(), N, C, PH, PW, G, gn_eps);\n auto out = torch::empty({N, C, PH, PW}, opts);\n group_apply_kernel<<<blocks, threads, 0, stream>>>(pooled.data_ptr<float>(), gmean.data_ptr<float>(), grstd.data_ptr<float>(), gn_weight.data_ptr<float>(), gn_bias.data_ptr<float>(), out.data_ptr<float>(), total, C, PH, PW, G);\n return out;\n}\n\n__global__ void bn_eval_params_kernel(const float* __restrict__ running_mean,\n const float* __restrict__ running_var,\n float* __restrict__ mean,\n float* __restrict__ invstd,\n int C, float eps) {\n int c = blockIdx.x * blockDim.x + threadIdx.x;\n if (c < C) {\n mean[c] = running_mean[c];\n invstd[c] = rsqrtf(running_var[c] + eps);\n }\n}\n\nvoid launch_bn_eval_params(const float* rm, const float* rv, float* mean, float* invstd, int C, float eps, cudaStream_t stream) {\n int threads = 128;\n int blocks = (C + threads - 1) / threads;\n bn_eval_params_kernel<<<blocks, threads, 0, stream>>>(rm, rv, mean, invstd, C, eps);\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"fused_deconv_bn_tanh_pool_gn_ext_v1\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"fused_post\"],\n extra_cflags=[\"-O3\"],\n extra_cuda_cflags=[\"-O3\"],\n with_cuda=True,\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_channels, out_channels, kernel_size, stride, padding, groups, num_groups):\n super(ModelNew, self).__init__()\n self.conv_transpose = nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding)\n self.batch_norm = nn.BatchNorm2d(out_channels)\n self.tanh = nn.Tanh()\n self.max_pool = nn.MaxPool2d(kernel_size=2, stride=2)\n self.group_norm = nn.GroupNorm(num_groups=num_groups, num_channels=out_channels)\n self.num_groups = num_groups\n\n def forward(self, x):\n y = F.conv_transpose2d(x, self.conv_transpose.weight, self.conv_transpose.bias,\n stride=self.conv_transpose.stride, padding=self.conv_transpose.padding,\n output_padding=self.conv_transpose.output_padding, groups=self.conv_transpose.groups,\n dilation=self.conv_transpose.dilation)\n return _ext.fused_post(y,\n self.batch_norm.weight, self.batch_norm.bias,\n self.batch_norm.running_mean, self.batch_norm.running_var,\n self.group_norm.weight, self.group_norm.bias,\n bool(self.batch_norm.training), float(self.batch_norm.eps),\n int(self.group_norm.num_groups), float(self.group_norm.eps))\n"
}