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#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAGuard.h>\n\ntorch::Tensor fused_deconv_pool_avg_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double scale);\n\ntorch::Tensor fused_deconv_pool_avg(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double scale) {\n return fused_deconv_pool_avg_cuda(x, weight, bias, scale);\n}\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAGuard.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <float.h>\n\n__global__ void fused_kernel_ks3_s2_p1_pool2(\n const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ out,\n int N, int D, int H, int W, int Cout, float scale)\n{\n // One block computes one (batch, output-channel) result.\n int bc = blockIdx.x;\n int oc = bc % Cout;\n int n = bc / Cout;\n int tid = threadIdx.x;\n\n __shared__ float smem[81 + 32]; // weights for 3 input channels * 3*3*3, then warp sums\n float* sw = smem;\n float* warp_sums = smem + 81;\n\n // Cache the small weight tile for this output channel. PyTorch ConvTranspose3d\n // weight layout is [Cin, Cout, kD, kH, kW].\n if (tid < 81) {\n int t = tid;\n int kw = t % 3; t /= 3;\n int kh = t % 3; t /= 3;\n int kd = t % 3; t /= 3;\n int ic = t;\n sw[tid] = weight[((((ic * Cout + oc) * 3 + kd) * 3 + kh) * 3 + kw)];\n }\n __syncthreads();\n\n int PD = D - 1;\n int PH = H - 1;\n int PW = W - 1;\n int P = PD * PH * PW;\n\n float local = 0.0f;\n int plane = H * W;\n int nbase = n * 3 * D * H * W;\n\n for (int idx = tid; idx < P; idx += blockDim.x) {\n int tmp = idx;\n int pw = tmp % PW; tmp /= PW;\n int ph = tmp % PH;\n int pd = tmp / PH;\n\n float v000 = 0.0f, v001 = 0.0f, v010 = 0.0f, v011 = 0.0f;\n float v100 = 0.0f, v101 = 0.0f, v110 = 0.0f, v111 = 0.0f;\n\n #pragma unroll\n for (int ic = 0; ic < 3; ++ic) {\n const float* xp = x + nbase + ic * D * H * W + pd * plane + ph * W + pw;\n float x000 = __ldg(xp);\n float x001 = __ldg(xp + 1);\n float x010 = __ldg(xp + W);\n float x011 = __ldg(xp + W + 1);\n float x100 = __ldg(xp + plane);\n float x101 = __ldg(xp + plane + 1);\n float x110 = __ldg(xp + plane + W);\n float x111 = __ldg(xp + plane + W + 1);\n\n const float* w = sw + ic * 27;\n // Names are v[output parity d,h,w]. For odd transposed-conv output\n // positions, either neighboring input element contributes.\n v000 = fmaf(x000, w[13], v000); // 111\n\n v001 = fmaf(x000, w[14], v001); // 112\n v001 = fmaf(x001, w[12], v001); // 110\n\n v010 = fmaf(x000, w[16], v010); // 121\n v010 = fmaf(x010, w[10], v010); // 101\n\n v011 = fmaf(x000, w[17], v011); // 122\n v011 = fmaf(x001, w[15], v011); // 120\n v011 = fmaf(x010, w[11], v011); // 102\n v011 = fmaf(x011, w[9], v011); // 100\n\n v100 = fmaf(x000, w[22], v100); // 211\n v100 = fmaf(x100, w[4], v100); // 011\n\n v101 = fmaf(x000, w[23], v101); // 212\n v101 = fmaf(x001, w[21], v101); // 210\n v101 = fmaf(x100, w[5], v101); // 012\n v101 = fmaf(x101, w[3], v101); // 010\n\n v110 = fmaf(x000, w[25], v110); // 221\n v110 = fmaf(x010, w[19], v110); // 201\n v110 = fmaf(x100, w[7], v110); // 021\n v110 = fmaf(x110, w[1], v110); // 001\n\n v111 = fmaf(x000, w[26], v111); // 222\n v111 = fmaf(x001, w[24], v111); // 220\n v111 = fmaf(x010, w[20], v111); // 202\n v111 = fmaf(x011, w[18], v111); // 200\n v111 = fmaf(x100, w[8], v111); // 022\n v111 = fmaf(x101, w[6], v111); // 020\n v111 = fmaf(x110, w[2], v111); // 002\n v111 = fmaf(x111, w[0], v111); // 000\n }\n\n float m01 = fmaxf(v000, v001);\n float m23 = fmaxf(v010, v011);\n float m45 = fmaxf(v100, v101);\n float m67 = fmaxf(v110, v111);\n float m = fmaxf(fmaxf(m01, m23), fmaxf(m45, m67));\n local += m;\n }\n\n // Block reduction.\n unsigned mask = 0xffffffffu;\n for (int off = 16; off > 0; off >>= 1) {\n local += __shfl_down_sync(mask, local, off);\n }\n int lane = tid & 31;\n int warp = tid >> 5;\n if (lane == 0) warp_sums[warp] = local;\n __syncthreads();\n\n if (warp == 0) {\n float sum = (tid < (blockDim.x >> 5)) ? warp_sums[lane] : 0.0f;\n for (int off = 16; off > 0; off >>= 1) {\n sum += __shfl_down_sync(mask, sum, off);\n }\n if (tid == 0) {\n float y = scale * (bias[oc] + sum / (float)P);\n y = fminf(1.0f, fmaxf(0.0f, y));\n out[((n * Cout + oc))] = y;\n }\n }\n}\n\ntorch::Tensor fused_deconv_pool_avg_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double scale) {\n const c10::cuda::CUDAGuard device_guard(x.device());\n int N = (int)x.size(0);\n int D = (int)x.size(2);\n int H = (int)x.size(3);\n int W = (int)x.size(4);\n int Cout = (int)weight.size(1);\n auto out = torch::empty({N, Cout, 1, 1, 1}, x.options());\n\n dim3 block(256);\n dim3 grid(N * Cout);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n fused_kernel_ks3_s2_p1_pool2<<<grid, block, 0, stream>>>(\n x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), out.data_ptr<float>(),\n N, D, H, W, Cout, (float)scale);\n return out;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"fused_deconv3d_pool_avg_ext_v1\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"fused_deconv_pool_avg\"],\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, stride, padding, scale, maxpool_kernel_size):\n super(ModelNew, self).__init__()\n self.conv_transpose = nn.ConvTranspose3d(in_channels, out_channels, kernel_size, stride=stride, padding=padding)\n self.scale = scale\n self.maxpool_kernel_size = maxpool_kernel_size\n self.clamp_min = 0\n self.clamp_max = 1\n\n def forward(self, x):\n return _ext.fused_deconv_pool_avg(x, self.conv_transpose.weight, self.conv_transpose.bias, float(self.scale))\n"
}