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 <vector>\n\ntorch::Tensor conv_transpose3d_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias,\n std::vector<int64_t> stride, std::vector<int64_t> padding,\n std::vector<int64_t> output_padding, int64_t groups, bool has_bias);\n\ntorch::Tensor conv_transpose3d_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias,\n std::vector<int64_t> stride, std::vector<int64_t> padding,\n std::vector<int64_t> output_padding, int64_t groups, bool has_bias) {\n return conv_transpose3d_forward_cuda(x, weight, bias, stride, padding, output_padding, groups, has_bias);\n}\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__global__ void pack_w_kernel(const float* __restrict__ w, float* __restrict__ wp,\n int Ci, int CoG, int KD, int KH, int KW, int total) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int t = idx;\n int kw = t % KW; t /= KW;\n int kh = t % KH; t /= KH;\n int kd = t % KD; t /= KD;\n int co = t % CoG; t /= CoG;\n int ci = t;\n int out = (((ci * KD + kd) * KH + kh) * KW + kw) * CoG + co;\n wp[out] = w[idx];\n}\n\n// Optimized path for the benchmark case: groups=1 and out_channels=16.\n// One half-warp computes all 16 output channels for one (n,d,h,w) output position.\n__global__ void deconv3d_s1_co16_kernel(const float* __restrict__ x,\n const float* __restrict__ wp,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int N, int Ci, int D, int H, int W,\n int Do, int Ho, int Wo,\n int KD, int KH, int KW,\n int pD, int pH, int pW,\n bool has_bias, long long positions) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n int lane = threadIdx.x & 31;\n int half = lane >> 4;\n int co = lane & 15;\n long long pos = ((long long)tid) >> 4;\n if (pos >= positions) return;\n\n int ow = (int)(pos % Wo);\n long long q = pos / Wo;\n int oh = (int)(q % Ho); q /= Ho;\n int od = (int)(q % Do); q /= Do;\n int n = (int)q;\n\n float acc = has_bias ? __ldg(bias + co) : 0.0f;\n\n int odpg = od + pD;\n int ohpg = oh + pH;\n int owpg = ow + pW;\n\n int kd0 = odpg - (D - 1); if (kd0 < 0) kd0 = 0;\n int kh0 = ohpg - (H - 1); if (kh0 < 0) kh0 = 0;\n int kw0 = owpg - (W - 1); if (kw0 < 0) kw0 = 0;\n int kd1 = odpg; if (kd1 > KD - 1) kd1 = KD - 1;\n int kh1 = ohpg; if (kh1 > KH - 1) kh1 = KH - 1;\n int kw1 = owpg; if (kw1 > KW - 1) kw1 = KW - 1;\n\n unsigned mask = half ? 0xFFFF0000u : 0x0000FFFFu;\n int leader = half << 4;\n\n long long nbase = ((long long)n * Ci * D * H * W);\n for (int ci = 0; ci < Ci; ++ci) {\n long long cbase = nbase + (long long)ci * D * H * W;\n for (int kd = kd0; kd <= kd1; ++kd) {\n int id = odpg - kd;\n long long dbase = cbase + (long long)id * H * W;\n for (int kh = kh0; kh <= kh1; ++kh) {\n int ih = ohpg - kh;\n long long hbase = dbase + (long long)ih * W;\n int wpo_base = (((ci * KD + kd) * KH + kh) * KW + kw0) * 16 + co;\n for (int kw = kw0; kw <= kw1; ++kw) {\n float xv = 0.0f;\n if (co == 0) {\n int iw = owpg - kw;\n xv = __ldg(x + hbase + iw);\n }\n xv = __shfl_sync(mask, xv, leader, 32);\n float wv = __ldg(wp + wpo_base);\n acc = fmaf(xv, wv, acc);\n wpo_base += 16;\n }\n }\n }\n }\n long long yidx = (((((long long)n * 16 + co) * Do + od) * Ho + oh) * Wo + ow);\n y[yidx] = acc;\n}\n\n__global__ void deconv3d_generic_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int N, int Ci, int Co, int D, int H, int W,\n int Do, int Ho, int Wo,\n int KD, int KH, int KW,\n int sD, int sH, int sW,\n int pD, int pH, int pW,\n int groups, bool has_bias,\n long long total) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int ow = (int)(idx % Wo); long long t = idx / Wo;\n int oh = (int)(t % Ho); t /= Ho;\n int od = (int)(t % Do); t /= Do;\n int co = (int)(t % Co); t /= Co;\n int n = (int)t;\n int CoG = Co / groups;\n int CiG = Ci / groups;\n int g = co / CoG;\n int cog = co - g * CoG;\n float acc = has_bias ? __ldg(bias + co) : 0.0f;\n for (int cig = 0; cig < CiG; ++cig) {\n int ci = g * CiG + cig;\n for (int kd = 0; kd < KD; ++kd) {\n int idn = od + pD - kd;\n if (idn < 0 || idn % sD) continue;\n int id = idn / sD;\n if (id < 0 || id >= D) continue;\n for (int kh = 0; kh < KH; ++kh) {\n int ihn = oh + pH - kh;\n if (ihn < 0 || ihn % sH) continue;\n int ih = ihn / sH;\n if (ih < 0 || ih >= H) continue;\n for (int kw = 0; kw < KW; ++kw) {\n int iwn = ow + pW - kw;\n if (iwn < 0 || iwn % sW) continue;\n int iw = iwn / sW;\n if (iw < 0 || iw >= W) continue;\n long long xidx = (((((long long)n * Ci + ci) * D + id) * H + ih) * W + iw);\n long long widx = (((((long long)ci * CoG + cog) * KD + kd) * KH + kh) * KW + kw);\n acc = fmaf(__ldg(x + xidx), __ldg(w + widx), acc);\n }\n }\n }\n }\n y[idx] = acc;\n}\n\ntorch::Tensor conv_transpose3d_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias,\n std::vector<int64_t> stride, std::vector<int64_t> padding,\n std::vector<int64_t> output_padding, int64_t groups64, bool has_bias) {\n int N = (int)x.size(0);\n int Ci = (int)x.size(1);\n int D = (int)x.size(2);\n int H = (int)x.size(3);\n int W = (int)x.size(4);\n int CoG = (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 groups = (int)groups64;\n int Co = CoG * groups;\n int sD = (int)stride[0], sH = (int)stride[1], sW = (int)stride[2];\n int pD = (int)padding[0], pH = (int)padding[1], pW = (int)padding[2];\n int opD = (int)output_padding[0], opH = (int)output_padding[1], opW = (int)output_padding[2];\n int Do = (D - 1) * sD - 2 * pD + KD + opD;\n int Ho = (H - 1) * sH - 2 * pH + KH + opH;\n int Wo = (W - 1) * sW - 2 * pW + KW + opW;\n auto y = torch::empty({N, Co, Do, Ho, Wo}, x.options());\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n\n if (x.scalar_type() == at::kFloat && weight.scalar_type() == at::kFloat && groups == 1 && Co == 16 && sD == 1 && sH == 1 && sW == 1) {\n auto wp = torch::empty({Ci, KD, KH, KW, 16}, weight.options());\n int totalw = Ci * 16 * KD * KH * KW;\n pack_w_kernel<<<(totalw + 255) / 256, 256, 0, stream>>>(weight.data_ptr<float>(), wp.data_ptr<float>(), Ci, 16, KD, KH, KW, totalw);\n long long positions = (long long)N * Do * Ho * Wo;\n int threads = 128;\n int blocks = (int)(((positions * 16) + threads - 1) / threads);\n const float* bptr = has_bias ? bias.data_ptr<float>() : nullptr;\n deconv3d_s1_co16_kernel<<<blocks, threads, 0, stream>>>(x.data_ptr<float>(), wp.data_ptr<float>(), bptr, y.data_ptr<float>(),\n N, Ci, D, H, W, Do, Ho, Wo, KD, KH, KW, pD, pH, pW, has_bias, positions);\n } else {\n long long total = (long long)N * Co * Do * Ho * Wo;\n int threads = 256;\n int blocks = (int)((total + threads - 1) / threads);\n const float* bptr = has_bias ? bias.data_ptr<float>() : nullptr;\n deconv3d_generic_kernel<<<blocks, threads, 0, stream>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bptr, y.data_ptr<float>(),\n N, Ci, Co, D, H, W, Do, Ho, Wo, KD, KH, KW, sD, sH, sW, pD, pH, pW, groups, has_bias, total);\n }\n return y;\n}\n'''\n\n_ext = load_inline(\n name='custom_deconv3d_asym_ext',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['conv_transpose3d_forward'],\n extra_cflags=['-O3'],\n extra_cuda_cflags=['-O3'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_channels: int, out_channels: int, kernel_size: tuple, stride: tuple = (1, 1, 1), padding: tuple = (0, 0, 0), output_padding: tuple = (0, 0, 0), groups: int = 1, bias: bool = False):\n super(ModelNew, self).__init__()\n self.conv_transpose3d = nn.ConvTranspose3d(in_channels, out_channels, kernel_size, stride=stride, padding=padding, output_padding=output_padding, groups=groups, bias=bias)\n self.stride = tuple(stride)\n self.padding = tuple(padding)\n self.output_padding = tuple(output_padding)\n self.groups = groups\n self.has_bias = bias\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n # The benchmark tensors/parameters are contiguous; these preserve correctness for the common case at no-copy cost.\n if not x.is_contiguous():\n x = x.contiguous()\n w = self.conv_transpose3d.weight\n if not w.is_contiguous():\n w = w.contiguous()\n b = self.conv_transpose3d.bias\n if b is None:\n b = torch.empty(0, device=x.device, dtype=x.dtype)\n has_b = False\n else:\n has_b = True\n return _ext.conv_transpose3d_forward(x, w, b, list(self.stride), list(self.padding), list(self.output_padding), int(self.groups), bool(has_b))\n"
}