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#include <vector>\n\ntorch::Tensor eff_forward(torch::Tensor x, std::vector<torch::Tensor> p);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <vector>\n#include <cmath>\n\n#define BN_EPS 1.0e-5f\n\n__device__ __forceinline__ float relu_f(float x){ return x > 0.0f ? x : 0.0f; }\n__device__ __forceinline__ float sigmoid_f(float x){ return 1.0f / (1.0f + __expf(-x)); }\n\n__global__ void conv1_bn_relu_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ gamma,\n const float* __restrict__ beta,\n const float* __restrict__ mean,\n const float* __restrict__ var,\n float* __restrict__ y,\n int N) {\n const int Hout = 112, Wout = 112, Coo = 32, Cin = 3, Hin = 224, Win = 224;\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = N * Coo * Hout * Wout;\n if (idx >= total) return;\n int ow = idx % Wout;\n int t = idx / Wout;\n int oh = t % Hout;\n t /= Hout;\n int co = t % Coo;\n int n = t / Coo;\n\n float sum = 0.0f;\n int ih0 = oh * 2 - 1;\n int iw0 = ow * 2 - 1;\n #pragma unroll\n for (int ci=0; ci<3; ++ci) {\n #pragma unroll\n for (int kh=0; kh<3; ++kh) {\n int ih = ih0 + kh;\n if ((unsigned)ih >= (unsigned)Hin) continue;\n #pragma unroll\n for (int kw=0; kw<3; ++kw) {\n int iw = iw0 + kw;\n if ((unsigned)iw >= (unsigned)Win) continue;\n float xv = x[((n*Cin + ci)*Hin + ih)*Win + iw];\n float wv = w[((co*Cin + ci)*3 + kh)*3 + kw];\n sum += xv * wv;\n }\n }\n }\n float v = (sum - mean[co]) * rsqrtf(var[co] + BN_EPS) * gamma[co] + beta[co];\n y[idx] = relu_f(v);\n}\n\n__global__ void conv1x1_bn_relu_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ gamma,\n const float* __restrict__ beta,\n const float* __restrict__ mean,\n const float* __restrict__ var,\n float* __restrict__ y,\n int N, int Cin, int Cout, int HW) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = N * Cout * HW;\n if (idx >= total) return;\n int s = idx % HW;\n int t = idx / HW;\n int co = t % Cout;\n int n = t / Cout;\n float sum = 0.0f;\n const float* xp = x + n * Cin * HW + s;\n const float* wp = w + co * Cin;\n for (int ci=0; ci<Cin; ++ci) sum += xp[ci * HW] * wp[ci];\n float v = (sum - mean[co]) * rsqrtf(var[co] + BN_EPS) * gamma[co] + beta[co];\n y[idx] = relu_f(v);\n}\n\n__global__ void depthwise3x3_avg_bn_relu_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ gamma,\n const float* __restrict__ beta,\n const float* __restrict__ mean,\n const float* __restrict__ var,\n float* __restrict__ out,\n int N, int C) {\n const int H = 112, Wd = 112, HW = 12544;\n int bc = blockIdx.x;\n int c = bc % C;\n int n = bc / C;\n int tid = threadIdx.x;\n __shared__ float sh[256];\n float acc = 0.0f;\n const float* xp = x + (n*C + c)*HW;\n const float* wp = w + c*9;\n for (int s = tid; s < HW; s += blockDim.x) {\n int oh = s / Wd;\n int ow = s - oh * Wd;\n float sum = 0.0f;\n #pragma unroll\n for (int kh=0; kh<3; ++kh) {\n int ih = oh + kh - 1;\n if ((unsigned)ih >= (unsigned)H) continue;\n #pragma unroll\n for (int kw=0; kw<3; ++kw) {\n int iw = ow + kw - 1;\n if ((unsigned)iw >= (unsigned)Wd) continue;\n sum += xp[ih*Wd + iw] * wp[kh*3 + kw];\n }\n }\n float v = (sum - mean[c]) * rsqrtf(var[c] + BN_EPS) * gamma[c] + beta[c];\n acc += relu_f(v);\n }\n sh[tid] = acc;\n __syncthreads();\n for (int off = 128; off > 0; off >>= 1) {\n if (tid < off) sh[tid] += sh[tid + off];\n __syncthreads();\n }\n if (tid == 0) out[n*C + c] = sh[0] * (1.0f / 12544.0f);\n}\n\n__global__ void matvec_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n const float* __restrict__ gamma,\n const float* __restrict__ beta,\n const float* __restrict__ mean,\n const float* __restrict__ var,\n float* __restrict__ y,\n int N, int K, int M,\n int has_bias, int has_bn, int do_relu, int do_sigmoid) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = N * M;\n if (idx >= total) return;\n int m = idx % M;\n int n = idx / M;\n const float* xp = x + n*K;\n const float* wp = w + m*K;\n float sum = 0.0f;\n for (int k=0; k<K; ++k) sum += xp[k] * wp[k];\n if (has_bias) sum += bias[m];\n if (has_bn) sum = (sum - mean[m]) * rsqrtf(var[m] + BN_EPS) * gamma[m] + beta[m];\n if (do_relu) sum = relu_f(sum);\n if (do_sigmoid) sum = sigmoid_f(sum);\n y[idx] = sum;\n}\n\n__global__ void vector_dw_bn_relu_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ gamma,\n const float* __restrict__ beta,\n const float* __restrict__ mean,\n const float* __restrict__ var,\n float* __restrict__ y,\n int N, int C) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = N*C;\n if (idx >= total) return;\n int c = idx % C;\n float sum = x[idx] * w[c*9 + 4];\n float v = (sum - mean[c]) * rsqrtf(var[c] + BN_EPS) * gamma[c] + beta[c];\n y[idx] = relu_f(v);\n}\n\nstatic inline void launch_mat(torch::Tensor in, torch::Tensor w, torch::Tensor bias,\n torch::Tensor gamma, torch::Tensor beta, torch::Tensor mean, torch::Tensor var,\n torch::Tensor out, int N, int K, int M,\n int has_bias, int has_bn, int do_relu, int do_sigmoid) {\n int total = N*M;\n dim3 block(256);\n dim3 grid((total + 255) / 256);\n const float* bptr = has_bias ? bias.data_ptr<float>() : nullptr;\n const float* gptr = has_bn ? gamma.data_ptr<float>() : nullptr;\n const float* betaptr = has_bn ? beta.data_ptr<float>() : nullptr;\n const float* mptr = has_bn ? mean.data_ptr<float>() : nullptr;\n const float* vptr = has_bn ? var.data_ptr<float>() : nullptr;\n matvec_kernel<<<grid, block>>>(in.data_ptr<float>(), w.data_ptr<float>(), bptr, gptr, betaptr, mptr, vptr,\n out.data_ptr<float>(), N, K, M, has_bias, has_bn, do_relu, do_sigmoid);\n}\n\ntorch::Tensor eff_forward(torch::Tensor x, std::vector<torch::Tensor> p) {\n int N = (int)x.size(0);\n auto opts = x.options();\n const int HW = 112*112;\n torch::Tensor a = torch::empty({N, 32, 112, 112}, opts);\n torch::Tensor b = torch::empty({N, 96, 112, 112}, opts);\n torch::Tensor v = torch::empty({N, 96}, opts);\n\n int idx = 0;\n dim3 block(256);\n conv1_bn_relu_kernel<<<(N*32*HW + 255)/256, block>>>(x.data_ptr<float>(), p[idx].data_ptr<float>(), p[idx+1].data_ptr<float>(), p[idx+2].data_ptr<float>(), p[idx+3].data_ptr<float>(), p[idx+4].data_ptr<float>(), a.data_ptr<float>(), N);\n idx += 5;\n\n // MBConv1 spatial part: expansion 32->96, depthwise+avg\n conv1x1_bn_relu_kernel<<<(N*96*HW + 255)/256, block>>>(a.data_ptr<float>(), p[idx].data_ptr<float>(), p[idx+1].data_ptr<float>(), p[idx+2].data_ptr<float>(), p[idx+3].data_ptr<float>(), p[idx+4].data_ptr<float>(), b.data_ptr<float>(), N, 32, 96, HW);\n idx += 5;\n depthwise3x3_avg_bn_relu_kernel<<<N*96, block>>>(b.data_ptr<float>(), p[idx].data_ptr<float>(), p[idx+1].data_ptr<float>(), p[idx+2].data_ptr<float>(), p[idx+3].data_ptr<float>(), p[idx+4].data_ptr<float>(), v.data_ptr<float>(), N, 96);\n idx += 5;\n\n // remaining per-vector layers. Consume rest of MBConv1 first.\n auto empty = torch::Tensor();\n torch::Tensor t1, t2;\n t1 = torch::empty({N, 24}, opts);\n launch_mat(v, p[idx], empty, empty, empty, empty, empty, t1, N, 96, 24, 0, 0, 1, 0); idx++;\n t2 = torch::empty({N, 96}, opts);\n launch_mat(t1, p[idx], empty, empty, empty, empty, empty, t2, N, 24, 96, 0, 0, 0, 1); idx++;\n v = torch::empty({N, 96}, opts);\n launch_mat(t2, p[idx], empty, p[idx+1], p[idx+2], p[idx+3], p[idx+4], v, N, 96, 96, 0, 1, 0, 0); idx += 5;\n\n // MBConv2..5\n int Cin_arr[4] = {96,144,192,288};\n int E_arr[4] = {576,864,1152,1728};\n int O_arr[4] = {144,192,288,384};\n for (int bi=0; bi<4; ++bi) {\n int Cin = Cin_arr[bi], E = E_arr[bi], O = O_arr[bi];\n t1 = torch::empty({N, E}, opts);\n launch_mat(v, p[idx], empty, p[idx+1], p[idx+2], p[idx+3], p[idx+4], t1, N, Cin, E, 0, 1, 1, 0); idx += 5;\n t2 = torch::empty({N, E}, opts);\n vector_dw_bn_relu_kernel<<<(N*E + 255)/256, block>>>(t1.data_ptr<float>(), p[idx].data_ptr<float>(), p[idx+1].data_ptr<float>(), p[idx+2].data_ptr<float>(), p[idx+3].data_ptr<float>(), p[idx+4].data_ptr<float>(), t2.data_ptr<float>(), N, E);\n idx += 5;\n t1 = torch::empty({N, E/4}, opts);\n launch_mat(t2, p[idx], empty, empty, empty, empty, empty, t1, N, E, E/4, 0, 0, 1, 0); idx++;\n torch::Tensor sig = torch::empty({N, E}, opts);\n launch_mat(t1, p[idx], empty, empty, empty, empty, empty, sig, N, E/4, E, 0, 0, 0, 1); idx++;\n v = torch::empty({N, O}, opts);\n launch_mat(sig, p[idx], empty, p[idx+1], p[idx+2], p[idx+3], p[idx+4], v, N, E, O, 0, 1, 0, 0); idx += 5;\n }\n\n // final conv/bn/relu and FC\n t1 = torch::empty({N, 1408}, opts);\n launch_mat(v, p[idx], empty, p[idx+1], p[idx+2], p[idx+3], p[idx+4], t1, N, 384, 1408, 0, 1, 1, 0); idx += 5;\n int M = (int)p[idx].size(0);\n torch::Tensor out = torch::empty({N, M}, opts);\n launch_mat(t1, p[idx], p[idx+1], empty, empty, empty, empty, out, N, 1408, M, 1, 0, 0, 0);\n return out;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"efficientnet_b2_weird_fused_ext\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"eff_forward\"],\n with_cuda=True,\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, 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.relu = nn.ReLU(inplace=True)\n self.mbconv1 = self._make_mbconv_block(32, 96, 1, 3)\n self.mbconv2 = self._make_mbconv_block(96, 144, 2, 6)\n self.mbconv3 = self._make_mbconv_block(144, 192, 2, 6)\n self.mbconv4 = self._make_mbconv_block(192, 288, 2, 6)\n self.mbconv5 = self._make_mbconv_block(288, 384, 1, 6)\n self.conv_final = nn.Conv2d(384, 1408, kernel_size=1, stride=1, padding=0, bias=False)\n self.bn_final = nn.BatchNorm2d(1408)\n self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n self.fc = nn.Linear(1408, num_classes)\n\n def _make_mbconv_block(self, in_channels, out_channels, stride, expand_ratio):\n layers = []\n expanded_channels = in_channels * expand_ratio\n if expand_ratio != 1:\n layers.append(nn.Conv2d(in_channels, expanded_channels, kernel_size=1, stride=1, padding=0, bias=False))\n layers.append(nn.BatchNorm2d(expanded_channels))\n layers.append(nn.ReLU(inplace=True))\n layers.append(nn.Conv2d(expanded_channels, expanded_channels, kernel_size=3, stride=stride, padding=1, groups=expanded_channels, bias=False))\n layers.append(nn.BatchNorm2d(expanded_channels))\n layers.append(nn.ReLU(inplace=True))\n layers.append(nn.AdaptiveAvgPool2d((1, 1)))\n layers.append(nn.Conv2d(expanded_channels, expanded_channels // 4, kernel_size=1, stride=1, padding=0, bias=False))\n layers.append(nn.ReLU(inplace=True))\n layers.append(nn.Conv2d(expanded_channels // 4, expanded_channels, kernel_size=1, stride=1, padding=0, bias=False))\n layers.append(nn.Sigmoid())\n layers.append(nn.Conv2d(expanded_channels, out_channels, kernel_size=1, stride=1, padding=0, bias=False))\n layers.append(nn.BatchNorm2d(out_channels))\n return nn.Sequential(*layers)\n\n def _append_bn(self, params, bn):\n params.extend([bn.weight, bn.bias, bn.running_mean, bn.running_var])\n\n def _append_block(self, params, block):\n # all blocks in this model have expansion conv at indices 0/1\n params.append(block[0].weight); self._append_bn(params, block[1])\n params.append(block[3].weight); self._append_bn(params, block[4])\n params.append(block[7].weight)\n params.append(block[9].weight)\n params.append(block[11].weight); self._append_bn(params, block[12])\n\n def forward(self, x):\n params = []\n params.append(self.conv1.weight); self._append_bn(params, self.bn1)\n self._append_block(params, self.mbconv1)\n self._append_block(params, self.mbconv2)\n self._append_block(params, self.mbconv3)\n self._append_block(params, self.mbconv4)\n self._append_block(params, self.mbconv5)\n params.append(self.conv_final.weight); self._append_bn(params, self.bn_final)\n params.extend([self.fc.weight, self.fc.bias])\n return _ext.eff_forward(x.contiguous(), params)\n"
}