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>\n\ntorch::Tensor relu_maxpool2d_cuda(torch::Tensor x);\ntorch::Tensor maxpool2d_cuda(torch::Tensor x);\ntorch::Tensor spatial_avg_cuda(torch::Tensor x);\n\ntorch::Tensor relu_maxpool2d_forward(torch::Tensor x) {\n return relu_maxpool2d_cuda(x);\n}\n\ntorch::Tensor maxpool2d_forward(torch::Tensor x) {\n return maxpool2d_cuda(x);\n}\n\ntorch::Tensor spatial_avg_forward(torch::Tensor x) {\n return spatial_avg_cuda(x);\n}\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAGuard.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cfloat>\n\n__global__ void maxpool3s2p1_kernel(const float* __restrict__ x, float* __restrict__ y,\n int N, int C, int H, int W, int OH, int OW,\n int64_t xs0, int64_t xs1, int64_t xs2, int64_t xs3,\n int64_t ys0, int64_t ys1, int64_t ys2, int64_t ys3,\n bool do_relu) {\n // Iterate in NHWC logical order. This gives coalesced accesses/stores for\n // channels-last tensors while still working for arbitrary strided inputs.\n int64_t idx = (int64_t)blockIdx.x * blockDim.x + threadIdx.x;\n int64_t total = (int64_t)N * OH * OW * C;\n for (; idx < total; idx += (int64_t)blockDim.x * gridDim.x) {\n int t = (int)idx;\n int c = t % C; t /= C;\n int ow = t % OW; t /= OW;\n int oh = t % OH; t /= OH;\n int n = t;\n\n int hs = oh * 2 - 1;\n int ws = ow * 2 - 1;\n int he = hs + 3;\n int we = ws + 3;\n if (hs < 0) hs = 0;\n if (ws < 0) ws = 0;\n if (he > H) he = H;\n if (we > W) we = W;\n\n float m = -FLT_MAX;\n for (int h = hs; h < he; ++h) {\n for (int w = ws; w < we; ++w) {\n float v = x[(int64_t)n*xs0 + (int64_t)c*xs1 + (int64_t)h*xs2 + (int64_t)w*xs3];\n if (do_relu && v < 0.0f) v = 0.0f;\n m = fmaxf(m, v);\n }\n }\n y[(int64_t)n*ys0 + (int64_t)c*ys1 + (int64_t)oh*ys2 + (int64_t)ow*ys3] = m;\n }\n}\n\n__global__ void spatial_avg_kernel(const float* __restrict__ x, float* __restrict__ y,\n int N, int C, int H, int W,\n int64_t xs0, int64_t xs1, int64_t xs2, int64_t xs3) {\n int bc = blockIdx.x;\n int c = bc % C;\n int n = bc / C;\n float sum = 0.0f;\n int HW = H * W;\n for (int i = threadIdx.x; i < HW; i += blockDim.x) {\n int h = i / W;\n int w = i - h * W;\n sum += x[(int64_t)n*xs0 + (int64_t)c*xs1 + (int64_t)h*xs2 + (int64_t)w*xs3];\n }\n __shared__ float smem[64];\n smem[threadIdx.x] = sum;\n __syncthreads();\n for (int s = 32; s > 0; s >>= 1) {\n if (threadIdx.x < s) smem[threadIdx.x] += smem[threadIdx.x + s];\n __syncthreads();\n }\n if (threadIdx.x == 0) {\n y[(int64_t)n*C + c] = smem[0] / (float)HW;\n }\n}\n\nstatic torch::Tensor pool_common(torch::Tensor x, bool relu) {\n TORCH_CHECK(x.is_cuda(), \"x must be CUDA\");\n TORCH_CHECK(x.scalar_type() == at::kFloat, \"only float32 is supported\");\n c10::cuda::CUDAGuard device_guard(x.device());\n int N = (int)x.size(0);\n int C = (int)x.size(1);\n int H = (int)x.size(2);\n int W = (int)x.size(3);\n int OH = (H + 1) / 2;\n int OW = (W + 1) / 2;\n auto y = at::empty({N, C, OH, OW}, x.options().memory_format(c10::MemoryFormat::ChannelsLast));\n int64_t total = (int64_t)N * OH * OW * C;\n int threads = 256;\n int blocks = (int)((total + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n maxpool3s2p1_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(\n x.data_ptr<float>(), y.data_ptr<float>(), N, C, H, W, OH, OW,\n x.stride(0), x.stride(1), x.stride(2), x.stride(3),\n y.stride(0), y.stride(1), y.stride(2), y.stride(3), relu);\n C10_CUDA_KERNEL_LAUNCH_CHECK();\n return y;\n}\n\ntorch::Tensor relu_maxpool2d_cuda(torch::Tensor x) {\n return pool_common(x, true);\n}\n\ntorch::Tensor maxpool2d_cuda(torch::Tensor x) {\n return pool_common(x, false);\n}\n\ntorch::Tensor spatial_avg_cuda(torch::Tensor x) {\n TORCH_CHECK(x.is_cuda(), \"x must be CUDA\");\n TORCH_CHECK(x.scalar_type() == at::kFloat, \"only float32 is supported\");\n c10::cuda::CUDAGuard device_guard(x.device());\n int N = (int)x.size(0);\n int C = (int)x.size(1);\n int H = (int)x.size(2);\n int W = (int)x.size(3);\n auto y = at::empty({N, C}, x.options());\n spatial_avg_kernel<<<N * C, 64, 0, at::cuda::getCurrentCUDAStream()>>>(\n x.data_ptr<float>(), y.data_ptr<float>(), N, C, H, W,\n x.stride(0), x.stride(1), x.stride(2), x.stride(3));\n C10_CUDA_KERNEL_LAUNCH_CHECK();\n return y;\n}\n'''\n\n_ext = load_inline(\n name=\"googlenet_custom_pool_ops_v1\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"relu_maxpool2d_forward\", \"maxpool2d_forward\", \"spatial_avg_forward\"],\n extra_cflags=[\"-O3\"],\n extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"],\n verbose=False,\n)\n\n\nclass InceptionModule(nn.Module):\n def __init__(self, in_channels, out_1x1, reduce_3x3, out_3x3, reduce_5x5, out_5x5, pool_proj):\n super(InceptionModule, self).__init__()\n self.branch1x1 = nn.Conv2d(in_channels, out_1x1, kernel_size=1)\n self.branch3x3 = nn.Sequential(\n nn.Conv2d(in_channels, reduce_3x3, kernel_size=1),\n nn.Conv2d(reduce_3x3, out_3x3, kernel_size=3, padding=1),\n )\n self.branch5x5 = nn.Sequential(\n nn.Conv2d(in_channels, reduce_5x5, kernel_size=1),\n nn.Conv2d(reduce_5x5, out_5x5, kernel_size=5, padding=2),\n )\n self.branch_pool = nn.Sequential(\n nn.MaxPool2d(kernel_size=3, stride=1, padding=1),\n nn.Conv2d(in_channels, pool_proj, kernel_size=1),\n )\n\n def forward(self, x):\n b1 = self.branch1x1(x)\n b3 = self.branch3x3(x)\n b5 = self.branch5x5(x)\n # The reference pool branch is maxpool stride=1, not stride=2; keep it as\n # PyTorch/cudnn for exact shape and optimized behavior.\n bp = self.branch_pool(x)\n return torch.cat((b1, b3, b5, bp), 1)\n\n\nclass ModelNew(nn.Module):\n def __init__(self, num_classes=1000):\n super(ModelNew, self).__init__()\n self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3)\n self.maxpool1 = nn.MaxPool2d(3, stride=2, padding=1)\n self.conv2 = nn.Conv2d(64, 64, kernel_size=1)\n self.conv3 = nn.Conv2d(64, 192, kernel_size=3, padding=1)\n self.maxpool2 = nn.MaxPool2d(3, stride=2, padding=1)\n\n self.inception3a = InceptionModule(192, 64, 96, 128, 16, 32, 32)\n self.inception3b = InceptionModule(256, 128, 128, 192, 32, 96, 64)\n self.maxpool3 = nn.MaxPool2d(3, stride=2, padding=1)\n\n self.inception4a = InceptionModule(480, 192, 96, 208, 16, 48, 64)\n self.inception4b = InceptionModule(512, 160, 112, 224, 24, 64, 64)\n self.inception4c = InceptionModule(512, 128, 128, 256, 24, 64, 64)\n self.inception4d = InceptionModule(512, 112, 144, 288, 32, 64, 64)\n self.inception4e = InceptionModule(528, 256, 160, 320, 32, 128, 128)\n self.maxpool4 = nn.MaxPool2d(3, stride=2, padding=1)\n\n self.inception5a = InceptionModule(832, 256, 160, 320, 32, 128, 128)\n self.inception5b = InceptionModule(832, 384, 192, 384, 48, 128, 128)\n\n self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n self.dropout = nn.Dropout(0.0)\n self.fc = nn.Linear(1024, num_classes)\n # NHWC improves cuDNN convolution throughput for this network. State-dict\n # loading copies values into these parameters without changing names.\n self.to(memory_format=torch.channels_last)\n\n def forward(self, x):\n if x.is_cuda and x.dtype is torch.float32:\n x = x.contiguous(memory_format=torch.channels_last)\n x = _ext.relu_maxpool2d_forward(self.conv1(x))\n x = F.relu(self.conv2(x))\n x = _ext.relu_maxpool2d_forward(self.conv3(x))\n\n x = self.inception3a(x)\n x = self.inception3b(x)\n x = _ext.maxpool2d_forward(x)\n\n x = self.inception4a(x)\n x = self.inception4b(x)\n x = self.inception4c(x)\n x = self.inception4d(x)\n x = self.inception4e(x)\n x = _ext.maxpool2d_forward(x)\n\n x = self.inception5a(x)\n x = self.inception5b(x)\n\n x = _ext.spatial_avg_forward(x)\n return self.fc(x)\n else:\n x = self.maxpool1(F.relu(self.conv1(x)))\n x = F.relu(self.conv2(x))\n x = self.maxpool2(F.relu(self.conv3(x)))\n x = self.inception3a(x)\n x = self.inception3b(x)\n x = self.maxpool3(x)\n x = self.inception4a(x)\n x = self.inception4b(x)\n x = self.inception4c(x)\n x = self.inception4d(x)\n x = self.inception4e(x)\n x = self.maxpool4(x)\n x = self.inception5a(x)\n x = self.inception5b(x)\n x = self.avgpool(x)\n x = torch.flatten(x, 1)\n x = self.dropout(x)\n x = self.fc(x)\n return x\n"
}