call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n_cpp_src=r'''\n#include <torch/extension.h>\n#include <vector>\nstd::vector<torch::Tensor> prepare_avg(torch::Tensor weight, torch::Tensor bias, int64_t pool);\ntorch::Tensor fused_forward(torch::Tensor x, torch::Tensor wavg, torch::Tensor bavg, double scale);\n'''\n_cuda_src=r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cublas_v2.h>\n#include <vector>\n#include <cmath>\n__global__ void avg_weight_kernel(const float* __restrict__ w,const float* __restrict__ b,float* __restrict__ wavg,float* __restrict__ bavg,int K,int M,int pool){int idx=blockIdx.x*blockDim.x+threadIdx.x;int total=M*K;for(int t=idx;t<total;t+=blockDim.x*gridDim.x){int k=t%K,m=t/K;float s=0;int base=m*pool*K+k;#pragma unroll\nfor(int r=0;r<16;++r){if(r<pool)s+=w[base+r*K];}wavg[t]=s/(float)pool;}for(int m=idx;m<M;m+=blockDim.x*gridDim.x){float s=0;int base=m*pool;#pragma unroll\nfor(int r=0;r<16;++r){if(r<pool)s+=b[base+r];}bavg[m]=s/(float)pool;}}\n__global__ void gelu_scale_max_kernel(const float* __restrict__ y,const float* __restrict__ bavg,float* __restrict__ out,int B,int M,float scale){int row=blockIdx.x,tid=threadIdx.x;float maxv=-INFINITY;const float c=0.7071067811865475f;for(int j=tid;j<M;j+=blockDim.x){float v=y[row*M+j]+bavg[j];float g=0.5f*v*(1.0f+erff(v*c));maxv=fmaxf(maxv,g*scale);}extern __shared__ float smem[];smem[tid]=maxv;__syncthreads();for(int s=blockDim.x>>1;s>0;s>>=1){if(tid<s)smem[tid]=fmaxf(smem[tid],smem[tid+s]);__syncthreads();}if(tid==0)out[row]=smem[0];}\nstd::vector<torch::Tensor> prepare_avg(torch::Tensor weight,torch::Tensor bias,int64_t pool){int64_t O=weight.size(0),K=weight.size(1),M=O/pool;auto wavg=torch::empty({M,K},weight.options());auto bavg=torch::empty({M},bias.options());int threads=256;int blocks=(int)std::min<int64_t>(65535,(M*K+threads-1)/threads);avg_weight_kernel<<<blocks,threads>>>(weight.data_ptr<float>(),bias.data_ptr<float>(),wavg.data_ptr<float>(),bavg.data_ptr<float>(),(int)K,(int)M,(int)pool);return{wavg,bavg};}\ntorch::Tensor fused_forward(torch::Tensor x,torch::Tensor wavg,torch::Tensor bavg,double scale){int B=x.size(0),K=x.size(1),M=wavg.size(0);auto y=torch::empty({B,M},x.options());cublasHandle_t handle=at::cuda::getCurrentCUDABlasHandle();cublasSetMathMode(handle,CUBLAS_TF32_TENSOR_OP_MATH);const float alpha=1.0f,beta=0.0f;cublasSgemm(handle,CUBLAS_OP_T,CUBLAS_OP_N,M,B,K,&alpha,wavg.data_ptr<float>(),K,x.data_ptr<float>(),K,&beta,y.data_ptr<float>(),M);auto out=torch::empty({B},x.options());gelu_scale_max_kernel<<<B,256,256*sizeof(float)>>>(y.data_ptr<float>(),bavg.data_ptr<float>(),out.data_ptr<float>(),B,M,(float)scale);return out;}\n'''\n_ext=load_inline(name='matmul_avg_gelu_max_ext_tf32test2',cpp_sources=[_cpp_src],cuda_sources=[_cuda_src],functions=['prepare_avg','fused_forward'],extra_cuda_cflags=['-O3','--use_fast_math'],extra_cflags=['-O3'],verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self,in_features,out_features,pool_kernel_size,scale_factor):\n super().__init__();self.matmul=nn.Linear(in_features,out_features);self.pool_kernel_size=pool_kernel_size;self.scale_factor=scale_factor;self._wavg=None;self._bavg=None;self._w_version=None;self._b_version=None\n def forward(self,x):\n if self._wavg is None or self._w_version!=self.matmul.weight._version or self._b_version!=self.matmul.bias._version:\n self._wavg,self._bavg=_ext.prepare_avg(self.matmul.weight.contiguous(),self.matmul.bias.contiguous(),int(self.pool_kernel_size));self._w_version=self.matmul.weight._version;self._b_version=self.matmul.bias._version\n return _ext.fused_forward(x,self._wavg,self._bavg,float(self.scale_factor))\n"
}