call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor postprocess_forward(torch::Tensor x, double subtract_value, int pool_k);\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 <math.h>\n\n__device__ __forceinline__ float hswish_sub(float v, float sub) {\n float x = v - sub;\n if (x <= -3.0f) return 0.0f;\n if (x >= 3.0f) return x;\n return x * (x + 3.0f) * 0.16666666666666667f;\n}\n\n__device__ __forceinline__ float mishf_oneexp(float x) {\n // mish(x)=x*tanh(log(1+exp(x))). tanh(log(1+e)) simplifies to e*(e+2)/(e*(e+2)+2),\n // saving a log and tanh while matching fp32 PyTorch well within tolerance.\n if (x > 20.0f) return x;\n float e = expf(x);\n return x * (e * (2.0f + e)) / (2.0f + e * (2.0f + e));\n}\n\n__global__ void post_pool2_3d_kernel(const float* __restrict__ in, float* __restrict__ out,\n int H, int W, int OH, int OW, float sub) {\n int ow = blockIdx.x * blockDim.x + threadIdx.x;\n int oh = blockIdx.y * blockDim.y + threadIdx.y;\n int nc = blockIdx.z;\n if (ow >= OW || oh >= OH) return;\n\n long base = ((long)nc * H + (oh << 1)) * (long)W + (ow << 1);\n float a = hswish_sub(in[base], sub);\n float b = hswish_sub(in[base + 1], sub);\n float c = hswish_sub(in[base + W], sub);\n float d = hswish_sub(in[base + W + 1], sub);\n float m = fmaxf(fmaxf(a, b), fmaxf(c, d));\n\n long oidx = ((long)nc * OH + oh) * (long)OW + ow;\n out[oidx] = mishf_oneexp(m);\n}\n\n__global__ void post_pool2_1d_kernel(const float* __restrict__ in, float* __restrict__ out,\n long total, int H, int W, int OH, int OW, float sub) {\n long idx = (long)blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int ow = idx % OW;\n long t = idx / OW;\n int oh = t % OH;\n long nc = t / OH;\n\n long base = (nc * (long)H + (oh << 1)) * (long)W + (ow << 1);\n float a = hswish_sub(in[base], sub);\n float b = hswish_sub(in[base + 1], sub);\n float c = hswish_sub(in[base + W], sub);\n float d = hswish_sub(in[base + W + 1], sub);\n float m = fmaxf(fmaxf(a, b), fmaxf(c, d));\n out[idx] = mishf_oneexp(m);\n}\n\n__global__ void post_poolk_kernel(const float* __restrict__ in, float* __restrict__ out,\n long total, int H, int W, int OH, int OW, int K, float sub) {\n long idx = (long)blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int ow = idx % OW;\n long t = idx / OW;\n int oh = t % OH;\n long nc = t / OH;\n\n long base0 = (nc * (long)H + oh * K) * (long)W + ow * K;\n float m = -INFINITY;\n for (int r = 0; r < K; ++r) {\n long base = base0 + r * (long)W;\n for (int c = 0; c < K; ++c) {\n m = fmaxf(m, hswish_sub(in[base + c], sub));\n }\n }\n out[idx] = mishf_oneexp(m);\n}\n\ntorch::Tensor postprocess_forward(torch::Tensor x, double subtract_value, int pool_k) {\n TORCH_CHECK(x.is_cuda(), \"x must be CUDA\");\n TORCH_CHECK(x.scalar_type() == at::kFloat, \"x must be float32\");\n TORCH_CHECK(x.is_contiguous(), \"x must be contiguous\");\n\n int64_t N = x.size(0), C = x.size(1), H = x.size(2), W = x.size(3);\n int64_t OH = H / pool_k, OW = W / pool_k;\n auto out = torch::empty({N, C, OH, OW}, x.options());\n long total = N * C * OH * OW;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n\n if (pool_k == 2 && N * C <= 65535) {\n dim3 threads(32, 8, 1);\n dim3 blocks((OW + 31) / 32, (OH + 7) / 8, N * C);\n post_pool2_3d_kernel<<<blocks, threads, 0, stream>>>(\n x.data_ptr<float>(), out.data_ptr<float>(), (int)H, (int)W, (int)OH, (int)OW,\n (float)subtract_value);\n } else if (pool_k == 2) {\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n post_pool2_1d_kernel<<<blocks, threads, 0, stream>>>(\n x.data_ptr<float>(), out.data_ptr<float>(), total, (int)H, (int)W, (int)OH, (int)OW,\n (float)subtract_value);\n } else {\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n post_poolk_kernel<<<blocks, threads, 0, stream>>>(\n x.data_ptr<float>(), out.data_ptr<float>(), total, (int)H, (int)W, (int)OH, (int)OW,\n pool_k, (float)subtract_value);\n }\n return out;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"fused_post_hswish_pool_mish_ext_final\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"postprocess_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, out_channels, kernel_size, subtract_value, pool_kernel_size):\n super(ModelNew, self).__init__()\n self.conv = nn.Conv2d(in_channels, out_channels, kernel_size)\n self.subtract_value = subtract_value\n self.pool_kernel_size = pool_kernel_size if isinstance(pool_kernel_size, int) else pool_kernel_size[0]\n\n def forward(self, x):\n y = F.conv2d(x, self.conv.weight, self.conv.bias)\n return _ext.postprocess_forward(y, float(self.subtract_value), int(self.pool_kernel_size))\n"
}