call → compile_kernel
callcompile_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>\ntorch::Tensor fused_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double hmin, double hmax);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <math.h>\n\ntemplate<int BLOCK>\n__global__ void fused_ct_pool_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ b,\n float* __restrict__ out,\n float hmin, float hmax) {\n // fixed problem: N,IC,OC,H,W = 128,64,64,256,256, k=3, pad=1, pool 2x2/2\n const int oc = blockIdx.x;\n const int n = blockIdx.y;\n const int tid = threadIdx.x;\n constexpr int IC = 64;\n constexpr int H = 256;\n constexpr int W = 256;\n constexpr int PH = 128;\n constexpr int PW = 128;\n extern __shared__ float smem[];\n float* sw = smem; // 64*9\n for (int i = tid; i < IC*9; i += BLOCK) {\n int ic = i / 9;\n int r = i - ic*9;\n // weight layout: [in_c, out_c, kh, kw] contiguous (((ic*OC+oc)*3+kh)*3+kw)\n sw[i] = w[((ic * 64 + oc) * 9) + r];\n }\n __syncthreads();\n\n const float* xb = x + ((size_t)n * IC * H * W);\n const float bias = b[oc];\n float tsum = 0.0f;\n\n for (int idx = tid; idx < PH*PW; idx += BLOCK) {\n int ph = idx >> 7; // /128\n int pw = idx & 127;\n int oh = ph << 1;\n int ow = pw << 1;\n float v00 = bias, v01 = bias, v10 = bias, v11 = bias;\n\n if (ph > 0 && ph < 127 && pw > 0 && pw < 127) {\n // Fully interior: no bounds checks. ConvTranspose2d stride=1,pad=1.\n #pragma unroll 4\n for (int ic = 0; ic < IC; ++ic) {\n const float* xi = xb + (size_t)ic * H * W;\n const float* ww = sw + ic * 9;\n int base = oh * W + ow;\n // rows oh-1,oh,oh+1,oh+2 and cols ow-1..ow+2\n float xm1m1 = xi[base - W - 1];\n float xm1_0 = xi[base - W];\n float xm1p1 = xi[base - W + 1];\n float xm1p2 = xi[base - W + 2];\n float x0m1 = xi[base - 1];\n float x0_0 = xi[base];\n float x0p1 = xi[base + 1];\n float x0p2 = xi[base + 2];\n float xp1m1 = xi[base + W - 1];\n float xp1_0 = xi[base + W];\n float xp1p1 = xi[base + W + 1];\n float xp1p2 = xi[base + W + 2];\n float xp2m1 = xi[base + 2*W - 1];\n float xp2_0 = xi[base + 2*W];\n float xp2p1 = xi[base + 2*W + 1];\n float xp2p2 = xi[base + 2*W + 2];\n // ww[0]=kh0kw0 multiplies input (oh+1,ow+1) for y(oh,ow)\n v00 = fmaf(xp1p1, ww[0], v00);\n v00 = fmaf(xp1_0, ww[1], v00);\n v00 = fmaf(xp1m1, ww[2], v00);\n v00 = fmaf(x0p1, ww[3], v00);\n v00 = fmaf(x0_0, ww[4], v00);\n v00 = fmaf(x0m1, ww[5], v00);\n v00 = fmaf(xm1p1, ww[6], v00);\n v00 = fmaf(xm1_0, ww[7], v00);\n v00 = fmaf(xm1m1, ww[8], v00);\n\n v01 = fmaf(xp1p2, ww[0], v01);\n v01 = fmaf(xp1p1, ww[1], v01);\n v01 = fmaf(xp1_0, ww[2], v01);\n v01 = fmaf(x0p2, ww[3], v01);\n v01 = fmaf(x0p1, ww[4], v01);\n v01 = fmaf(x0_0, ww[5], v01);\n v01 = fmaf(xm1p2, ww[6], v01);\n v01 = fmaf(xm1p1, ww[7], v01);\n v01 = fmaf(xm1_0, ww[8], v01);\n\n v10 = fmaf(xp2p1, ww[0], v10);\n v10 = fmaf(xp2_0, ww[1], v10);\n v10 = fmaf(xp2m1, ww[2], v10);\n v10 = fmaf(xp1p1, ww[3], v10);\n v10 = fmaf(xp1_0, ww[4], v10);\n v10 = fmaf(xp1m1, ww[5], v10);\n v10 = fmaf(x0p1, ww[6], v10);\n v10 = fmaf(x0_0, ww[7], v10);\n v10 = fmaf(x0m1, ww[8], v10);\n\n v11 = fmaf(xp2p2, ww[0], v11);\n v11 = fmaf(xp2p1, ww[1], v11);\n v11 = fmaf(xp2_0, ww[2], v11);\n v11 = fmaf(xp1p2, ww[3], v11);\n v11 = fmaf(xp1p1, ww[4], v11);\n v11 = fmaf(xp1_0, ww[5], v11);\n v11 = fmaf(x0p2, ww[6], v11);\n v11 = fmaf(x0p1, ww[7], v11);\n v11 = fmaf(x0_0, ww[8], v11);\n }\n } else {\n // boundary slow path\n #pragma unroll 4\n for (int ic = 0; ic < IC; ++ic) {\n const float* xi = xb + (size_t)ic * H * W;\n const float* ww = sw + ic * 9;\n #pragma unroll\n for (int kh = 0; kh < 3; ++kh) {\n int ih0 = oh + 1 - kh;\n int ih1 = oh + 2 - kh;\n bool vh0 = (ih0 >= 0 && ih0 < H);\n bool vh1 = (ih1 >= 0 && ih1 < H);\n #pragma unroll\n for (int kw = 0; kw < 3; ++kw) {\n float wt = ww[kh*3+kw];\n int iw0 = ow + 1 - kw;\n int iw1 = ow + 2 - kw;\n bool vw0 = (iw0 >= 0 && iw0 < W);\n bool vw1 = (iw1 >= 0 && iw1 < W);\n if (vh0 && vw0) v00 = fmaf(xi[ih0*W + iw0], wt, v00);\n if (vh0 && vw1) v01 = fmaf(xi[ih0*W + iw1], wt, v01);\n if (vh1 && vw0) v10 = fmaf(xi[ih1*W + iw0], wt, v10);\n if (vh1 && vw1) v11 = fmaf(xi[ih1*W + iw1], wt, v11);\n }\n }\n }\n }\n float m = fmaxf(fmaxf(v00, v01), fmaxf(v10, v11));\n m = fminf(fmaxf(m, hmin), hmax);\n tsum += m;\n }\n\n // block reduction\n #pragma unroll\n for (int offset = 16; offset > 0; offset >>= 1) {\n tsum += __shfl_down_sync(0xffffffff, tsum, offset);\n }\n __shared__ float warp_sums[32];\n int lane = tid & 31;\n int warp = tid >> 5;\n if (lane == 0) warp_sums[warp] = tsum;\n __syncthreads();\n if (warp == 0) {\n float s = (lane < (BLOCK/32)) ? warp_sums[lane] : 0.0f;\n #pragma unroll\n for (int offset = 16; offset > 0; offset >>= 1) {\n s += __shfl_down_sync(0xffffffff, s, offset);\n }\n if (lane == 0) {\n float mean = s * (1.0f / 16384.0f);\n out[((size_t)n * 64 + oc)] = tanhf(mean);\n }\n }\n}\n\ntorch::Tensor fused_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double hmin, double hmax) {\n auto out = torch::empty({x.size(0), weight.size(1), 1, 1}, x.options());\n const int BLOCK = 256;\n dim3 grid((unsigned)weight.size(1), (unsigned)x.size(0));\n size_t shmem = 64 * 9 * sizeof(float);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n fused_ct_pool_kernel<BLOCK><<<grid, BLOCK, shmem, stream>>>(\n x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), out.data_ptr<float>(), (float)hmin, (float)hmax);\n return out;\n}\n'''\n\n_ext = load_inline(name='fused_ct_pool_ext_v1', cpp_sources=[_cpp_src], cuda_sources=[_cuda_src], functions=['fused_forward'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_channels, out_channels, kernel_size, stride, padding, maxpool_kernel_size, maxpool_stride, hardtanh_min, hardtanh_max):\n super(ModelNew, self).__init__()\n self.conv_transpose = nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding)\n self.hardtanh_min = float(hardtanh_min)\n self.hardtanh_max = float(hardtanh_max)\n def forward(self, x):\n return _ext.fused_forward(x.contiguous(), self.conv_transpose.weight, self.conv_transpose.bias, self.hardtanh_min, self.hardtanh_max)\n"
}