call → compile_kernel
callcompile_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>\ntorch::Tensor conv_gn_mean_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, torch::Tensor gamma, torch::Tensor beta);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAGuard.h>\n\n#define BLOCK 256\n#define ITEMS 4\n#define CIN 3\n#define D_IN 24\n#define H_IN 32\n#define W_IN 32\n#define DO 22\n#define HO 30\n#define WO 30\n#define SPATIAL 19800\n#define GROUPS 8\n#define TILES 20\n\n__device__ __forceinline__ void calc_one(const float* __restrict__ x, const float* __restrict__ w, const float* __restrict__ b,\n int n, int g, int idx,\n float &s0, float &s1, float &s2, float &q0, float &q1, float &q2) {\n int ow = idx % WO;\n int tt = idx / WO;\n int oh = tt % HO;\n int od = tt / HO;\n int c0 = g * 3;\n float z0 = b[c0];\n float z1 = b[c0+1];\n float z2 = b[c0+2];\n #pragma unroll\n for (int ic=0; ic<3; ++ic) {\n #pragma unroll\n for (int kd=0; kd<3; ++kd) {\n int id = od + kd;\n #pragma unroll\n for (int kh=0; kh<3; ++kh) {\n int ih = oh + kh;\n int base_x = (((n*3 + ic)*D_IN + id)*H_IN + ih)*W_IN + ow;\n int bw = (((c0*3 + ic)*3 + kd)*3 + kh)*3;\n float xv0 = x[base_x];\n float xv1 = x[base_x + 1];\n float xv2 = x[base_x + 2];\n float w00 = w[bw], w01 = w[bw+1], w02 = w[bw+2];\n float w10 = w[bw+81], w11 = w[bw+82], w12 = w[bw+83];\n float w20 = w[bw+162], w21 = w[bw+163], w22 = w[bw+164];\n z0 = fmaf(xv0, w00, z0); z1 = fmaf(xv0, w10, z1); z2 = fmaf(xv0, w20, z2);\n z0 = fmaf(xv1, w01, z0); z1 = fmaf(xv1, w11, z1); z2 = fmaf(xv1, w21, z2);\n z0 = fmaf(xv2, w02, z0); z1 = fmaf(xv2, w12, z1); z2 = fmaf(xv2, w22, z2);\n }\n }\n }\n s0 += z0; s1 += z1; s2 += z2;\n q0 = fmaf(z0, z0, q0); q1 = fmaf(z1, z1, q1); q2 = fmaf(z2, z2, q2);\n}\n\n__device__ __forceinline__ float warp_sum(float v) {\n #pragma unroll\n for (int off=16; off>0; off>>=1) v += __shfl_down_sync(0xffffffff, v, off);\n return v;\n}\n\n__global__ void conv_partial_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ b,\n float* __restrict__ partial) {\n int tile = blockIdx.x;\n int g = blockIdx.y;\n int n = blockIdx.z;\n int tid = threadIdx.x;\n float s0=0.f, s1=0.f, s2=0.f, q0=0.f, q1=0.f, q2=0.f;\n int base = tile * (BLOCK*ITEMS) + tid;\n #pragma unroll\n for (int it=0; it<ITEMS; ++it) {\n int idx = base + it*BLOCK;\n if (idx < SPATIAL) calc_one(x,w,b,n,g,idx,s0,s1,s2,q0,q1,q2);\n }\n s0=warp_sum(s0); s1=warp_sum(s1); s2=warp_sum(s2); q0=warp_sum(q0); q1=warp_sum(q1); q2=warp_sum(q2);\n __shared__ float sh[6][8];\n int lane = tid & 31;\n int warp = tid >> 5;\n if (lane == 0) { sh[0][warp]=s0; sh[1][warp]=s1; sh[2][warp]=s2; sh[3][warp]=q0; sh[4][warp]=q1; sh[5][warp]=q2; }\n __syncthreads();\n if (warp == 0) {\n float v0 = (lane < 8) ? sh[0][lane] : 0.f;\n float v1 = (lane < 8) ? sh[1][lane] : 0.f;\n float v2 = (lane < 8) ? sh[2][lane] : 0.f;\n float v3 = (lane < 8) ? sh[3][lane] : 0.f;\n float v4 = (lane < 8) ? sh[4][lane] : 0.f;\n float v5 = (lane < 8) ? sh[5][lane] : 0.f;\n v0=warp_sum(v0); v1=warp_sum(v1); v2=warp_sum(v2); v3=warp_sum(v3); v4=warp_sum(v4); v5=warp_sum(v5);\n if (lane == 0) {\n long long off = (((long long)n * GROUPS + g) * TILES + tile) * 6;\n partial[off+0] = v0; partial[off+1] = v1; partial[off+2] = v2;\n partial[off+3] = v3; partial[off+4] = v4; partial[off+5] = v5;\n }\n }\n}\n\n__global__ void final_kernel(const float* __restrict__ partial,\n const float* __restrict__ gamma,\n const float* __restrict__ beta,\n float* __restrict__ out) {\n int n = blockIdx.x;\n if (threadIdx.x != 0) return;\n float total = 0.f;\n const float inv_group_elems = 1.0f / (3.0f * SPATIAL);\n #pragma unroll\n for (int g=0; g<GROUPS; ++g) {\n float s0=0.f,s1=0.f,s2=0.f,q0=0.f,q1=0.f,q2=0.f;\n #pragma unroll\n for (int tile=0; tile<TILES; ++tile) {\n long long off = (((long long)n * GROUPS + g) * TILES + tile) * 6;\n s0 += partial[off+0]; s1 += partial[off+1]; s2 += partial[off+2];\n q0 += partial[off+3]; q1 += partial[off+4]; q2 += partial[off+5];\n }\n int c = g*3;\n float S = s0+s1+s2;\n float Q = q0+q1+q2;\n float mean = S * inv_group_elems;\n float var = Q * inv_group_elems - mean * mean;\n if (var < 0.f) var = 0.f;\n float invstd = rsqrtf(var + 1.0e-5f);\n float gz = gamma[c]*s0 + gamma[c+1]*s1 + gamma[c+2]*s2;\n float gsum = (gamma[c] + gamma[c+1] + gamma[c+2]) * (float)SPATIAL;\n float bsum = (beta[c] + beta[c+1] + beta[c+2]) * (float)SPATIAL;\n total += invstd * (gz - mean * gsum) + bsum;\n }\n out[n] = total * (1.0f / (24.0f * SPATIAL));\n}\n\ntorch::Tensor conv_gn_mean_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, torch::Tensor gamma, torch::Tensor beta) {\n c10::cuda::CUDAGuard device_guard(x.device());\n int N = x.size(0);\n auto opts = x.options();\n auto partial = torch::empty({N, GROUPS, TILES, 6}, opts);\n auto out = torch::empty({N}, opts);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n dim3 grid(TILES, GROUPS, N);\n conv_partial_kernel<<<grid, BLOCK, 0, stream>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), partial.data_ptr<float>());\n final_kernel<<<N, 1, 0, stream>>>(partial.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>());\n return out;\n}\n\"\"\"\n\n_ext = load_inline(name=\"conv_gn_mean_ext_v2\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"conv_gn_mean_forward\"], extra_cflags=[\"-O3\"], extra_cuda_cflags=[\"-O3\"], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_channels, out_channels, kernel_size, num_groups):\n super(ModelNew, self).__init__()\n self.conv = nn.Conv3d(in_channels, out_channels, kernel_size)\n self.group_norm = nn.GroupNorm(num_groups, out_channels)\n def forward(self, x):\n return _ext.conv_gn_mean_forward(x.contiguous(), self.conv.weight.contiguous(), self.conv.bias.contiguous(), self.group_norm.weight.contiguous(), self.group_norm.bias.contiguous())\n"
}