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 deconv3d_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias,\n int64_t stride, int64_t padding, int64_t dilation);\n\ntorch::Tensor deconv3d_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias,\n int64_t stride, int64_t padding, int64_t dilation) {\n return deconv3d_forward_cuda(x, weight, bias, stride, padding, dilation);\n}\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAException.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void init_bias_kernel(float* __restrict__ y, const float* __restrict__ bias,\n long total, int Cout, int outD, int outH, int outW) {\n long idx = blockIdx.x * (long)blockDim.x + threadIdx.x;\n long stride = (long)blockDim.x * gridDim.x;\n long spatial = (long)outD * outH * outW;\n for (long i = idx; i < total; i += stride) {\n int co = (int)((i / spatial) % Cout);\n y[i] = bias[co];\n }\n}\n\n__global__ void deconv3d_s2p1d2_k3_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ y,\n long total_nonzero,\n int N, int Cin, int Cout,\n int D, int H, int W,\n int outD, int outH, int outW,\n int has_bias) {\n long idx = blockIdx.x * (long)blockDim.x + threadIdx.x;\n if (idx >= total_nonzero) return;\n\n int iw = (int)(idx % W); idx /= W;\n int ih = (int)(idx % H); idx /= H;\n int id = (int)(idx % D); idx /= D;\n int co = (int)(idx % Cout);\n int n = (int)(idx / Cout);\n\n float acc = 0.0f;\n const long xNbase = ((long)n * Cin) * D * H * W;\n\n // Interior points: all 27 kernel taps are valid. Output coordinate is (2*id+1,2*ih+1,2*iw+1).\n if (id > 0 && id < D-1 && ih > 0 && ih < H-1 && iw > 0 && iw < W-1) {\n int id0 = id + 1, id1 = id, id2 = id - 1;\n int ih0 = ih + 1, ih1 = ih, ih2 = ih - 1;\n int iw0 = iw + 1, iw1 = iw, iw2 = iw - 1;\n #pragma unroll 1\n for (int ci = 0; ci < Cin; ++ci) {\n const float* xp = x + xNbase + ((long)ci * D * H * W);\n const float* wp = w + (((long)ci * Cout + co) * 27);\n long d0 = (long)id0 * H * W, d1 = (long)id1 * H * W, d2 = (long)id2 * H * W;\n long h0 = (long)ih0 * W, h1 = (long)ih1 * W, h2 = (long)ih2 * W;\n acc = fmaf(xp[d0 + h0 + iw0], wp[0], acc);\n acc = fmaf(xp[d0 + h0 + iw1], wp[1], acc);\n acc = fmaf(xp[d0 + h0 + iw2], wp[2], acc);\n acc = fmaf(xp[d0 + h1 + iw0], wp[3], acc);\n acc = fmaf(xp[d0 + h1 + iw1], wp[4], acc);\n acc = fmaf(xp[d0 + h1 + iw2], wp[5], acc);\n acc = fmaf(xp[d0 + h2 + iw0], wp[6], acc);\n acc = fmaf(xp[d0 + h2 + iw1], wp[7], acc);\n acc = fmaf(xp[d0 + h2 + iw2], wp[8], acc);\n acc = fmaf(xp[d1 + h0 + iw0], wp[9], acc);\n acc = fmaf(xp[d1 + h0 + iw1], wp[10], acc);\n acc = fmaf(xp[d1 + h0 + iw2], wp[11], acc);\n acc = fmaf(xp[d1 + h1 + iw0], wp[12], acc);\n acc = fmaf(xp[d1 + h1 + iw1], wp[13], acc);\n acc = fmaf(xp[d1 + h1 + iw2], wp[14], acc);\n acc = fmaf(xp[d1 + h2 + iw0], wp[15], acc);\n acc = fmaf(xp[d1 + h2 + iw1], wp[16], acc);\n acc = fmaf(xp[d1 + h2 + iw2], wp[17], acc);\n acc = fmaf(xp[d2 + h0 + iw0], wp[18], acc);\n acc = fmaf(xp[d2 + h0 + iw1], wp[19], acc);\n acc = fmaf(xp[d2 + h0 + iw2], wp[20], acc);\n acc = fmaf(xp[d2 + h1 + iw0], wp[21], acc);\n acc = fmaf(xp[d2 + h1 + iw1], wp[22], acc);\n acc = fmaf(xp[d2 + h1 + iw2], wp[23], acc);\n acc = fmaf(xp[d2 + h2 + iw0], wp[24], acc);\n acc = fmaf(xp[d2 + h2 + iw1], wp[25], acc);\n acc = fmaf(xp[d2 + h2 + iw2], wp[26], acc);\n }\n } else {\n int jd = id + 1, jh = ih + 1, jw = iw + 1;\n #pragma unroll 1\n for (int ci = 0; ci < Cin; ++ci) {\n const float* xp = x + xNbase + ((long)ci * D * H * W);\n const float* wp = w + (((long)ci * Cout + co) * 27);\n #pragma unroll\n for (int kd = 0; kd < 3; ++kd) {\n int xid = jd - kd;\n if ((unsigned)xid >= (unsigned)D) continue;\n #pragma unroll\n for (int kh = 0; kh < 3; ++kh) {\n int xih = jh - kh;\n if ((unsigned)xih >= (unsigned)H) continue;\n #pragma unroll\n for (int kw = 0; kw < 3; ++kw) {\n int xiw = jw - kw;\n if ((unsigned)xiw >= (unsigned)W) continue;\n acc = fmaf(xp[((long)xid * H + xih) * W + xiw], wp[kd*9 + kh*3 + kw], acc);\n }\n }\n }\n }\n }\n\n long out_index = (((((long)n * Cout + co) * outD + (2*id + 1)) * outH + (2*ih + 1)) * outW + (2*iw + 1));\n y[out_index] = acc + (has_bias ? bias[co] : 0.0f);\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 long total,\n int N, int Cin, int Cout,\n int D, int H, int W,\n int K, int stride, int padding, int dilation,\n int outD, int outH, int outW,\n int has_bias) {\n long idx0 = blockIdx.x * (long)blockDim.x + threadIdx.x;\n if (idx0 >= total) return;\n long idx = idx0;\n int ow = (int)(idx % outW); idx /= outW;\n int oh = (int)(idx % outH); idx /= outH;\n int od = (int)(idx % outD); idx /= outD;\n int co = (int)(idx % Cout);\n int n = (int)(idx / Cout);\n float acc = has_bias ? bias[co] : 0.0f;\n const long xNbase = ((long)n * Cin) * D * H * W;\n for (int ci = 0; ci < Cin; ++ci) {\n const float* xp = x + xNbase + (long)ci * D * H * W;\n const float* wp = w + (((long)ci * Cout + co) * K * K * K);\n for (int kd = 0; kd < K; ++kd) {\n int td = od + padding - kd * dilation;\n if (td % stride) continue;\n int xid = td / stride;\n if ((unsigned)xid >= (unsigned)D) continue;\n for (int kh = 0; kh < K; ++kh) {\n int th = oh + padding - kh * dilation;\n if (th % stride) continue;\n int xih = th / stride;\n if ((unsigned)xih >= (unsigned)H) continue;\n for (int kw = 0; kw < K; ++kw) {\n int tw = ow + padding - kw * dilation;\n if (tw % stride) continue;\n int xiw = tw / stride;\n if ((unsigned)xiw >= (unsigned)W) continue;\n acc = fmaf(xp[((long)xid * H + xih) * W + xiw], wp[((kd*K + kh)*K + kw)], acc);\n }\n }\n }\n }\n y[idx0] = acc;\n}\n\ntorch::Tensor deconv3d_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias,\n int64_t stride64, int64_t padding64, int64_t dilation64) {\n TORCH_CHECK(x.is_cuda() && weight.is_cuda(), \"tensors must be CUDA\");\n TORCH_CHECK(x.scalar_type() == at::kFloat && weight.scalar_type() == at::kFloat, \"float32 only\");\n x = x.contiguous();\n weight = weight.contiguous();\n int N = (int)x.size(0), Cin = (int)x.size(1), D = (int)x.size(2), H = (int)x.size(3), W = (int)x.size(4);\n int Cout = (int)weight.size(1), K = (int)weight.size(2);\n int stride = (int)stride64, padding = (int)padding64, dilation = (int)dilation64;\n int outD = (D - 1) * stride - 2 * padding + dilation * (K - 1) + 1;\n int outH = (H - 1) * stride - 2 * padding + dilation * (K - 1) + 1;\n int outW = (W - 1) * stride - 2 * padding + dilation * (K - 1) + 1;\n auto y = at::empty({N, Cout, outD, outH, outW}, x.options());\n bool has_bias = (bias.defined() && bias.numel() > 0);\n if (has_bias) bias = bias.contiguous();\n const float* bptr = has_bias ? bias.data_ptr<float>() : nullptr;\n float* yptr = y.data_ptr<float>();\n auto stream = at::cuda::getCurrentCUDAStream();\n const int threads = 256;\n\n if (stride == 2 && padding == 1 && dilation == 2 && K == 3) {\n long total = y.numel();\n if (has_bias) {\n int blocks_init = (int)std::min<long>((total + threads - 1) / threads, 65535L);\n init_bias_kernel<<<blocks_init, threads, 0, stream>>>(yptr, bptr, total, Cout, outD, outH, outW);\n } else {\n C10_CUDA_CHECK(cudaMemsetAsync(yptr, 0, total * sizeof(float), stream));\n }\n long nz = (long)N * Cout * D * H * W;\n int blocks = (int)((nz + threads - 1) / threads);\n deconv3d_s2p1d2_k3_kernel<<<blocks, threads, 0, stream>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bptr, yptr,\n nz, N, Cin, Cout, D, H, W, outD, outH, outW, has_bias ? 1 : 0);\n } else {\n long total = y.numel();\n int blocks = (int)((total + threads - 1) / threads);\n deconv3d_generic_kernel<<<blocks, threads, 0, stream>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bptr, yptr,\n total, N, Cin, Cout, D, H, W, K, stride, padding, dilation,\n outD, outH, outW, has_bias ? 1 : 0);\n }\n C10_CUDA_KERNEL_LAUNCH_CHECK();\n return y;\n}\n'''\n\n_ext = load_inline(\n name='deconv3d_sparse_s2p1d2_ext',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['deconv3d_forward'],\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: int, out_channels: int, kernel_size: int, stride: int = 1, padding: int = 0, dilation: int = 1, bias: bool = False):\n super(ModelNew, self).__init__()\n self.conv_transpose3d = nn.ConvTranspose3d(\n in_channels, out_channels,\n kernel_size=(kernel_size, kernel_size, kernel_size),\n stride=stride, padding=padding, dilation=dilation, bias=bias\n )\n self.stride = int(stride)\n self.padding = int(padding)\n self.dilation = int(dilation)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n b = self.conv_transpose3d.bias\n if b is None:\n b = torch.empty(0, device=x.device, dtype=x.dtype)\n return _ext.deconv3d_forward(x, self.conv_transpose3d.weight, b, self.stride, self.padding, self.dilation)\n"
}