call → profile_kernel
callprofile_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>\n\ntorch::Tensor bn_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias,\n torch::Tensor running_mean, torch::Tensor running_var,\n bool training, double momentum, double eps);\n'''\n\ncuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <ATen/cuda/CUDAContext.h>\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be a CUDA tensor\")\nstatic constexpr int THREADS = 256;\nstatic constexpr int PARTS = 256;\n__inline__ __device__ float warp_sum(float v){for(int o=16;o>0;o>>=1)v+=__shfl_down_sync(0xffffffff,v,o);return v;}\n__global__ void partial_sum_kernel(const float* __restrict__ x,float* __restrict__ sums,float* __restrict__ sqs,int N,int C,int HW,int64_t M){int c=blockIdx.x,p=blockIdx.y,tid=threadIdx.x;int64_t chunk=(M+PARTS-1)/PARTS,start=(int64_t)p*chunk,end=start+chunk;if(end>M)end=M;float s=0.f,q=0.f;for(int64_t i=start+tid;i<end;i+=blockDim.x){int64_t n=i/HW;int hw=(int)(i-n*(int64_t)HW);float v=x[((n*C+c)*(int64_t)HW)+hw];s+=v;q=fmaf(v,v,q);}s=warp_sum(s);q=warp_sum(q);__shared__ float ss[32],qq[32];int lane=tid&31,warp=tid>>5;if(lane==0){ss[warp]=s;qq[warp]=q;}__syncthreads();if(warp==0){s=(lane<(blockDim.x>>5))?ss[lane]:0.f;q=(lane<(blockDim.x>>5))?qq[lane]:0.f;s=warp_sum(s);q=warp_sum(q);if(lane==0){int idx=c*PARTS+p;sums[idx]=s;sqs[idx]=q;}}}\n__global__ void stats_kernel(const float* __restrict__ sums,const float* __restrict__ sqs,const float* __restrict__ weight,const float* __restrict__ bias,float* __restrict__ running_mean,float* __restrict__ running_var,float* __restrict__ scale,float* __restrict__ shift,int C,int64_t M,float momentum,float eps,bool update_running){int c=blockIdx.x,tid=threadIdx.x;float s=0.f,q=0.f;for(int p=tid;p<PARTS;p+=blockDim.x){int idx=c*PARTS+p;s+=sums[idx];q+=sqs[idx];}s=warp_sum(s);q=warp_sum(q);__shared__ float ss[32],qq[32];int lane=tid&31,warp=tid>>5;if(lane==0){ss[warp]=s;qq[warp]=q;}__syncthreads();if(warp==0){s=(lane<(blockDim.x>>5))?ss[lane]:0.f;q=(lane<(blockDim.x>>5))?qq[lane]:0.f;s=warp_sum(s);q=warp_sum(q);if(lane==0){float mean=s/(float)M;float var=fmaxf(q/(float)M-mean*mean,0.f);float inv=rsqrtf(var+eps);float w=weight[c],b=bias[c];scale[c]=w*inv;shift[c]=b-mean*w*inv;if(update_running){running_mean[c]=running_mean[c]*(1.f-momentum)+mean*momentum;float unb=var*((float)M/(float)(M-1));running_var[c]=running_var[c]*(1.f-momentum)+unb*momentum;}}}}\n__global__ void output_channel_kernel(const float* __restrict__ x,float* __restrict__ y,const float* __restrict__ scale,const float* __restrict__ shift,int N,int C,int HW,int64_t M){int c=blockIdx.x,p=blockIdx.y,tid=threadIdx.x;float a=scale[c],b=shift[c];int64_t chunk=(M+PARTS-1)/PARTS,start=(int64_t)p*chunk,end=start+chunk;if(end>M)end=M;for(int64_t i=start+tid;i<end;i+=blockDim.x){int64_t n=i/HW;int hw=(int)(i-n*(int64_t)HW);int64_t off=((n*C+c)*(int64_t)HW)+hw;y[off]=fmaf(x[off],a,b);}}\n__global__ void eval_kernel(const float* __restrict__ x,float* __restrict__ y,const float* __restrict__ weight,const float* __restrict__ bias,const float* __restrict__ running_mean,const float* __restrict__ running_var,int64_t total,int C,int HW,float eps){int64_t idx=(int64_t)blockIdx.x*blockDim.x+threadIdx.x;int64_t stride=(int64_t)blockDim.x*gridDim.x;for(;idx<total;idx+=stride){int c=(int)((idx/HW)%C);float inv=rsqrtf(running_var[c]+eps);float a=weight[c]*inv;float b=bias[c]-running_mean[c]*a;y[idx]=fmaf(x[idx],a,b);}}\ntorch::Tensor bn_forward_cuda(torch::Tensor x,torch::Tensor weight,torch::Tensor bias,torch::Tensor running_mean,torch::Tensor running_var,bool training,double momentum_d,double eps_d){CHECK_CUDA(x);TORCH_CHECK(x.scalar_type()==at::kFloat,\"only float32 supported\");TORCH_CHECK(x.dim()==4,\"expected NCHW 4D\");auto y=torch::empty_like(x);int N=(int)x.size(0),C=(int)x.size(1),HW=(int)(x.size(2)*x.size(3));int64_t M=(int64_t)N*HW;cudaStream_t stream=at::cuda::getCurrentCUDAStream();float eps=(float)eps_d;if(!training){int64_t total=x.numel();eval_kernel<<<65536,THREADS,0,stream>>>(x.data_ptr<float>(),y.data_ptr<float>(),weight.data_ptr<float>(),bias.data_ptr<float>(),running_mean.data_ptr<float>(),running_var.data_ptr<float>(),total,C,HW,eps);return y;}auto opts=x.options();auto sums=torch::empty({C,PARTS},opts);auto sqs=torch::empty({C,PARTS},opts);auto scale=torch::empty({C},opts);auto shift=torch::empty({C},opts);dim3 grid1(C,PARTS);partial_sum_kernel<<<grid1,THREADS,0,stream>>>(x.data_ptr<float>(),sums.data_ptr<float>(),sqs.data_ptr<float>(),N,C,HW,M);stats_kernel<<<C,THREADS,0,stream>>>(sums.data_ptr<float>(),sqs.data_ptr<float>(),weight.data_ptr<float>(),bias.data_ptr<float>(),running_mean.data_ptr<float>(),running_var.data_ptr<float>(),scale.data_ptr<float>(),shift.data_ptr<float>(),C,M,(float)momentum_d,eps,true);output_channel_kernel<<<grid1,THREADS,0,stream>>>(x.data_ptr<float>(),y.data_ptr<float>(),scale.data_ptr<float>(),shift.data_ptr<float>(),N,C,HW,M);return y;}\n'''\n_ext=load_inline(name='bn2d_custom_ext',cpp_sources=cpp_src,cuda_sources=cuda_src,functions=['bn_forward_cuda'],extra_cuda_cflags=['-O3'],extra_cflags=['-O3'],verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self,num_features:int):\n super(ModelNew,self).__init__(); self.bn=nn.BatchNorm2d(num_features=num_features)\n def forward(self,x:torch.Tensor)->torch.Tensor:\n if x.is_cuda and x.dtype==torch.float32 and x.dim()==4 and x.is_contiguous():\n return _ext.bn_forward_cuda(x,self.bn.weight,self.bn.bias,self.bn.running_mean,self.bn.running_var,self.bn.training,float(self.bn.momentum),float(self.bn.eps))\n return self.bn(x)\n"
}