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 fused_forward(torch::Tensor input, torch::Tensor weight, torch::Tensor bias,\n torch::Tensor bn_weight, torch::Tensor bn_bias,\n torch::Tensor running_mean, torch::Tensor running_var, torch::Tensor scale,\n bool training, double eps, double momentum);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/ATen.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#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be CUDA\")\n#define CHECK_FLOAT(x) TORCH_CHECK(x.scalar_type()==at::kFloat, #x \" must be float\")\n\n__global__ void partial_stats_kernel(const float* __restrict__ y, float* __restrict__ psum, float* __restrict__ psum2,\n int M, int N, int groups) {\n int tx = threadIdx.x; // 0..31 feature within tile\n int ty = threadIdx.y; // 0..7 row lane\n int c = blockIdx.x * 32 + tx;\n int g = blockIdx.y;\n int r0 = g * 256;\n int r1 = min(r0 + 256, M);\n float s = 0.0f, s2 = 0.0f;\n if (c < N) {\n for (int r = r0 + ty; r < r1; r += 8) {\n float v = y[(long long)r * N + c];\n s += v; s2 += v * v;\n }\n }\n __shared__ float sh[8][32];\n __shared__ float sh2[8][32];\n sh[ty][tx] = s; sh2[ty][tx] = s2;\n __syncthreads();\n if (ty == 0 && c < N) {\n float a = sh[0][tx] + sh[1][tx] + sh[2][tx] + sh[3][tx] + sh[4][tx] + sh[5][tx] + sh[6][tx] + sh[7][tx];\n float b = sh2[0][tx] + sh2[1][tx] + sh2[2][tx] + sh2[3][tx] + sh2[4][tx] + sh2[5][tx] + sh2[6][tx] + sh2[7][tx];\n psum[(long long)g * N + c] = a;\n psum2[(long long)g * N + c] = b;\n }\n}\n\n__global__ void finalize_stats_kernel(const float* __restrict__ psum, const float* __restrict__ psum2,\n float* __restrict__ mean, float* __restrict__ invstd,\n float* __restrict__ running_mean, float* __restrict__ running_var,\n int M, int N, int groups, float eps, float momentum) {\n int c = blockIdx.x * blockDim.x + threadIdx.x;\n if (c < N) {\n float s = 0.0f, s2 = 0.0f;\n for (int g = 0; g < groups; ++g) { s += psum[(long long)g*N+c]; s2 += psum2[(long long)g*N+c]; }\n float m = s / (float)M;\n float var = s2 / (float)M - m*m;\n if (var < 0.0f) var = 0.0f;\n float inv = rsqrtf(var + eps);\n mean[c] = m; invstd[c] = inv;\n float var_unbiased = var * ((float)M / (float)(M - 1));\n running_mean[c] = (1.0f - momentum) * running_mean[c] + momentum * m;\n running_var[c] = (1.0f - momentum) * running_var[c] + momentum * var_unbiased;\n }\n}\n\n__global__ void bn_softmax_train_kernel(const float* __restrict__ y, const float* __restrict__ mean, const float* __restrict__ invstd,\n const float* __restrict__ bn_w, const float* __restrict__ bn_b, const float* __restrict__ scale,\n float* __restrict__ out, int M, int N) {\n int row = blockIdx.x, tid = threadIdx.x; float sc = scale[0];\n float vmax = -FLT_MAX;\n for (int c = tid; c < N; c += blockDim.x) {\n float v = (y[(long long)row*N+c] - mean[c]) * invstd[c];\n v = (v * bn_w[c] + bn_b[c]) * sc; vmax = fmaxf(vmax, v);\n }\n __shared__ float sh[256]; sh[tid]=vmax; __syncthreads();\n for(int s=128;s>0;s>>=1){ if(tid<s) sh[tid]=fmaxf(sh[tid],sh[tid+s]); __syncthreads(); }\n float m=sh[0], sum=0.0f;\n for (int c = tid; c < N; c += blockDim.x) {\n float v = (y[(long long)row*N+c] - mean[c]) * invstd[c];\n v = (v * bn_w[c] + bn_b[c]) * sc; sum += __expf(v-m);\n }\n sh[tid]=sum; __syncthreads();\n for(int s=128;s>0;s>>=1){ if(tid<s) sh[tid]+=sh[tid+s]; __syncthreads(); }\n float invs=1.0f/sh[0];\n for (int c = tid; c < N; c += blockDim.x) {\n float v = (y[(long long)row*N+c] - mean[c]) * invstd[c];\n v = (v * bn_w[c] + bn_b[c]) * sc; out[(long long)row*N+c] = __expf(v-m)*invs;\n }\n}\n\n__global__ void bn_softmax_eval_kernel(const float* __restrict__ y, const float* __restrict__ rm, const float* __restrict__ rv,\n const float* __restrict__ bn_w, const float* __restrict__ bn_b, const float* __restrict__ scale,\n float* __restrict__ out, int M, int N, float eps) {\n int row = blockIdx.x, tid = threadIdx.x; float sc = scale[0];\n float vmax = -FLT_MAX;\n for (int c = tid; c < N; c += blockDim.x) {\n float v = (y[(long long)row*N+c] - rm[c]) * rsqrtf(rv[c] + eps);\n v = (v * bn_w[c] + bn_b[c]) * sc; vmax = fmaxf(vmax, v);\n }\n __shared__ float sh[256]; sh[tid]=vmax; __syncthreads();\n for(int s=128;s>0;s>>=1){ if(tid<s) sh[tid]=fmaxf(sh[tid],sh[tid+s]); __syncthreads(); }\n float m=sh[0], sum=0.0f;\n for (int c = tid; c < N; c += blockDim.x) {\n float v = (y[(long long)row*N+c] - rm[c]) * rsqrtf(rv[c] + eps);\n v = (v * bn_w[c] + bn_b[c]) * sc; sum += __expf(v-m);\n }\n sh[tid]=sum; __syncthreads();\n for(int s=128;s>0;s>>=1){ if(tid<s) sh[tid]+=sh[tid+s]; __syncthreads(); }\n float invs=1.0f/sh[0];\n for (int c = tid; c < N; c += blockDim.x) {\n float v = (y[(long long)row*N+c] - rm[c]) * rsqrtf(rv[c] + eps);\n v = (v * bn_w[c] + bn_b[c]) * sc; out[(long long)row*N+c] = __expf(v-m)*invs;\n }\n}\n\ntorch::Tensor fused_forward(torch::Tensor input, torch::Tensor weight, torch::Tensor bias,\n torch::Tensor bn_weight, torch::Tensor bn_bias,\n torch::Tensor running_mean, torch::Tensor running_var, torch::Tensor scale,\n bool training, double eps, double momentum) {\n CHECK_CUDA(input); CHECK_FLOAT(input);\n const at::cuda::OptionalCUDAGuard device_guard(device_of(input));\n auto y = at::linear(input, weight, bias);\n int M=(int)y.size(0), N=(int)y.size(1); auto out=torch::empty_like(y);\n cudaStream_t stream=at::cuda::getCurrentCUDAStream(); const int threads=256;\n if(training){\n int groups=(M+255)/256; auto opts=y.options(); auto mean=torch::empty({N},opts); auto invstd=torch::empty({N},opts);\n auto psum=torch::empty({groups,N},opts); auto psum2=torch::empty({groups,N},opts);\n dim3 block(32,8); dim3 grid((N+31)/32, groups);\n partial_stats_kernel<<<grid, block, 0, stream>>>(y.data_ptr<float>(), psum.data_ptr<float>(), psum2.data_ptr<float>(), M,N,groups);\n finalize_stats_kernel<<<(N+255)/256,256,0,stream>>>(psum.data_ptr<float>(), psum2.data_ptr<float>(), mean.data_ptr<float>(), invstd.data_ptr<float>(), running_mean.data_ptr<float>(), running_var.data_ptr<float>(), M,N,groups,(float)eps,(float)momentum);\n bn_softmax_train_kernel<<<M,threads,0,stream>>>(y.data_ptr<float>(), mean.data_ptr<float>(), invstd.data_ptr<float>(), bn_weight.data_ptr<float>(), bn_bias.data_ptr<float>(), scale.data_ptr<float>(), out.data_ptr<float>(), M,N);\n } else {\n bn_softmax_eval_kernel<<<M,threads,0,stream>>>(y.data_ptr<float>(), running_mean.data_ptr<float>(), running_var.data_ptr<float>(), bn_weight.data_ptr<float>(), bn_bias.data_ptr<float>(), scale.data_ptr<float>(), out.data_ptr<float>(), M,N,(float)eps);\n }\n C10_CUDA_KERNEL_LAUNCH_CHECK(); return out;\n}\n'''\n\n_ext = load_inline(name='gemm_bn_scale_softmax_ext_v2', cpp_sources=[_cpp_src], cuda_sources=[_cuda_src], functions=['fused_forward'], extra_cuda_cflags=['-O3'], extra_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, bn_eps=1e-5, bn_momentum=0.1, scale_shape=(1,)):\n super(ModelNew,self).__init__(); self.gemm=nn.Linear(in_features,out_features); self.bn=nn.BatchNorm1d(out_features,eps=bn_eps,momentum=bn_momentum); self.scale=nn.Parameter(torch.ones(scale_shape))\n def forward(self,x):\n return _ext.fused_forward(x,self.gemm.weight,self.gemm.bias,self.bn.weight,self.bn.bias,self.bn.running_mean,self.bn.running_var,self.scale,self.training,self.bn.eps,self.bn.momentum)\n"
}