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_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <vector>\n\n__global__ void spatial_mean_kernel(const float* __restrict__ x, float* __restrict__ m,\n int N, int C, int H, int W) {\n int idx = blockIdx.x;\n int c = idx % C;\n int n = idx / C;\n int HW = H * W;\n const float* p = x + ((n * C + c) * H * W);\n float s = 0.0f;\n // H*W is normally 64 here; keep generic.\n for (int i = threadIdx.x; i < HW; i += blockDim.x) s += p[i];\n __shared__ float sm[128];\n sm[threadIdx.x] = s;\n __syncthreads();\n for (int off = blockDim.x >> 1; off > 0; off >>= 1) {\n if (threadIdx.x < off) sm[threadIdx.x] += sm[threadIdx.x + off];\n __syncthreads();\n }\n if (threadIdx.x == 0) m[n * C + c] = sm[0] / (float)HW;\n}\n\n__global__ void hidden_kernel(const float* __restrict__ m,\n const float* __restrict__ cw,\n const float* __restrict__ bw,\n const float* __restrict__ bb,\n const float* __restrict__ brm,\n const float* __restrict__ brv,\n float* __restrict__ h,\n int N, int C, int K, float eps) {\n int idx = blockIdx.x;\n int k = idx % K;\n int n = idx / K;\n float sum = 0.0f;\n const float* mp = m + n * C;\n const float* wp = cw + k * C;\n for (int c = threadIdx.x; c < C; c += blockDim.x) {\n sum += mp[c] * wp[c];\n }\n __shared__ float sm[256];\n sm[threadIdx.x] = sum;\n __syncthreads();\n for (int off = blockDim.x >> 1; off > 0; off >>= 1) {\n if (threadIdx.x < off) sm[threadIdx.x] += sm[threadIdx.x + off];\n __syncthreads();\n }\n if (threadIdx.x == 0) {\n float y = (sm[0] - brm[k]) * rsqrtf(brv[k] + eps) * bw[k] + bb[k];\n h[n * K + k] = y > 0.0f ? y : 0.0f;\n }\n}\n\n__global__ void fc_kernel(const float* __restrict__ h,\n const float* __restrict__ fw,\n const float* __restrict__ fb,\n float* __restrict__ out,\n int N, int K, int O) {\n int idx = blockIdx.x;\n int o = idx % O;\n int n = idx / O;\n const float* hp = h + n * K;\n const float* wp = fw + o * K;\n float sum = 0.0f;\n for (int k = threadIdx.x; k < K; k += blockDim.x) {\n sum += hp[k] * wp[k];\n }\n __shared__ float sm[256];\n sm[threadIdx.x] = sum;\n __syncthreads();\n for (int off = blockDim.x >> 1; off > 0; off >>= 1) {\n if (threadIdx.x < off) sm[threadIdx.x] += sm[threadIdx.x + off];\n __syncthreads();\n }\n if (threadIdx.x == 0) out[n * O + o] = sm[0] + fb[o];\n}\n\ntorch::Tensor eff_tail_forward(torch::Tensor x,\n torch::Tensor conv_w,\n torch::Tensor bn_w,\n torch::Tensor bn_b,\n torch::Tensor bn_rm,\n torch::Tensor bn_rv,\n torch::Tensor fc_w,\n torch::Tensor fc_b,\n double eps) {\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 K = (int)conv_w.size(0);\n const int O = (int)fc_w.size(0);\n auto opts = x.options();\n auto means = torch::empty({N, C}, opts);\n auto hidden = torch::empty({N, K}, opts);\n auto out = torch::empty({N, O}, opts);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n spatial_mean_kernel<<<N * C, 128, 0, stream>>>(x.data_ptr<float>(), means.data_ptr<float>(), N, C, H, W);\n hidden_kernel<<<N * K, 256, 0, stream>>>(means.data_ptr<float>(), conv_w.data_ptr<float>(),\n bn_w.data_ptr<float>(), bn_b.data_ptr<float>(),\n bn_rm.data_ptr<float>(), bn_rv.data_ptr<float>(),\n hidden.data_ptr<float>(), N, C, K, (float)eps);\n fc_kernel<<<N * O, 256, 0, stream>>>(hidden.data_ptr<float>(), fc_w.data_ptr<float>(),\n fc_b.data_ptr<float>(), out.data_ptr<float>(), N, K, O);\n return out;\n}\n'''\n\n_cpp_src = r'''\n#include <torch/extension.h>\ntorch::Tensor eff_tail_forward(torch::Tensor x,\n torch::Tensor conv_w,\n torch::Tensor bn_w,\n torch::Tensor bn_b,\n torch::Tensor bn_rm,\n torch::Tensor bn_rv,\n torch::Tensor fc_w,\n torch::Tensor fc_b,\n double eps);\n'''\n\n_eff_ext = load_inline(\n name='effnet_b1_tail_ext_v1',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['eff_tail_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, num_classes=1000):\n super(ModelNew, self).__init__()\n self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=2, padding=1, bias=False)\n self.bn1 = nn.BatchNorm2d(32)\n self.mbconv1 = self._make_mbconv_block(32, 16, 1, 1)\n self.mbconv2 = self._make_mbconv_block(16, 24, 2, 6)\n self.mbconv3 = self._make_mbconv_block(24, 40, 2, 6)\n self.mbconv4 = self._make_mbconv_block(40, 80, 2, 6)\n self.mbconv5 = self._make_mbconv_block(80, 112, 1, 6)\n self.mbconv6 = self._make_mbconv_block(112, 192, 2, 6)\n self.mbconv7 = self._make_mbconv_block(192, 320, 1, 6)\n self.conv2 = nn.Conv2d(320, 1280, kernel_size=1, stride=1, padding=0, bias=False)\n self.bn2 = nn.BatchNorm2d(1280)\n self.fc = nn.Linear(1280, num_classes)\n\n def _make_mbconv_block(self, in_channels, out_channels, stride, expand_ratio):\n hidden_dim = round(in_channels * expand_ratio)\n return nn.Sequential(\n nn.Conv2d(in_channels, hidden_dim, kernel_size=1, stride=1, padding=0, bias=False),\n nn.BatchNorm2d(hidden_dim),\n nn.ReLU6(inplace=True),\n nn.Conv2d(hidden_dim, hidden_dim, kernel_size=3, stride=stride, padding=1, groups=hidden_dim, bias=False),\n nn.BatchNorm2d(hidden_dim),\n nn.ReLU6(inplace=True),\n nn.Conv2d(hidden_dim, out_channels, kernel_size=1, stride=1, padding=0, bias=False),\n nn.BatchNorm2d(out_channels),\n )\n\n def forward(self, x):\n x = F.relu(self.bn1(self.conv1(x)))\n x = self.mbconv1(x)\n x = self.mbconv2(x)\n x = self.mbconv3(x)\n x = self.mbconv4(x)\n x = self.mbconv5(x)\n x = self.mbconv6(x)\n x = self.mbconv7(x)\n # In inference mode, commute the final 1x1 convolution with global average pooling\n # and fuse conv2 + bn2 + relu + avgpool + linear in custom CUDA kernels.\n if x.is_cuda and x.dtype is torch.float32 and (not self.training):\n return _eff_ext.eff_tail_forward(\n x.contiguous(), self.conv2.weight.contiguous().view(1280, 320),\n self.bn2.weight.contiguous(), self.bn2.bias.contiguous(),\n self.bn2.running_mean.contiguous(), self.bn2.running_var.contiguous(),\n self.fc.weight.contiguous(), self.fc.bias.contiguous(), float(self.bn2.eps))\n else:\n x = F.relu(self.bn2(self.conv2(x)))\n x = F.adaptive_avg_pool2d(x, (1, 1))\n x = torch.flatten(x, 1)\n x = self.fc(x)\n return x\n"
}