call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\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\nstatic inline void check_inputs(const torch::Tensor& x, const torch::Tensor& w) {\n TORCH_CHECK(x.is_cuda(), \"x must be CUDA\");\n TORCH_CHECK(w.is_cuda(), \"w must be CUDA\");\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"only fp32 supported\");\n}\n\n__device__ __forceinline__ float sigmoidf_fast(float x) {\n return 1.0f / (1.0f + expf(-x));\n}\n\n// Specialized for the benchmark shape: C=3, K=3, O arbitrary (16 here), contiguous NCDHW.\n__global__ __launch_bounds__(256, 2)\nvoid conv3d_fused_k3_c3_kernel(\n const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ conv_b,\n const float* __restrict__ scale,\n const float* __restrict__ post_b,\n float* __restrict__ y,\n long total,\n int N, int O, int D, int H, int W,\n int Do, int Ho, int Wo)\n{\n long idx = (long)blockIdx.x * blockDim.x + threadIdx.x;\n long stride = (long)blockDim.x * gridDim.x;\n const int HW = H * W;\n const int DHW = D * HW;\n const int out_spatial = Do * Ho * Wo;\n const int out_hw = Ho * Wo;\n\n for (; idx < total; idx += stride) {\n long t = idx;\n int ow = (int)(t % Wo); t /= Wo;\n int oh = (int)(t % Ho); t /= Ho;\n int od = (int)(t % Do); t /= Do;\n int oc = (int)(t % O); t /= O;\n int n = (int)t;\n\n const float* xp = x + ((long)n * 3 * D + od) * HW + oh * W + ow;\n const float* wp = w + (long)oc * 3 * 27;\n float acc = conv_b ? __ldg(conv_b + oc) : 0.0f;\n\n #pragma unroll\n for (int c = 0; c < 3; ++c) {\n const float* xpc = xp + (long)c * DHW;\n const float* wpc = wp + c * 27;\n // kd = 0\n acc = fmaf(__ldg(xpc + 0*HW + 0*W + 0), __ldg(wpc + 0), acc);\n acc = fmaf(__ldg(xpc + 0*HW + 0*W + 1), __ldg(wpc + 1), acc);\n acc = fmaf(__ldg(xpc + 0*HW + 0*W + 2), __ldg(wpc + 2), acc);\n acc = fmaf(__ldg(xpc + 0*HW + 1*W + 0), __ldg(wpc + 3), acc);\n acc = fmaf(__ldg(xpc + 0*HW + 1*W + 1), __ldg(wpc + 4), acc);\n acc = fmaf(__ldg(xpc + 0*HW + 1*W + 2), __ldg(wpc + 5), acc);\n acc = fmaf(__ldg(xpc + 0*HW + 2*W + 0), __ldg(wpc + 6), acc);\n acc = fmaf(__ldg(xpc + 0*HW + 2*W + 1), __ldg(wpc + 7), acc);\n acc = fmaf(__ldg(xpc + 0*HW + 2*W + 2), __ldg(wpc + 8), acc);\n // kd = 1\n acc = fmaf(__ldg(xpc + 1*HW + 0*W + 0), __ldg(wpc + 9), acc);\n acc = fmaf(__ldg(xpc + 1*HW + 0*W + 1), __ldg(wpc + 10), acc);\n acc = fmaf(__ldg(xpc + 1*HW + 0*W + 2), __ldg(wpc + 11), acc);\n acc = fmaf(__ldg(xpc + 1*HW + 1*W + 0), __ldg(wpc + 12), acc);\n acc = fmaf(__ldg(xpc + 1*HW + 1*W + 1), __ldg(wpc + 13), acc);\n acc = fmaf(__ldg(xpc + 1*HW + 1*W + 2), __ldg(wpc + 14), acc);\n acc = fmaf(__ldg(xpc + 1*HW + 2*W + 0), __ldg(wpc + 15), acc);\n acc = fmaf(__ldg(xpc + 1*HW + 2*W + 1), __ldg(wpc + 16), acc);\n acc = fmaf(__ldg(xpc + 1*HW + 2*W + 2), __ldg(wpc + 17), acc);\n // kd = 2\n acc = fmaf(__ldg(xpc + 2*HW + 0*W + 0), __ldg(wpc + 18), acc);\n acc = fmaf(__ldg(xpc + 2*HW + 0*W + 1), __ldg(wpc + 19), acc);\n acc = fmaf(__ldg(xpc + 2*HW + 0*W + 2), __ldg(wpc + 20), acc);\n acc = fmaf(__ldg(xpc + 2*HW + 1*W + 0), __ldg(wpc + 21), acc);\n acc = fmaf(__ldg(xpc + 2*HW + 1*W + 1), __ldg(wpc + 22), acc);\n acc = fmaf(__ldg(xpc + 2*HW + 1*W + 2), __ldg(wpc + 23), acc);\n acc = fmaf(__ldg(xpc + 2*HW + 2*W + 0), __ldg(wpc + 24), acc);\n acc = fmaf(__ldg(xpc + 2*HW + 2*W + 1), __ldg(wpc + 25), acc);\n acc = fmaf(__ldg(xpc + 2*HW + 2*W + 2), __ldg(wpc + 26), acc);\n }\n float v = acc * __ldg(scale + oc);\n v = tanhf(v);\n v *= __ldg(post_b + oc);\n y[idx] = sigmoidf_fast(v);\n }\n}\n\n// Generic direct fused kernel for less common constructor variants.\n__global__ void conv3d_fused_generic_kernel(\n const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ conv_b,\n const float* __restrict__ scale,\n const float* __restrict__ post_b,\n float* __restrict__ y,\n long total,\n int N, int C, int O, int D, int H, int W, int Kd, int Kh, int Kw,\n int Do, int Ho, int Wo)\n{\n long idx = (long)blockIdx.x * blockDim.x + threadIdx.x;\n long stride = (long)blockDim.x * gridDim.x;\n const int HW = H * W;\n const int DHW = D * HW;\n const int out_hw = Ho * Wo;\n const int KHW = Kh * Kw;\n const int Ktot = Kd * KHW;\n for (; idx < total; idx += stride) {\n long t = idx;\n int ow = (int)(t % Wo); t /= Wo;\n int oh = (int)(t % Ho); t /= Ho;\n int od = (int)(t % Do); t /= Do;\n int oc = (int)(t % O); t /= O;\n int n = (int)t;\n float acc = conv_b ? __ldg(conv_b + oc) : 0.0f;\n for (int c=0; c<C; ++c) {\n for (int kd=0; kd<Kd; ++kd) {\n for (int kh=0; kh<Kh; ++kh) {\n const float* xp = x + ((long)n*C + c)*DHW + (od+kd)*HW + (oh+kh)*W + ow;\n const float* wp = w + ((long)oc*C + c)*Ktot + kd*KHW + kh*Kw;\n for (int kw=0; kw<Kw; ++kw) acc = fmaf(__ldg(xp+kw), __ldg(wp+kw), acc);\n }\n }\n }\n float v = acc * __ldg(scale + oc);\n v = tanhf(v);\n v *= __ldg(post_b + oc);\n y[idx] = 1.0f / (1.0f + expf(-v));\n }\n}\n\ntorch::Tensor fused_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor conv_bias, torch::Tensor scale, torch::Tensor post_bias) {\n check_inputs(x, weight);\n TORCH_CHECK(x.dim() == 5 && weight.dim() == 5, \"expected 5D tensors\");\n auto xc = x.contiguous();\n auto wc = weight.contiguous();\n auto sc = scale.contiguous();\n auto pc = post_bias.contiguous();\n torch::Tensor bc = conv_bias.defined() ? conv_bias.contiguous() : conv_bias;\n\n int N = (int)xc.size(0), C = (int)xc.size(1), D = (int)xc.size(2), H = (int)xc.size(3), W = (int)xc.size(4);\n int O = (int)wc.size(0), Kd = (int)wc.size(2), Kh = (int)wc.size(3), Kw = (int)wc.size(4);\n int Do = D - Kd + 1, Ho = H - Kh + 1, Wo = W - Kw + 1;\n auto y = torch::empty({N, O, Do, Ho, Wo}, xc.options());\n long total = y.numel();\n if (total == 0) return y;\n int threads = 256;\n int blocks = (int)((total + threads - 1) / threads);\n int maxBlocks = 65535;\n if (blocks > maxBlocks) blocks = maxBlocks;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n const float* bp = bc.defined() ? bc.data_ptr<float>() : nullptr;\n if (C == 3 && Kd == 3 && Kh == 3 && Kw == 3) {\n conv3d_fused_k3_c3_kernel<<<blocks, threads, 0, stream>>>(\n xc.data_ptr<float>(), wc.data_ptr<float>(), bp, sc.data_ptr<float>(), pc.data_ptr<float>(), y.data_ptr<float>(),\n total, N, O, D, H, W, Do, Ho, Wo);\n } else {\n conv3d_fused_generic_kernel<<<blocks, threads, 0, stream>>>(\n xc.data_ptr<float>(), wc.data_ptr<float>(), bp, sc.data_ptr<float>(), pc.data_ptr<float>(), y.data_ptr<float>(),\n total, N, C, O, D, H, W, Kd, Kh, Kw, Do, Ho, Wo);\n }\n return y;\n}\n'''\n\n_ext = load_inline(\n name='fused_conv3d_tanh_sigmoid_ext_v1',\n cpp_sources='',\n cuda_sources=_cuda_src,\n functions=['fused_forward'],\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n extra_cflags=['-O3'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_channels, out_channels, kernel_size, scaling_factor, bias_shape):\n super(ModelNew, self).__init__()\n self.conv = nn.Conv3d(in_channels, out_channels, kernel_size)\n self.scaling_factor = nn.Parameter(torch.randn(bias_shape))\n self.bias = nn.Parameter(torch.randn(bias_shape))\n\n def forward(self, x):\n return _ext.fused_forward(x, self.conv.weight, self.conv.bias, self.scaling_factor, self.bias)\n"
}