call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n\ntorch::Tensor fused_forward(torch::Tensor x,\n torch::Tensor weight,\n torch::Tensor bias,\n torch::Tensor bn_weight,\n torch::Tensor bn_bias,\n torch::Tensor running_mean,\n torch::Tensor running_var,\n double scale,\n double eps,\n bool training);\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 <algorithm>\n\n__global__ void input_sum_kernel(const float* __restrict__ x, float* __restrict__ in_sum,\n int N, int Cin, int D, int H, int W) {\n extern __shared__ float sdata[];\n int idx = blockIdx.x;\n int n = idx / Cin;\n int c = idx - n * Cin;\n int S = D * H * W;\n float acc = 0.0f;\n const float* base = x + ((n * Cin + c) * S);\n for (int i = threadIdx.x; i < S; i += blockDim.x) acc += base[i];\n sdata[threadIdx.x] = acc;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (threadIdx.x < stride) sdata[threadIdx.x] += sdata[threadIdx.x + stride];\n __syncthreads();\n }\n if (threadIdx.x == 0) in_sum[idx] = sdata[0];\n}\n\n__global__ void weight_sum_kernel(const float* __restrict__ w, float* __restrict__ w_sum,\n int Cin, int Cout, int Kd, int Kh, int Kw) {\n extern __shared__ float sdata[];\n int idx = blockIdx.x;\n int ic = idx / Cout;\n int oc = idx - ic * Cout;\n int K = Kd * Kh * Kw;\n const float* base = w + ((ic * Cout + oc) * K);\n float acc = 0.0f;\n for (int i = threadIdx.x; i < K; i += blockDim.x) acc += base[i];\n sdata[threadIdx.x] = acc;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (threadIdx.x < stride) sdata[threadIdx.x] += sdata[threadIdx.x + stride];\n __syncthreads();\n }\n if (threadIdx.x == 0) w_sum[idx] = sdata[0];\n}\n\n__global__ void eval_out_kernel(const float* __restrict__ in_sum,\n const float* __restrict__ w_sum,\n const float* __restrict__ bias,\n const float* __restrict__ gamma,\n const float* __restrict__ beta,\n const float* __restrict__ rmean,\n const float* __restrict__ rvar,\n float* __restrict__ out,\n int N, int Cin, int Cout, int Vout,\n float scale, float eps) {\n extern __shared__ float sdata[];\n int bid = blockIdx.x;\n int n = bid / Cout;\n int oc = bid - n * Cout;\n float acc = 0.0f;\n for (int ic = threadIdx.x; ic < Cin; ic += blockDim.x) {\n acc += in_sum[n * Cin + ic] * w_sum[ic * Cout + oc];\n }\n sdata[threadIdx.x] = acc;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (threadIdx.x < stride) sdata[threadIdx.x] += sdata[threadIdx.x + stride];\n __syncthreads();\n }\n if (threadIdx.x == 0) {\n float conv_avg = (sdata[0] + bias[oc] * (float)Vout) / (float)Vout;\n float v = conv_avg * scale;\n float y = (v - rmean[oc]) * rsqrtf(rvar[oc] + eps) * gamma[oc] + beta[oc];\n out[n * Cout + oc] = y;\n }\n}\n\n__global__ void conv_sum_kernel(const float* __restrict__ in_sum,\n const float* __restrict__ w_sum,\n const float* __restrict__ bias,\n float* __restrict__ conv_sum,\n int N, int Cin, int Cout, int Vout) {\n extern __shared__ float sdata[];\n int bid = blockIdx.x;\n int n = bid / Cout;\n int oc = bid - n * Cout;\n float acc = 0.0f;\n for (int ic = threadIdx.x; ic < Cin; ic += blockDim.x) {\n acc += in_sum[n * Cin + ic] * w_sum[ic * Cout + oc];\n }\n sdata[threadIdx.x] = acc;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (threadIdx.x < stride) sdata[threadIdx.x] += sdata[threadIdx.x + stride];\n __syncthreads();\n }\n if (threadIdx.x == 0) conv_sum[n * Cout + oc] = sdata[0] + bias[oc] * (float)Vout;\n}\n\n__global__ void sumsq_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ sumsq,\n int N, int Cin, int Cout,\n int D, int H, int Wd,\n int Kd, int Kh, int Kw,\n int OD, int OH, int OW,\n float scale, int blocks_per_oc) {\n int global_bid = blockIdx.x;\n int oc = global_bid / blocks_per_oc;\n int local_bid = global_bid - oc * blocks_per_oc;\n int M = N * OD * OH * OW;\n float acc2 = 0.0f;\n int stride = blockDim.x * blocks_per_oc;\n for (int m = local_bid * blockDim.x + threadIdx.x; m < M; m += stride) {\n int t = m;\n int ow = t % OW; t /= OW;\n int oh = t % OH; t /= OH;\n int od = t % OD; t /= OD;\n int n = t;\n float val = bias[oc];\n int kd0 = max(0, od - (D - 1));\n int kd1 = min(Kd - 1, od);\n int kh0 = max(0, oh - (H - 1));\n int kh1 = min(Kh - 1, oh);\n int kw0 = max(0, ow - (Wd - 1));\n int kw1 = min(Kw - 1, ow);\n for (int ic = 0; ic < Cin; ++ic) {\n for (int kd = kd0; kd <= kd1; ++kd) {\n int id = od - kd;\n for (int kh = kh0; kh <= kh1; ++kh) {\n int ih = oh - kh;\n const float* xb = x + (((n * Cin + ic) * D + id) * H + ih) * Wd;\n const float* wb = w + (((ic * Cout + oc) * Kd + kd) * Kh + kh) * Kw;\n for (int kw = kw0; kw <= kw1; ++kw) {\n val += xb[ow - kw] * wb[kw];\n }\n }\n }\n }\n float sv = val * scale;\n acc2 += sv * sv;\n }\n extern __shared__ float sdata[];\n sdata[threadIdx.x] = acc2;\n __syncthreads();\n for (int s = blockDim.x >> 1; s > 0; s >>= 1) {\n if (threadIdx.x < s) sdata[threadIdx.x] += sdata[threadIdx.x + s];\n __syncthreads();\n }\n if (threadIdx.x == 0) atomicAdd(sumsq + oc, sdata[0]);\n}\n\n__global__ void train_out_kernel(const float* __restrict__ conv_sum,\n const float* __restrict__ sumsq,\n const float* __restrict__ gamma,\n const float* __restrict__ beta,\n float* __restrict__ out,\n int N, int Cout, int Vout,\n float scale, float eps) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = N * Cout;\n if (idx >= total) return;\n int n = idx / Cout;\n int oc = idx - n * Cout;\n float tsum = 0.0f;\n for (int i = 0; i < N; ++i) tsum += conv_sum[i * Cout + oc];\n float invM = 1.0f / (float)(N * Vout);\n float mean = tsum * scale * invM;\n float var = sumsq[oc] * invM - mean * mean;\n if (var < 0.0f) var = 0.0f;\n float avg = conv_sum[n * Cout + oc] * scale / (float)Vout;\n out[idx] = (avg - mean) * rsqrtf(var + eps) * gamma[oc] + beta[oc];\n}\n\ntorch::Tensor fused_forward(torch::Tensor x,\n torch::Tensor weight,\n torch::Tensor bias,\n torch::Tensor bn_weight,\n torch::Tensor bn_bias,\n torch::Tensor running_mean,\n torch::Tensor running_var,\n double scale_d,\n double eps_d,\n bool training) {\n TORCH_CHECK(x.is_cuda(), \"x must be CUDA\");\n TORCH_CHECK(x.scalar_type() == at::kFloat, \"only float32 supported\");\n int N = (int)x.size(0);\n int Cin = (int)x.size(1);\n int D = (int)x.size(2);\n int H = (int)x.size(3);\n int Wd = (int)x.size(4);\n int Cout = (int)weight.size(1);\n int Kd = (int)weight.size(2);\n int Kh = (int)weight.size(3);\n int Kw = (int)weight.size(4);\n int OD = D + Kd - 1;\n int OH = H + Kh - 1;\n int OW = Wd + Kw - 1;\n int Vout = OD * OH * OW;\n auto opts = x.options();\n auto in_sum = torch::empty({N, Cin}, opts);\n auto w_sum = torch::empty({Cin, Cout}, opts);\n auto out = torch::empty({N, Cout, 1, 1, 1}, opts);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n const int T = 256;\n input_sum_kernel<<<N * Cin, T, T * sizeof(float), stream>>>(x.data_ptr<float>(), in_sum.data_ptr<float>(), N, Cin, D, H, Wd);\n weight_sum_kernel<<<Cin * Cout, T, T * sizeof(float), stream>>>(weight.data_ptr<float>(), w_sum.data_ptr<float>(), Cin, Cout, Kd, Kh, Kw);\n float scale = (float)scale_d;\n float eps = (float)eps_d;\n if (!training) {\n eval_out_kernel<<<N * Cout, T, T * sizeof(float), stream>>>(\n in_sum.data_ptr<float>(), w_sum.data_ptr<float>(), bias.data_ptr<float>(),\n bn_weight.data_ptr<float>(), bn_bias.data_ptr<float>(), running_mean.data_ptr<float>(), running_var.data_ptr<float>(),\n out.data_ptr<float>(), N, Cin, Cout, Vout, scale, eps);\n } else {\n auto conv_sum = torch::empty({N, Cout}, opts);\n conv_sum_kernel<<<N * Cout, T, T * sizeof(float), stream>>>(\n in_sum.data_ptr<float>(), w_sum.data_ptr<float>(), bias.data_ptr<float>(), conv_sum.data_ptr<float>(), N, Cin, Cout, Vout);\n auto sumsq = torch::zeros({Cout}, opts);\n int blocks_per_oc = 256;\n sumsq_kernel<<<Cout * blocks_per_oc, 128, 128 * sizeof(float), stream>>>(\n x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), sumsq.data_ptr<float>(),\n N, Cin, Cout, D, H, Wd, Kd, Kh, Kw, OD, OH, OW, scale, blocks_per_oc);\n int total = N * Cout;\n train_out_kernel<<<(total + 255) / 256, 256, 0, stream>>>(\n conv_sum.data_ptr<float>(), sumsq.data_ptr<float>(), bn_weight.data_ptr<float>(), bn_bias.data_ptr<float>(),\n out.data_ptr<float>(), N, Cout, Vout, scale, eps);\n }\n return out;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"fused_deconv_bn_gap_ext_v1\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"fused_forward\"],\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, in_channels, out_channels, kernel_size, scale_factor, eps=1e-5, momentum=0.1):\n super(ModelNew, self).__init__()\n self.conv_transpose = nn.ConvTranspose3d(in_channels, out_channels, kernel_size)\n self.scale_factor = scale_factor\n self.batch_norm = nn.BatchNorm3d(out_channels, eps=eps, momentum=momentum)\n self.global_avg_pool = nn.AdaptiveAvgPool3d((1, 1, 1))\n\n def forward(self, x):\n # The benchmark input and parameters are contiguous CUDA fp32 tensors. Keep a safe\n # contiguous view for the custom address arithmetic.\n if not x.is_contiguous():\n x = x.contiguous()\n return _ext.fused_forward(\n x,\n self.conv_transpose.weight,\n self.conv_transpose.bias,\n self.batch_norm.weight,\n self.batch_norm.bias,\n self.batch_norm.running_mean,\n self.batch_norm.running_var,\n float(self.scale_factor),\n float(self.batch_norm.eps),\n bool(self.training),\n )\n"
}