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 dwconv_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias,\n int64_t stride_h, int64_t stride_w,\n int64_t padding_h, int64_t padding_w,\n int64_t dilation_h, int64_t dilation_w);\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\n__global__ __launch_bounds__(256, 2)\nvoid dwconv3x7_w256_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ b,\n float* __restrict__ y,\n int N, int C, int H, int Hout, int Wout,\n bool has_bias) {\n // One block computes up to four adjacent output rows for one (N,C) plane,\n // and the full output width. For the benchmark W=256, Wout=250.\n __shared__ float tile[6][256];\n\n const int c = blockIdx.x;\n const int n = blockIdx.y;\n const int oh0 = blockIdx.z * 4;\n const int tid = threadIdx.x;\n\n const float* xnc = x + ((n * C + c) * H) * 256;\n\n #pragma unroll\n for (int r = 0; r < 6; ++r) {\n int ih = oh0 + r;\n tile[r][tid] = (ih < H) ? xnc[ih * 256 + tid] : 0.0f;\n }\n __syncthreads();\n\n if (tid >= Wout) return;\n\n const float* wc = w + c * 21;\n float acc0 = has_bias ? b[c] : 0.0f;\n float acc1 = acc0;\n float acc2 = acc0;\n float acc3 = acc0;\n\n #pragma unroll\n for (int kh = 0; kh < 3; ++kh) {\n #pragma unroll\n for (int kw = 0; kw < 7; ++kw) {\n float ww = __ldg(wc + kh * 7 + kw);\n int col = tid + kw;\n acc0 = fmaf(tile[kh + 0][col], ww, acc0);\n acc1 = fmaf(tile[kh + 1][col], ww, acc1);\n acc2 = fmaf(tile[kh + 2][col], ww, acc2);\n acc3 = fmaf(tile[kh + 3][col], ww, acc3);\n }\n }\n\n float* ync = y + ((n * C + c) * Hout + oh0) * Wout;\n ync[tid] = acc0;\n if (oh0 + 1 < Hout) ync[Wout + tid] = acc1;\n if (oh0 + 2 < Hout) ync[2 * Wout + tid] = acc2;\n if (oh0 + 3 < Hout) ync[3 * Wout + tid] = acc3;\n}\n\n__global__ __launch_bounds__(256, 2)\nvoid dwconv_generic_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ b,\n float* __restrict__ y,\n long total,\n int N, int C, int H, int W,\n int Kh, int Kw, int Hout, int Wout,\n int sh, int sw, int ph, int pw, int dh, int dw,\n bool has_bias) {\n long idx = (long)blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n\n int ow = (int)(idx % Wout);\n long t = idx / Wout;\n int oh = (int)(t % Hout);\n t /= Hout;\n int c = (int)(t % C);\n int n = (int)(t / C);\n\n float acc = has_bias ? b[c] : 0.0f;\n const float* xnc = x + ((n * C + c) * H) * W;\n const float* wc = w + c * Kh * Kw;\n\n for (int kh = 0; kh < Kh; ++kh) {\n int ih = oh * sh - ph + kh * dh;\n if ((unsigned)ih >= (unsigned)H) continue;\n for (int kw = 0; kw < Kw; ++kw) {\n int iw = ow * sw - pw + kw * dw;\n if ((unsigned)iw < (unsigned)W) {\n acc = fmaf(xnc[ih * W + iw], wc[kh * Kw + kw], acc);\n }\n }\n }\n y[idx] = acc;\n}\n\ntorch::Tensor dwconv_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias,\n int64_t stride_h, int64_t stride_w,\n int64_t padding_h, int64_t padding_w,\n int64_t dilation_h, int64_t dilation_w) {\n const int N = (int)x.size(0);\n const int C = (int)x.size(1);\n const int H = (int)x.size(2);\n const int W = (int)x.size(3);\n const int Kh = (int)weight.size(2);\n const int Kw = (int)weight.size(3);\n const int Hout = (H + 2 * (int)padding_h - (int)dilation_h * (Kh - 1) - 1) / (int)stride_h + 1;\n const int Wout = (W + 2 * (int)padding_w - (int)dilation_w * (Kw - 1) - 1) / (int)stride_w + 1;\n\n auto y = torch::empty({N, C, Hout, Wout}, x.options());\n const bool has_bias = (bias.numel() != 0);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n\n if (Kh == 3 && Kw == 7 && stride_h == 1 && stride_w == 1 &&\n padding_h == 0 && padding_w == 0 && dilation_h == 1 && dilation_w == 1 &&\n W == 256 && Wout <= 250 && x.scalar_type() == at::kFloat) {\n dim3 block(256);\n dim3 grid(C, N, (Hout + 3) / 4);\n dwconv3x7_w256_kernel<<<grid, block, 0, stream>>>(\n x.data_ptr<float>(), weight.data_ptr<float>(),\n has_bias ? bias.data_ptr<float>() : nullptr, y.data_ptr<float>(),\n N, C, H, Hout, Wout, has_bias);\n } else {\n long total = (long)N * C * Hout * Wout;\n dim3 block(256);\n dim3 grid((unsigned int)((total + block.x - 1) / block.x));\n dwconv_generic_kernel<<<grid, block, 0, stream>>>(\n x.data_ptr<float>(), weight.data_ptr<float>(),\n has_bias ? bias.data_ptr<float>() : nullptr, y.data_ptr<float>(), total,\n N, C, H, W, Kh, Kw, Hout, Wout,\n (int)stride_h, (int)stride_w, (int)padding_h, (int)padding_w,\n (int)dilation_h, (int)dilation_w, has_bias);\n }\n return y;\n}\n\"\"\"\n\n_dwconv_ext = load_inline(\n name=\"dwconv_depthwise_3x7_shared_ext\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"dwconv_forward\"],\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: int, out_channels: int, kernel_size_h: int, kernel_size_w: int,\n stride_h: int = 1, stride_w: int = 1, padding_h: int = 0, padding_w: int = 0,\n dilation_h: int = 1, dilation_w: int = 1, groups: int = 1, bias: bool = False):\n super(ModelNew, self).__init__()\n # Match the reference exactly: out_channels/groups arguments are ignored there.\n self.conv2d = nn.Conv2d(in_channels, in_channels, (kernel_size_h, kernel_size_w),\n stride=(stride_h, stride_w), padding=(padding_h, padding_w),\n dilation=(dilation_h, dilation_w), groups=in_channels, bias=bias)\n self.stride_h = stride_h\n self.stride_w = stride_w\n self.padding_h = padding_h\n self.padding_w = padding_w\n self.dilation_h = dilation_h\n self.dilation_w = dilation_w\n self.register_buffer(\"_empty_bias\", torch.empty(0), persistent=False)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n bias = self.conv2d.bias if self.conv2d.bias is not None else self._empty_bias\n return _dwconv_ext.dwconv_forward(x.contiguous(), self.conv2d.weight.contiguous(), bias,\n self.stride_h, self.stride_w,\n self.padding_h, self.padding_w,\n self.dilation_h, self.dilation_w)\n"
}