call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_sources = r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor fused_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, torch::Tensor mult, double clamp_min, double clamp_max);\n\"\"\"\n\ncuda_sources = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAGuard.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <float.h>\n\n#ifndef CHECK_CUDA\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be a CUDA tensor\")\n#endif\n\n__global__ void conv_sum_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ b,\n const float* __restrict__ m,\n float* __restrict__ mean,\n float* __restrict__ invstd,\n int N, int Ci, int D, int H, int W,\n int Co, int K, int Do, int Ho, int Wo) {\n int nc = blockIdx.x;\n int n = nc / Co;\n int co = nc - n * Co;\n int S = Do * Ho * Wo;\n float mult = m[co];\n float local_sum = 0.0f;\n float local_sumsq = 0.0f;\n for (int idx = threadIdx.x; idx < S; idx += blockDim.x) {\n int t = idx;\n int ow = t % Wo; t /= Wo;\n int oh = t % Ho; int od = t / Ho;\n float acc = b[co];\n #pragma unroll\n for (int ci = 0; ci < 3; ++ci) {\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 #pragma unroll\n for (int kw = 0; kw < 3; ++kw) {\n int iw = ow + kw;\n float xv = x[(((n * Ci + ci) * D + id) * H + ih) * W + iw];\n float ww = w[((((co * Ci + ci) * K + kd) * K + kh) * K + kw)];\n acc = fmaf(xv, ww, acc);\n }\n }\n }\n }\n float y = acc * mult;\n local_sum += y;\n local_sumsq = fmaf(y, y, local_sumsq);\n }\n __shared__ float ssum[256];\n __shared__ float ssq[256];\n ssum[threadIdx.x] = local_sum;\n ssq[threadIdx.x] = local_sumsq;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (threadIdx.x < stride) {\n ssum[threadIdx.x] += ssum[threadIdx.x + stride];\n ssq[threadIdx.x] += ssq[threadIdx.x + stride];\n }\n __syncthreads();\n }\n if (threadIdx.x == 0) {\n float mu = ssum[0] / (float)S;\n float var = ssq[0] / (float)S - mu * mu;\n if (var < 0.0f) var = 0.0f;\n mean[nc] = mu;\n invstd[nc] = rsqrtf(var + 1.0e-5f);\n }\n}\n\n__global__ void final_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ b,\n const float* __restrict__ m,\n const float* __restrict__ mean,\n const float* __restrict__ invstd,\n float* __restrict__ out,\n int N, int Ci, int D, int H, int W,\n int Co, int K, int Do, int Ho, int Wo,\n float clamp_min, float clamp_max) {\n int S = Do * Ho * Wo;\n int total = N * S;\n int g = blockIdx.x * blockDim.x + threadIdx.x;\n if (g >= total) return;\n int n = g / S;\n int idx = g - n * S;\n int t = idx;\n int ow = t % Wo; t /= Wo;\n int oh = t % Ho; int od = t / Ho;\n\n float acc[16];\n #pragma unroll\n for (int co = 0; co < 16; ++co) acc[co] = b[co];\n\n #pragma unroll\n for (int ci = 0; ci < 3; ++ci) {\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 #pragma unroll\n for (int kw = 0; kw < 3; ++kw) {\n int iw = ow + kw;\n float xv = x[(((n * Ci + ci) * D + id) * H + ih) * W + iw];\n int base = (((ci * K + kd) * K + kh) * K + kw);\n #pragma unroll\n for (int co = 0; co < 16; ++co) {\n float ww = w[co * (Ci*K*K*K) + base];\n acc[co] = fmaf(xv, ww, acc[co]);\n }\n }\n }\n }\n }\n float best = -FLT_MAX;\n #pragma unroll\n for (int co = 0; co < 16; ++co) {\n float mult = m[co];\n float y = acc[co] * mult;\n float z = (y - mean[n * Co + co]) * invstd[n * Co + co];\n z = fminf(fmaxf(z, clamp_min), clamp_max);\n float v = z * mult;\n best = fmaxf(best, v);\n }\n out[g] = best;\n}\n\ntorch::Tensor fused_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, torch::Tensor mult, double clamp_min_d, double clamp_max_d) {\n CHECK_CUDA(x); CHECK_CUDA(weight); CHECK_CUDA(bias); CHECK_CUDA(mult);\n const at::cuda::OptionalCUDAGuard device_guard(device_of(x));\n TORCH_CHECK(x.scalar_type() == at::kFloat, \"only float32 supported\");\n auto xc = x.contiguous();\n auto wc = weight.contiguous();\n auto bc = bias.contiguous();\n auto mc = mult.contiguous();\n int N = (int)xc.size(0);\n int Ci = (int)xc.size(1);\n int D = (int)xc.size(2);\n int H = (int)xc.size(3);\n int W = (int)xc.size(4);\n int Co = (int)wc.size(0);\n int K = (int)wc.size(2);\n int Do = D - K + 1;\n int Ho = H - K + 1;\n int Wo = W - K + 1;\n TORCH_CHECK(Ci == 3 && Co == 16 && K == 3, \"specialized for Ci=3 Co=16 K=3\");\n auto opts = xc.options();\n auto mean = torch::empty({N, Co}, opts);\n auto invstd = torch::empty({N, Co}, opts);\n auto out = torch::empty({N, Do, Ho, Wo}, opts);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n conv_sum_kernel<<<N * Co, 256, 0, stream>>>(\n xc.data_ptr<float>(), wc.data_ptr<float>(), bc.data_ptr<float>(), mc.data_ptr<float>(),\n mean.data_ptr<float>(), invstd.data_ptr<float>(), N, Ci, D, H, W, Co, K, Do, Ho, Wo);\n int total = N * Do * Ho * Wo;\n final_kernel<<<(total + 255) / 256, 256, 0, stream>>>(\n xc.data_ptr<float>(), wc.data_ptr<float>(), bc.data_ptr<float>(), mc.data_ptr<float>(),\n mean.data_ptr<float>(), invstd.data_ptr<float>(), out.data_ptr<float>(),\n N, Ci, D, H, W, Co, K, Do, Ho, Wo, (float)clamp_min_d, (float)clamp_max_d);\n return out;\n}\n\"\"\"\n\n_ext = load_inline(name=\"fused_conv_inorm_max_ext_v1\", cpp_sources=cpp_sources, cuda_sources=cuda_sources,\n functions=[\"fused_forward\"], extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_channels, out_channels, kernel_size, multiplier_shape, clamp_min, clamp_max):\n super(ModelNew, self).__init__()\n self.conv = nn.Conv3d(in_channels, out_channels, kernel_size)\n self.multiplier = nn.Parameter(torch.randn(multiplier_shape))\n self.instance_norm = nn.InstanceNorm3d(out_channels)\n self.clamp_min = clamp_min\n self.clamp_max = clamp_max\n def forward(self, x):\n return _ext.fused_forward(x, self.conv.weight, self.conv.bias, self.multiplier, float(self.clamp_min), float(self.clamp_max))\n"
}