call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_src = r'''\n#include <torch/extension.h>\ntorch::Tensor fused_forward(torch::Tensor x, torch::Tensor w, torch::Tensor conv_b, torch::Tensor gn_w, torch::Tensor gn_b, double eps, int64_t num_groups);\n'''\n\ncuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be CUDA\")\n#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x \" must be contiguous\")\n\n__device__ __forceinline__ float hswish_f(float v) {\n if (v <= -3.0f) return 0.0f;\n if (v >= 3.0f) return v;\n return v * (v + 3.0f) * 0.16666666666666666f;\n}\n\n__global__ __launch_bounds__(256, 2) void group4_kernel(\n const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n const float* __restrict__ gn_w,\n const float* __restrict__ gn_b,\n float* __restrict__ out,\n int B, int D, int H, int Wd, int Do, int Ho, int Wo, int groups, int has_bias, float eps)\n{\n int bg = blockIdx.x;\n int b = bg / groups;\n int g = bg - b * groups;\n int cbase = g * 4;\n int tid = threadIdx.x;\n int S = Do * Ho * Wo;\n\n extern __shared__ float smem[];\n float* sw = smem; // 192*4 weights, layout p*4+oc\n float* rs = sw + 192*4; // 8*256 reduction\n float* rq = rs + 4*256;\n\n for (int i = tid; i < 192*4; i += blockDim.x) {\n int p = i >> 2;\n int oc = i & 3;\n sw[i] = w[(cbase + oc) * 192 + p];\n }\n __syncthreads();\n\n float s0=0.0f, s1=0.0f, s2=0.0f, s3=0.0f;\n float q0=0.0f, q1=0.0f, q2=0.0f, q3=0.0f;\n float b0=0.0f, b1=0.0f, b2=0.0f, b3=0.0f;\n if (has_bias) { b0=bias[cbase]; b1=bias[cbase+1]; b2=bias[cbase+2]; b3=bias[cbase+3]; }\n\n for (int idx = tid; idx < S; idx += blockDim.x) {\n int t = idx;\n int ow = t % Wo; t /= Wo;\n int oh = t % Ho;\n int od = t / Ho;\n float a0=b0, a1=b1, a2=b2, a3=b3;\n #pragma unroll\n for (int ci=0; ci<3; ++ci) {\n #pragma unroll\n for (int kd=0; kd<4; ++kd) {\n int id = od + kd;\n #pragma unroll\n for (int kh=0; kh<4; ++kh) {\n int ih = oh + kh;\n int xbase = (((b*3 + ci) * D + id) * H + ih) * Wd + ow;\n int pbase = ci*64 + kd*16 + kh*4;\n #pragma unroll\n for (int kw=0; kw<4; ++kw) {\n float xv = x[xbase + kw];\n int pp = (pbase + kw) * 4;\n a0 = fmaf(xv, sw[pp+0], a0);\n a1 = fmaf(xv, sw[pp+1], a1);\n a2 = fmaf(xv, sw[pp+2], a2);\n a3 = fmaf(xv, sw[pp+3], a3);\n }\n }\n }\n }\n float y0=hswish_f(a0), y1=hswish_f(a1), y2=hswish_f(a2), y3=hswish_f(a3);\n s0 += y0; s1 += y1; s2 += y2; s3 += y3;\n q0 = fmaf(y0,y0,q0); q1 = fmaf(y1,y1,q1); q2 = fmaf(y2,y2,q2); q3 = fmaf(y3,y3,q3);\n }\n\n rs[tid] = s0; rs[256+tid]=s1; rs[512+tid]=s2; rs[768+tid]=s3;\n rq[tid] = q0; rq[256+tid]=q1; rq[512+tid]=q2; rq[768+tid]=q3;\n __syncthreads();\n for (int stride=128; stride>0; stride >>= 1) {\n if (tid < stride) {\n rs[tid]+=rs[tid+stride]; rs[256+tid]+=rs[256+tid+stride]; rs[512+tid]+=rs[512+tid+stride]; rs[768+tid]+=rs[768+tid+stride];\n rq[tid]+=rq[tid+stride]; rq[256+tid]+=rq[256+tid+stride]; rq[512+tid]+=rq[512+tid+stride]; rq[768+tid]+=rq[768+tid+stride];\n }\n __syncthreads();\n }\n if (tid == 0) {\n float sum0=rs[0], sum1=rs[256], sum2=rs[512], sum3=rs[768];\n float sq0=rq[0], sq1=rq[256], sq2=rq[512], sq3=rq[768];\n float invS = 1.0f / (float)S;\n float mean = (sum0+sum1+sum2+sum3) * (0.25f * invS);\n float var = (sq0+sq1+sq2+sq3) * (0.25f * invS) - mean*mean;\n var = fmaxf(var, 0.0f);\n float inv = rsqrtf(var + eps);\n int ob = b * (groups*4) + cbase;\n out[ob+0] = ((sum0*invS - mean) * inv) * gn_w[cbase+0] + gn_b[cbase+0];\n out[ob+1] = ((sum1*invS - mean) * inv) * gn_w[cbase+1] + gn_b[cbase+1];\n out[ob+2] = ((sum2*invS - mean) * inv) * gn_w[cbase+2] + gn_b[cbase+2];\n out[ob+3] = ((sum3*invS - mean) * inv) * gn_w[cbase+3] + gn_b[cbase+3];\n }\n}\n\ntorch::Tensor fused_forward(torch::Tensor x, torch::Tensor w, torch::Tensor conv_b, torch::Tensor gn_w, torch::Tensor gn_b, double eps, int64_t num_groups) {\n CHECK_CUDA(x); CHECK_CUDA(w); CHECK_CUDA(gn_w); CHECK_CUDA(gn_b);\n CHECK_CONTIGUOUS(x); CHECK_CONTIGUOUS(w); CHECK_CONTIGUOUS(gn_w); CHECK_CONTIGUOUS(gn_b);\n int B=x.size(0), D=x.size(2), H=x.size(3), Wd=x.size(4);\n int K=w.size(2); TORCH_CHECK(x.size(1)==3 && K==4 && w.size(0)==(num_groups*4), \"specialized for Cin=3,K=4,group size 4\");\n int Do=D-3, Ho=H-3, Wo=Wd-3;\n auto out=torch::empty({B, w.size(0)}, x.options());\n int has_bias = conv_b.numel() > 0;\n const float* bp = has_bias ? conv_b.data_ptr<float>() : nullptr;\n size_t shmem = (192*4 + 8*256) * sizeof(float);\n group4_kernel<<<B*(int)num_groups, 256, shmem>>>(x.data_ptr<float>(), w.data_ptr<float>(), bp, gn_w.data_ptr<float>(), gn_b.data_ptr<float>(), out.data_ptr<float>(), B, D, H, Wd, Do, Ho, Wo, (int)num_groups, has_bias, (float)eps);\n return out;\n}\n'''\n\n_ext = load_inline(name='fused_conv3d_hswish_gn_mean_ext_v2', cpp_sources=cpp_src, cuda_sources=cuda_src, functions=['fused_forward'], extra_cuda_cflags=['-O3', '--use_fast_math'], extra_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_channels, out_channels, kernel_size, num_groups=4, bias=True):\n super(ModelNew, self).__init__()\n self.conv = nn.Conv3d(in_channels, out_channels, kernel_size, bias=bias)\n self.group_norm = nn.GroupNorm(num_groups, out_channels)\n def forward(self, x):\n b = self.conv.bias\n if b is None:\n b = torch.empty(0, device=x.device, dtype=x.dtype)\n return _ext.fused_forward(x.contiguous(), self.conv.weight.contiguous(), b.contiguous(), self.group_norm.weight.contiguous(), self.group_norm.bias.contiguous(), float(self.group_norm.eps), int(self.group_norm.num_groups))\n"
}