correct
7_GoogleNetInceptionV1.py
started
2026-05-04T16:59:55Z
timingkernelbench.timing
kernel mean / median / std
6.52 / — / 33.70 μs
ref mean / median / std
3.36 / — / 0.39 μs
numerical precisioneval_kernel_against_ref
gpu memoryextended_metrics.measure_memory
kernel launches / fusiontorch.profiler
fusion ratio (ref / kernel)
1.04x
energyNVML (pynvml)
ratio (ref / kernel)
2.00x
SOL (speed-of-light)heuristic_from_speedup
roofline / occupancyheuristic
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn
import torch.nn.functional as F
class InceptionModule(nn.Module):
def __init__(self, in_channels, out_1x1, reduce_3x3, out_3x3, reduce_5x5, out_5x5, pool_proj):
"""
:param in_channels: Number of input channels
:param out_1x1: Number of output channels for the 1x1 convolution
:param reduce_3x3: Number of output channels for the 1x1 reduction before 3x3 convolution
:param out_3x3: Number of output channels for the 3x3 convolution
:param reduce_5x5: Number of output channels for the 1x1 reduction before 5x5 convolution
:param out_5x5: Number of output channels for the 5x5 convolution
:param pool_proj: Number of output channels for the pooling projection
"""
super(InceptionModule, self).__init__()
# 1x1 convolution branch
self.branch1x1 = nn.Conv2d(in_channels, out_1x1, kernel_size=1)
# 3x3 convolution branch
self.branch3x3 = nn.Sequential(
nn.Conv2d(in_channels, reduce_3x3, kernel_size=1),
nn.Conv2d(reduce_3x3, out_3x3, kernel_size=3, padding=1)
)
# 5x5 convolution branch
self.branch5x5 = nn.Sequential(
nn.Conv2d(in_channels, reduce_5x5, kernel_size=1),
nn.Conv2d(reduce_5x5, out_5x5, kernel_size=5, padding=2)
)
# Max pooling branch
self.branch_pool = nn.Sequential(
nn.MaxPool2d(kernel_size=3, stride=1, padding=1),
nn.Conv2d(in_channels, pool_proj, kernel_size=1)
)
def forward(self, x):
"""
:param x: Input tensor, shape (batch_size, in_channels, height, width)
:return: Output tensor, shape (batch_size, out_channels, height, width)
"""
branch1x1 = self.branch1x1(x)
branch3x3 = self.branch3x3(x)
branch5x5 = self.branch5x5(x)
branch_pool = self.branch_pool(x)
outputs = [branch1x1, branch3x3, branch5x5, branch_pool]
return torch.cat(outputs, 1)
class Model(nn.Module):
def __init__(self, num_classes=1000):
"""
:param num_classes: Number of output classes
"""
super(Model, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3)
self.maxpool1 = nn.MaxPool2d(3, stride=2, padding=1)
self.conv2 = nn.Conv2d(64, 64, kernel_size=1)
self.conv3 = nn.Conv2d(64, 192, kernel_size=3, padding=1)
self.maxpool2 = nn.MaxPool2d(3, stride=2, padding=1)
self.inception3a = InceptionModule(192, 64, 96, 128, 16, 32, 32)
self.inception3b = InceptionModule(256, 128, 128, 192, 32, 96, 64)
self.maxpool3 = nn.MaxPool2d(3, stride=2, padding=1)
self.inception4a = InceptionModule(480, 192, 96, 208, 16, 48, 64)
self.inception4b = InceptionModule(512, 160, 112, 224, 24, 64, 64)
self.inception4c = InceptionModule(512, 128, 128, 256, 24, 64, 64)
self.inception4d = InceptionModule(512, 112, 144, 288, 32, 64, 64)
self.inception4e = InceptionModule(528, 256, 160, 320, 32, 128, 128)
self.maxpool4 = nn.MaxPool2d(3, stride=2, padding=1)
self.inception5a = InceptionModule(832, 256, 160, 320, 32, 128, 128)
self.inception5b = InceptionModule(832, 384, 192, 384, 48, 128, 128)
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
self.dropout = nn.Dropout(0.0)
self.fc = nn.Linear(1024, num_classes)
def forward(self, x):
"""
:param x: Input tensor, shape (batch_size, 3, height, width)
:return: Output tensor, shape (batch_size, num_classes)
"""
x = self.maxpool1(F.relu(self.conv1(x)))
x = F.relu(self.conv2(x))
x = self.maxpool2(F.relu(self.conv3(x)))
x = self.inception3a(x)
x = self.inception3b(x)
x = self.maxpool3(x)
x = self.inception4a(x)
x = self.inception4b(x)
x = self.inception4c(x)
x = self.inception4d(x)
x = self.inception4e(x)
x = self.maxpool4(x)
x = self.inception5a(x)
x = self.inception5b(x)
x = self.avgpool(x)
x = torch.flatten(x, 1)
x = self.dropout(x)
x = self.fc(x)
return x
# Test code
batch_size = 10
input_channels = 3
height = 224
width = 224
num_classes = 1000
def get_inputs():
return [torch.rand(batch_size, input_channels, height, width)]
def get_init_inputs():
return [num_classes]turn 012.8s turn · 12.8s LLM · 0.0s tools
reasoning
**Considering model optimization**
I need to think about crafting a full model similar to GoogLeNet. It might be a good idea to use the same weights, perhaps by copying the state in the ModelNew constructor. I wonder if we need to define the same parameter names. If I subclass nn.Module, I could create identical layers to match the state_dict. Additionally, should I optimize using custom kernels or leverage PyTorch’s capabilities for convolution? I'll also need to think about the overall architecture and its efficiency.
**Exploring fusions and layers**
I need to consider how there’s no ReLU after inception layers, meaning the network operates post-max pooling. Max pooling adds nonlinearity, and I wonder if I can fuse 1x1 and 3x3 convolutions into a single 3x3 conv with combined weights, perhaps even for 5x5. I also think about using PyTorch to lazily fuse weights during each forward call to reduce conv calls, but the costs of fused direct convolutions seem significant. Maybe I should explore using custom kernels or specific configurations for better performance.
**Analyzing convolution outputs**
I'm considering the convolution output sizes starting with conv1, which shapes to B10 64 112x112, then goes through ReLU and max pooling to reduce to 56. I wonder if fusing operations could save memory and reduce the overhead from PyTorch's max pooling. In my evaluation, it seems that implementing custom maxpool kernels might expedite the process. However, I recognize that the overall convolution operations could still be dominating the performance, so I need to assess if the custom maxpool would be enough.
call → get_gpu_specs
callget_gpu_specs
{}
result ← get_gpu_specs (ok)
okget_gpu_specs
GPU specs for NVIDIA H100 80GB HBM3:
total memory (runtime): 79.1 GB
spec entry: H100
GPU Architecture: Hopper
GPU Memory: 80GB
Memory Bandwidth: 3.35 TB/s
FP64 TFLOPS: 34
FP64 Tensor Core TFLOPS: 67
FP32 TFLOPS: 67
TF32 Tensor Core TFLOPS: 989 with sparsity
BFLOAT16 Tensore Core TFLOPS: 1979 with sparsity
FP16 Tensor Core TFLOPS: 1979 with sparsity
FP8 Tensor Core TFLOPS: 3958 with sparsity
INT8 Tensor Core TOPS: 3958 with sparsity
Register File Size: 64K 32-bit registers per SM
Maximum number of registers per thread: 255
Maximum number of thread blocks per SM: 32
Shared memory capacity per SM: 228 KB
Maximum shared memory per thread block: 227 KB
turn 1 · 1 tool call(s) · 27.8s turn · 27.8s LLM · 6,289 chars (click to expand)
turn 127.8s turn · 27.8s LLM · 0.0s tools
call → compile_kernel
callcompile_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 = r'''\n#include <torch/extension.h>\ntorch::Tensor maxpool3x3_forward(torch::Tensor x, int stride, bool relu);\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <float.h>\n\n__global__ void maxpool3x3_kernel(const float* __restrict__ x, float* __restrict__ y,\n int total, int N, int C, int H, int W, int OH, int OW,\n int stride, bool relu) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int ow = idx % OW;\n int t = idx / OW;\n int oh = t % OH;\n t /= OH;\n int c = t % C;\n int n = t / C;\n int ih0 = oh * stride - 1;\n int iw0 = ow * stride - 1;\n const float* base = x + ((n * C + c) * H) * W;\n float m = relu ? 0.0f : -FLT_MAX;\n #pragma unroll\n for (int kh=0; kh<3; ++kh) {\n int ih = ih0 + kh;\n if ((unsigned)ih < (unsigned)H) {\n #pragma unroll\n for (int kw=0; kw<3; ++kw) {\n int iw = iw0 + kw;\n if ((unsigned)iw < (unsigned)W) {\n float v = base[ih * W + iw];\n if (relu && v < 0.0f) v = 0.0f;\n m = fmaxf(m, v);\n }\n }\n }\n }\n y[idx] = m;\n}\n\ntorch::Tensor maxpool3x3_forward(torch::Tensor x, int stride, bool relu) {\n TORCH_CHECK(x.is_cuda(), \"x must be CUDA\");\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"float32 only\");\n x = x.contiguous();\n int N = x.size(0), C = x.size(1), H = x.size(2), W = x.size(3);\n int OH = (H + 2 - 3) / stride + 1;\n int OW = (W + 2 - 3) / stride + 1;\n auto y = torch::empty({N, C, OH, OW}, x.options());\n int total = N*C*OH*OW;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n maxpool3x3_kernel<<<blocks, threads>>>(x.data_ptr<float>(), y.data_ptr<float>(), total, N, C, H, W, OH, OW, stride, relu);\n return y;\n}\n'''\n\n_ext = load_inline(name='googlenet_pool_ext_v1', cpp_sources=_cpp, cuda_sources=_cuda,\n functions=['maxpool3x3_forward'], extra_cuda_cflags=['-O3'], verbose=False)\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 def forward(self, x):\n branch1x1 = self.branch1x1(x)\n branch3x3 = self.branch3x3(x)\n branch5x5 = self.branch5x5(x)\n p = _ext.maxpool3x3_forward(x, 1, False)\n branch_pool = self.branch_pool[1](p)\n return torch.cat([branch1x1, branch3x3, branch5x5, branch_pool], 1)\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 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 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 self.inception5a = InceptionModule(832, 256, 160, 320, 32, 128, 128)\n self.inception5b = InceptionModule(832, 384, 192, 384, 48, 128, 128)\n self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n self.dropout = nn.Dropout(0.0)\n self.fc = nn.Linear(1024, num_classes)\n def forward(self, x):\n x = _ext.maxpool3x3_forward(self.conv1(x), 2, True)\n x = F.relu(self.conv2(x))\n x = _ext.maxpool3x3_forward(self.conv3(x), 2, True)\n x = self.inception3a(x)\n x = self.inception3b(x)\n x = _ext.maxpool3x3_forward(x, 2, False)\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.maxpool3x3_forward(x, 2, False)\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"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 2 · 1 tool call(s) · 11.2s turn · 11.2s LLM · 6,391 chars (click to expand)
turn 211.2s turn · 11.2s LLM · 0.0s tools
call → run_correctness
callrun_correctness
{
"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 = r'''\n#include <torch/extension.h>\ntorch::Tensor maxpool3x3_forward(torch::Tensor x, int stride, bool relu);\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <float.h>\n\n__global__ void maxpool3x3_kernel(const float* __restrict__ x, float* __restrict__ y,\n int total, int N, int C, int H, int W, int OH, int OW,\n int stride, bool relu) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int ow = idx % OW;\n int t = idx / OW;\n int oh = t % OH;\n t /= OH;\n int c = t % C;\n int n = t / C;\n int ih0 = oh * stride - 1;\n int iw0 = ow * stride - 1;\n const float* base = x + ((n * C + c) * H) * W;\n float m = relu ? 0.0f : -FLT_MAX;\n #pragma unroll\n for (int kh=0; kh<3; ++kh) {\n int ih = ih0 + kh;\n if ((unsigned)ih < (unsigned)H) {\n #pragma unroll\n for (int kw=0; kw<3; ++kw) {\n int iw = iw0 + kw;\n if ((unsigned)iw < (unsigned)W) {\n float v = base[ih * W + iw];\n if (relu && v < 0.0f) v = 0.0f;\n m = fmaxf(m, v);\n }\n }\n }\n }\n y[idx] = m;\n}\n\ntorch::Tensor maxpool3x3_forward(torch::Tensor x, int stride, bool relu) {\n TORCH_CHECK(x.is_cuda(), \"x must be CUDA\");\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"float32 only\");\n x = x.contiguous();\n int N = x.size(0), C = x.size(1), H = x.size(2), W = x.size(3);\n int OH = (H + 2 - 3) / stride + 1;\n int OW = (W + 2 - 3) / stride + 1;\n auto y = torch::empty({N, C, OH, OW}, x.options());\n int total = N*C*OH*OW;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n maxpool3x3_kernel<<<blocks, threads>>>(x.data_ptr<float>(), y.data_ptr<float>(), total, N, C, H, W, OH, OW, stride, relu);\n return y;\n}\n'''\n\n_ext = load_inline(name='googlenet_pool_ext_v1', cpp_sources=_cpp, cuda_sources=_cuda,\n functions=['maxpool3x3_forward'], extra_cuda_cflags=['-O3'], verbose=False)\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 def forward(self, x):\n branch1x1 = self.branch1x1(x)\n branch3x3 = self.branch3x3(x)\n branch5x5 = self.branch5x5(x)\n p = _ext.maxpool3x3_forward(x, 1, False)\n branch_pool = self.branch_pool[1](p)\n return torch.cat([branch1x1, branch3x3, branch5x5, branch_pool], 1)\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 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 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 self.inception5a = InceptionModule(832, 256, 160, 320, 32, 128, 128)\n self.inception5b = InceptionModule(832, 384, 192, 384, 48, 128, 128)\n self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n self.dropout = nn.Dropout(0.0)\n self.fc = nn.Linear(1024, num_classes)\n def forward(self, x):\n x = _ext.maxpool3x3_forward(self.conv1(x), 2, True)\n x = F.relu(self.conv2(x))\n x = _ext.maxpool3x3_forward(self.conv3(x), 2, True)\n x = self.inception3a(x)\n x = self.inception3b(x)\n x = _ext.maxpool3x3_forward(x, 2, False)\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.maxpool3x3_forward(x, 2, False)\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"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=0.00e+00 mean_abs_err=0.00e+00 max_rel_err=0.00e+00
turn 3 · FINAL · 1 tool call(s) · 12.6s turn · 12.6s LLM · 6,652 chars (click to expand)
turn 312.6s turn · 12.6s LLM · 0.0s tools · FINAL
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 = r'''\n#include <torch/extension.h>\ntorch::Tensor maxpool3x3_forward(torch::Tensor x, int stride, bool relu);\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <float.h>\n\n__global__ void maxpool3x3_kernel(const float* __restrict__ x, float* __restrict__ y,\n int total, int N, int C, int H, int W, int OH, int OW,\n int stride, bool relu) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int ow = idx % OW;\n int t = idx / OW;\n int oh = t % OH;\n t /= OH;\n int c = t % C;\n int n = t / C;\n int ih0 = oh * stride - 1;\n int iw0 = ow * stride - 1;\n const float* base = x + ((n * C + c) * H) * W;\n float m = relu ? 0.0f : -FLT_MAX;\n #pragma unroll\n for (int kh=0; kh<3; ++kh) {\n int ih = ih0 + kh;\n if ((unsigned)ih < (unsigned)H) {\n #pragma unroll\n for (int kw=0; kw<3; ++kw) {\n int iw = iw0 + kw;\n if ((unsigned)iw < (unsigned)W) {\n float v = base[ih * W + iw];\n if (relu && v < 0.0f) v = 0.0f;\n m = fmaxf(m, v);\n }\n }\n }\n }\n y[idx] = m;\n}\n\ntorch::Tensor maxpool3x3_forward(torch::Tensor x, int stride, bool relu) {\n TORCH_CHECK(x.is_cuda(), \"x must be CUDA\");\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"float32 only\");\n x = x.contiguous();\n int N = x.size(0), C = x.size(1), H = x.size(2), W = x.size(3);\n int OH = (H + 2 - 3) / stride + 1;\n int OW = (W + 2 - 3) / stride + 1;\n auto y = torch::empty({N, C, OH, OW}, x.options());\n int total = N*C*OH*OW;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n maxpool3x3_kernel<<<blocks, threads>>>(x.data_ptr<float>(), y.data_ptr<float>(), total, N, C, H, W, OH, OW, stride, relu);\n return y;\n}\n'''\n\n_ext = load_inline(name='googlenet_pool_ext_v1', cpp_sources=_cpp, cuda_sources=_cuda,\n functions=['maxpool3x3_forward'], extra_cuda_cflags=['-O3'], verbose=False)\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 def forward(self, x):\n branch1x1 = self.branch1x1(x)\n branch3x3 = self.branch3x3(x)\n branch5x5 = self.branch5x5(x)\n p = _ext.maxpool3x3_forward(x, 1, False)\n branch_pool = self.branch_pool[1](p)\n return torch.cat([branch1x1, branch3x3, branch5x5, branch_pool], 1)\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 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 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 self.inception5a = InceptionModule(832, 256, 160, 320, 32, 128, 128)\n self.inception5b = InceptionModule(832, 384, 192, 384, 48, 128, 128)\n self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n self.dropout = nn.Dropout(0.0)\n self.fc = nn.Linear(1024, num_classes)\n def forward(self, x):\n x = _ext.maxpool3x3_forward(self.conv1(x), 2, True)\n x = F.relu(self.conv2(x))\n x = _ext.maxpool3x3_forward(self.conv3(x), 2, True)\n x = self.inception3a(x)\n x = self.inception3b(x)\n x = _ext.maxpool3x3_forward(x, 2, False)\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.maxpool3x3_forward(x, 2, False)\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"
}
result ← submit_kernel (ok)
oksubmit_kernel
submit_kernel PASSED: (5 / 5) correctness trials all passed.
Kernel runtime: 6.52 μs
Runtime stats: mean=6.52μs median=?μs std=33.70μs
Numerical precision: max_abs_err=0.00e+00 mean_abs_err=0.00e+00 max_rel_err=0.00e+00
Memory: 329.43 MB peak (ref: 330.39 MB, ratio: 0.9971x)
Kernel launches: 433 (ref: 450, fusion ratio: 1.0393)
Energy: 484.26 mJ/run (ref: 968.34 mJ, ratio: 1.9996x)
SOL score: 0.0515
final submitted kernel (135 lines, 5,418 chars) — full source, untruncated
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.cpp_extension import load_inline
_cpp = r'''
#include <torch/extension.h>
torch::Tensor maxpool3x3_forward(torch::Tensor x, int stride, bool relu);
'''
_cuda = r'''
#include <torch/extension.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <float.h>
__global__ void maxpool3x3_kernel(const float* __restrict__ x, float* __restrict__ y,
int total, int N, int C, int H, int W, int OH, int OW,
int stride, bool relu) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx >= total) return;
int ow = idx % OW;
int t = idx / OW;
int oh = t % OH;
t /= OH;
int c = t % C;
int n = t / C;
int ih0 = oh * stride - 1;
int iw0 = ow * stride - 1;
const float* base = x + ((n * C + c) * H) * W;
float m = relu ? 0.0f : -FLT_MAX;
#pragma unroll
for (int kh=0; kh<3; ++kh) {
int ih = ih0 + kh;
if ((unsigned)ih < (unsigned)H) {
#pragma unroll
for (int kw=0; kw<3; ++kw) {
int iw = iw0 + kw;
if ((unsigned)iw < (unsigned)W) {
float v = base[ih * W + iw];
if (relu && v < 0.0f) v = 0.0f;
m = fmaxf(m, v);
}
}
}
}
y[idx] = m;
}
torch::Tensor maxpool3x3_forward(torch::Tensor x, int stride, bool relu) {
TORCH_CHECK(x.is_cuda(), "x must be CUDA");
TORCH_CHECK(x.scalar_type() == torch::kFloat32, "float32 only");
x = x.contiguous();
int N = x.size(0), C = x.size(1), H = x.size(2), W = x.size(3);
int OH = (H + 2 - 3) / stride + 1;
int OW = (W + 2 - 3) / stride + 1;
auto y = torch::empty({N, C, OH, OW}, x.options());
int total = N*C*OH*OW;
int threads = 256;
int blocks = (total + threads - 1) / threads;
maxpool3x3_kernel<<<blocks, threads>>>(x.data_ptr<float>(), y.data_ptr<float>(), total, N, C, H, W, OH, OW, stride, relu);
return y;
}
'''
_ext = load_inline(name='googlenet_pool_ext_v1', cpp_sources=_cpp, cuda_sources=_cuda,
functions=['maxpool3x3_forward'], extra_cuda_cflags=['-O3'], verbose=False)
class InceptionModule(nn.Module):
def __init__(self, in_channels, out_1x1, reduce_3x3, out_3x3, reduce_5x5, out_5x5, pool_proj):
super(InceptionModule, self).__init__()
self.branch1x1 = nn.Conv2d(in_channels, out_1x1, kernel_size=1)
self.branch3x3 = nn.Sequential(
nn.Conv2d(in_channels, reduce_3x3, kernel_size=1),
nn.Conv2d(reduce_3x3, out_3x3, kernel_size=3, padding=1)
)
self.branch5x5 = nn.Sequential(
nn.Conv2d(in_channels, reduce_5x5, kernel_size=1),
nn.Conv2d(reduce_5x5, out_5x5, kernel_size=5, padding=2)
)
self.branch_pool = nn.Sequential(
nn.MaxPool2d(kernel_size=3, stride=1, padding=1),
nn.Conv2d(in_channels, pool_proj, kernel_size=1)
)
def forward(self, x):
branch1x1 = self.branch1x1(x)
branch3x3 = self.branch3x3(x)
branch5x5 = self.branch5x5(x)
p = _ext.maxpool3x3_forward(x, 1, False)
branch_pool = self.branch_pool[1](p)
return torch.cat([branch1x1, branch3x3, branch5x5, branch_pool], 1)
class ModelNew(nn.Module):
def __init__(self, num_classes=1000):
super(ModelNew, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3)
self.maxpool1 = nn.MaxPool2d(3, stride=2, padding=1)
self.conv2 = nn.Conv2d(64, 64, kernel_size=1)
self.conv3 = nn.Conv2d(64, 192, kernel_size=3, padding=1)
self.maxpool2 = nn.MaxPool2d(3, stride=2, padding=1)
self.inception3a = InceptionModule(192, 64, 96, 128, 16, 32, 32)
self.inception3b = InceptionModule(256, 128, 128, 192, 32, 96, 64)
self.maxpool3 = nn.MaxPool2d(3, stride=2, padding=1)
self.inception4a = InceptionModule(480, 192, 96, 208, 16, 48, 64)
self.inception4b = InceptionModule(512, 160, 112, 224, 24, 64, 64)
self.inception4c = InceptionModule(512, 128, 128, 256, 24, 64, 64)
self.inception4d = InceptionModule(512, 112, 144, 288, 32, 64, 64)
self.inception4e = InceptionModule(528, 256, 160, 320, 32, 128, 128)
self.maxpool4 = nn.MaxPool2d(3, stride=2, padding=1)
self.inception5a = InceptionModule(832, 256, 160, 320, 32, 128, 128)
self.inception5b = InceptionModule(832, 384, 192, 384, 48, 128, 128)
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
self.dropout = nn.Dropout(0.0)
self.fc = nn.Linear(1024, num_classes)
def forward(self, x):
x = _ext.maxpool3x3_forward(self.conv1(x), 2, True)
x = F.relu(self.conv2(x))
x = _ext.maxpool3x3_forward(self.conv3(x), 2, True)
x = self.inception3a(x)
x = self.inception3b(x)
x = _ext.maxpool3x3_forward(x, 2, False)
x = self.inception4a(x)
x = self.inception4b(x)
x = self.inception4c(x)
x = self.inception4d(x)
x = self.inception4e(x)
x = _ext.maxpool3x3_forward(x, 2, False)
x = self.inception5a(x)
x = self.inception5b(x)
x = self.avgpool(x)
x = torch.flatten(x, 1)
x = self.dropout(x)
x = self.fc(x)
return x