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#include <pybind11/stl.h>\n\ntorch::Tensor cvit_forward(\n torch::Tensor x,\n torch::Tensor conv_w, torch::Tensor conv_b,\n torch::Tensor lp_w, torch::Tensor lp_b,\n torch::Tensor cls,\n std::vector<torch::Tensor> in_w, std::vector<torch::Tensor> in_b,\n std::vector<torch::Tensor> out_w, std::vector<torch::Tensor> out_b,\n std::vector<torch::Tensor> n1_w, std::vector<torch::Tensor> n1_b,\n std::vector<torch::Tensor> l1_w, std::vector<torch::Tensor> l1_b,\n std::vector<torch::Tensor> l2_w, std::vector<torch::Tensor> l2_b,\n std::vector<torch::Tensor> n2_w, std::vector<torch::Tensor> n2_b,\n torch::Tensor fc_w, torch::Tensor fc_b,\n int64_t num_heads);\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 <vector>\n#include <math.h>\n\n__global__ void conv_flat_kernel(const float* __restrict__ x, const float* __restrict__ w, const float* __restrict__ bias,\n float* __restrict__ out,\n int B, int C, int H, int W, int E, int P) {\n int Hp = H / P;\n int Wp = W / P;\n int Kflat = E * Hp * Wp;\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = B * Kflat;\n if (idx >= total) return;\n int k = idx % Kflat;\n int b = idx / Kflat;\n int pw = k % Wp;\n int ph = (k / Wp) % Hp;\n int e = k / (Hp * Wp);\n float sum = bias[e];\n int ih0 = ph * P;\n int iw0 = pw * P;\n for (int c = 0; c < C; ++c) {\n for (int kh = 0; kh < P; ++kh) {\n for (int kw = 0; kw < P; ++kw) {\n float xv = x[((b*C + c)*H + (ih0+kh))*W + (iw0+kw)];\n float wv = w[((e*C + c)*P + kh)*P + kw];\n sum += xv * wv;\n }\n }\n }\n out[idx] = sum;\n}\n\n__global__ void linear_proj_kernel(const float* __restrict__ inp, const float* __restrict__ w, const float* __restrict__ bias,\n float* __restrict__ out, int B, int K, int D) {\n __shared__ float s[256];\n int od = blockIdx.x;\n int b = blockIdx.y;\n int tid = threadIdx.x;\n float sum = 0.0f;\n const float* ip = inp + b*K;\n const float* wp = w + od*K;\n for (int k = tid; k < K; k += blockDim.x) sum += ip[k] * wp[k];\n s[tid] = sum;\n __syncthreads();\n for (int off = blockDim.x/2; off > 0; off >>= 1) {\n if (tid < off) s[tid] += s[tid+off];\n __syncthreads();\n }\n if (tid == 0) out[b*D + od] = s[0] + bias[od];\n}\n\n__global__ void init_seq_kernel(const float* __restrict__ lin, const float* __restrict__ cls,\n float* __restrict__ seq, int B, int D) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = B * 2 * D;\n if (idx >= total) return;\n int d = idx % D;\n int t = (idx / D) & 1;\n int b = idx / (2*D);\n seq[idx] = (t == 0) ? cls[d] : lin[b*D + d];\n}\n\n__global__ void encoder_layer_kernel(float* __restrict__ seq,\n const float* __restrict__ inpw, const float* __restrict__ inpb,\n const float* __restrict__ opw, const float* __restrict__ opb,\n const float* __restrict__ n1w, const float* __restrict__ n1b,\n const float* __restrict__ l1w, const float* __restrict__ l1b,\n const float* __restrict__ l2w, const float* __restrict__ l2b,\n const float* __restrict__ n2w, const float* __restrict__ n2b,\n int D, int FF, int NH) {\n __shared__ float X[256];\n __shared__ float Q[256];\n __shared__ float Kk[256];\n __shared__ float V[256];\n __shared__ float A[256];\n __shared__ float Z[256];\n __shared__ float Y[256];\n __shared__ float Hh[1024];\n __shared__ float red[256];\n\n int b = blockIdx.x;\n int tid = threadIdx.x;\n float* base = seq + b * 2 * D;\n\n for (int i = tid; i < 2*D; i += blockDim.x) X[i] = base[i];\n __syncthreads();\n\n // in-projection: q,k,v = X @ W^T + b\n for (int idx = tid; idx < 2*3*D; idx += blockDim.x) {\n int d = idx % D;\n int qkv = (idx / D) % 3;\n int t = idx / (3*D);\n float sum = inpb[qkv*D + d];\n const float* wp = inpw + (qkv*D + d) * D;\n const float* xp = X + t*D;\n for (int j = 0; j < D; ++j) sum += xp[j] * wp[j];\n if (qkv == 0) Q[t*D + d] = sum;\n else if (qkv == 1) Kk[t*D + d] = sum;\n else V[t*D + d] = sum;\n }\n __syncthreads();\n\n int HD = D / NH;\n float scale = rsqrtf((float)HD);\n // attention output before output projection\n for (int idx = tid; idx < 2*D; idx += blockDim.x) {\n int d = idx % D;\n int t = idx / D;\n int h = d / HD;\n int h0 = h * HD;\n float s0 = 0.0f, s1 = 0.0f;\n for (int i = 0; i < HD; ++i) {\n float qv = Q[t*D + h0 + i];\n s0 += qv * Kk[0*D + h0 + i];\n s1 += qv * Kk[1*D + h0 + i];\n }\n s0 *= scale; s1 *= scale;\n float m = s0 > s1 ? s0 : s1;\n float e0 = expf(s0 - m);\n float e1 = expf(s1 - m);\n float inv = 1.0f / (e0 + e1);\n float w0 = e0 * inv, w1 = e1 * inv;\n A[idx] = w0 * V[0*D + d] + w1 * V[1*D + d];\n }\n __syncthreads();\n\n // attention output projection, residual\n for (int idx = tid; idx < 2*D; idx += blockDim.x) {\n int d = idx % D;\n int t = idx / D;\n float sum = opb[d];\n const float* wp = opw + d*D;\n const float* ap = A + t*D;\n for (int j = 0; j < D; ++j) sum += ap[j] * wp[j];\n Z[idx] = X[idx] + sum;\n }\n __syncthreads();\n\n // norm1\n for (int t = 0; t < 2; ++t) {\n float v = (tid < D) ? Z[t*D + tid] : 0.0f;\n red[tid] = v;\n __syncthreads();\n for (int off = blockDim.x/2; off > 0; off >>= 1) {\n if (tid < off) red[tid] += red[tid+off];\n __syncthreads();\n }\n float mean = red[0] / (float)D;\n float vv = 0.0f;\n if (tid < D) { float a = Z[t*D + tid] - mean; vv = a*a; }\n red[tid] = vv;\n __syncthreads();\n for (int off = blockDim.x/2; off > 0; off >>= 1) {\n if (tid < off) red[tid] += red[tid+off];\n __syncthreads();\n }\n float invstd = rsqrtf(red[0] / (float)D + 1.0e-5f);\n if (tid < D) Y[t*D + tid] = (Z[t*D + tid] - mean) * invstd * n1w[tid] + n1b[tid];\n __syncthreads();\n }\n\n // MLP linear1 + ReLU\n for (int idx = tid; idx < 2*FF; idx += blockDim.x) {\n int f = idx % FF;\n int t = idx / FF;\n float sum = l1b[f];\n const float* wp = l1w + f*D;\n const float* yp = Y + t*D;\n for (int j = 0; j < D; ++j) sum += yp[j] * wp[j];\n Hh[idx] = sum > 0.0f ? sum : 0.0f;\n }\n __syncthreads();\n\n // MLP linear2, residual\n for (int idx = tid; idx < 2*D; idx += blockDim.x) {\n int d = idx % D;\n int t = idx / D;\n float sum = l2b[d];\n const float* hp = Hh + t*FF;\n for (int f = 0; f < FF; ++f) sum += hp[f] * l2w[d*FF + f];\n Z[idx] = Y[idx] + sum;\n }\n __syncthreads();\n\n // norm2 and write back\n for (int t = 0; t < 2; ++t) {\n float v = (tid < D) ? Z[t*D + tid] : 0.0f;\n red[tid] = v;\n __syncthreads();\n for (int off = blockDim.x/2; off > 0; off >>= 1) {\n if (tid < off) red[tid] += red[tid+off];\n __syncthreads();\n }\n float mean = red[0] / (float)D;\n float vv = 0.0f;\n if (tid < D) { float a = Z[t*D + tid] - mean; vv = a*a; }\n red[tid] = vv;\n __syncthreads();\n for (int off = blockDim.x/2; off > 0; off >>= 1) {\n if (tid < off) red[tid] += red[tid+off];\n __syncthreads();\n }\n float invstd = rsqrtf(red[0] / (float)D + 1.0e-5f);\n if (tid < D) base[t*D + tid] = (Z[t*D + tid] - mean) * invstd * n2w[tid] + n2b[tid];\n __syncthreads();\n }\n}\n\n__global__ void fc_kernel(const float* __restrict__ seq, const float* __restrict__ w, const float* __restrict__ bias,\n float* __restrict__ out, int B, int D, int C) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n const float* xp = seq + b*2*D; // CLS token\n for (int c = tid; c < C; c += blockDim.x) {\n float sum = bias[c];\n const float* wp = w + c*D;\n for (int j = 0; j < D; ++j) sum += xp[j] * wp[j];\n out[b*C + c] = sum;\n }\n}\n\ntorch::Tensor cvit_forward(\n torch::Tensor x,\n torch::Tensor conv_w, torch::Tensor conv_b,\n torch::Tensor lp_w, torch::Tensor lp_b,\n torch::Tensor cls,\n std::vector<torch::Tensor> in_w, std::vector<torch::Tensor> in_b,\n std::vector<torch::Tensor> out_w, std::vector<torch::Tensor> out_b,\n std::vector<torch::Tensor> n1_w, std::vector<torch::Tensor> n1_b,\n std::vector<torch::Tensor> l1_w, std::vector<torch::Tensor> l1_b,\n std::vector<torch::Tensor> l2_w, std::vector<torch::Tensor> l2_b,\n std::vector<torch::Tensor> n2_w, std::vector<torch::Tensor> n2_b,\n torch::Tensor fc_w, torch::Tensor fc_b,\n int64_t num_heads) {\n\n int B = (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 E = (int)conv_w.size(0);\n int P = (int)conv_w.size(2);\n int Hp = H / P, Wp = W / P;\n int Kflat = E * Hp * Wp;\n int D = (int)lp_w.size(0);\n int FF = (int)l1_w[0].size(0);\n int NC = (int)fc_w.size(0);\n\n auto opts = x.options();\n auto convflat = torch::empty({B, Kflat}, opts);\n auto lin = torch::empty({B, D}, opts);\n auto seq = torch::empty({B, 2, D}, opts);\n auto out = torch::empty({B, NC}, opts);\n\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n int threads = 256;\n int total_conv = B * Kflat;\n conv_flat_kernel<<<(total_conv + threads - 1)/threads, threads, 0, stream>>>(\n x.data_ptr<float>(), conv_w.data_ptr<float>(), conv_b.data_ptr<float>(), convflat.data_ptr<float>(), B, C, H, W, E, P);\n dim3 grid_lp(D, B);\n linear_proj_kernel<<<grid_lp, threads, 0, stream>>>(\n convflat.data_ptr<float>(), lp_w.data_ptr<float>(), lp_b.data_ptr<float>(), lin.data_ptr<float>(), B, Kflat, D);\n int total_seq = B * 2 * D;\n init_seq_kernel<<<(total_seq + threads - 1)/threads, threads, 0, stream>>>(\n lin.data_ptr<float>(), cls.data_ptr<float>(), seq.data_ptr<float>(), B, D);\n\n for (size_t i = 0; i < in_w.size(); ++i) {\n encoder_layer_kernel<<<B, threads, 0, stream>>>(\n seq.data_ptr<float>(),\n in_w[i].data_ptr<float>(), in_b[i].data_ptr<float>(),\n out_w[i].data_ptr<float>(), out_b[i].data_ptr<float>(),\n n1_w[i].data_ptr<float>(), n1_b[i].data_ptr<float>(),\n l1_w[i].data_ptr<float>(), l1_b[i].data_ptr<float>(),\n l2_w[i].data_ptr<float>(), l2_b[i].data_ptr<float>(),\n n2_w[i].data_ptr<float>(), n2_b[i].data_ptr<float>(),\n D, FF, (int)num_heads);\n }\n fc_kernel<<<B, threads, 0, stream>>>(seq.data_ptr<float>(), fc_w.data_ptr<float>(), fc_b.data_ptr<float>(), out.data_ptr<float>(), B, D, NC);\n return out;\n}\n'''\n\n_ext = load_inline(\n name='cvit_fused_ext_v1',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['cvit_forward'],\n extra_cflags=['-O3'],\n extra_cuda_cflags=['-O3'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, num_classes, embed_dim=512, num_heads=8, num_layers=6,\n mlp_ratio=4.0, patch_size=4, in_channels=3, image_size=32):\n super(ModelNew, self).__init__()\n self.patch_size = patch_size\n self.image_size = image_size\n self.embed_dim = embed_dim\n self.num_heads = num_heads\n self.conv1 = nn.Conv2d(in_channels, embed_dim, kernel_size=patch_size, stride=patch_size)\n num_patches = (image_size // patch_size) ** 2\n self.linear_proj = nn.Linear(embed_dim * num_patches, embed_dim)\n self.transformer_layers = nn.ModuleList([\n nn.TransformerEncoderLayer(\n d_model=embed_dim,\n nhead=num_heads,\n dim_feedforward=int(embed_dim * mlp_ratio),\n dropout=0.0,\n batch_first=True\n ) for _ in range(num_layers)\n ])\n self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim))\n self.fc_out = nn.Linear(embed_dim, num_classes)\n\n def forward(self, x):\n layers = self.transformer_layers\n return _ext.cvit_forward(\n x.contiguous(),\n self.conv1.weight, self.conv1.bias,\n self.linear_proj.weight, self.linear_proj.bias,\n self.cls_token,\n [l.self_attn.in_proj_weight for l in layers],\n [l.self_attn.in_proj_bias for l in layers],\n [l.self_attn.out_proj.weight for l in layers],\n [l.self_attn.out_proj.bias for l in layers],\n [l.norm1.weight for l in layers],\n [l.norm1.bias for l in layers],\n [l.linear1.weight for l in layers],\n [l.linear1.bias for l in layers],\n [l.linear2.weight for l in layers],\n [l.linear2.bias for l in layers],\n [l.norm2.weight for l in layers],\n [l.norm2.bias for l in layers],\n self.fc_out.weight, self.fc_out.bias,\n int(self.num_heads)\n )\n"
}