call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\ntorch.backends.cudnn.allow_tf32 = False\ntorch.backends.cuda.matmul.allow_tf32 = False\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n_cpp=r'''\n#include <torch/extension.h>\ntorch::Tensor gru_forward(torch::Tensor x, torch::Tensor h0, torch::Tensor wih0, torch::Tensor whh0, torch::Tensor bih0, torch::Tensor bhh0, torch::Tensor wih1, torch::Tensor whh1, torch::Tensor bih1, torch::Tensor bhh1, torch::Tensor wih2, torch::Tensor whh2, torch::Tensor bih2, torch::Tensor bhh2, torch::Tensor wih3, torch::Tensor whh3, torch::Tensor bih3, torch::Tensor bhh3, torch::Tensor wih4, torch::Tensor whh4, torch::Tensor bih4, torch::Tensor bhh4, torch::Tensor wih5, torch::Tensor whh5, torch::Tensor bih5, torch::Tensor bhh5, bool batch_first);\n'''\n_cuda=r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda_runtime.h>\n#include <cooperative_groups.h>\nnamespace cg=cooperative_groups;\n#define HSIZE 256\n#define NLAYER 6\n#define TILE 16\n#define LANES 8\n#define BPER 2\n__device__ __forceinline__ float red8(float v){unsigned int g=(threadIdx.x&31)>>3; unsigned int m=0xFFu<<(g*8); v+=__shfl_down_sync(m,v,4,8); v+=__shfl_down_sync(m,v,2,8); v+=__shfl_down_sync(m,v,1,8); return v;}\n__device__ __forceinline__ float sigm(float x){return 1.f/(1.f+expf(-x));}\n__global__ void gru_kernel(const float* __restrict__ x,const float* __restrict__ h0,float* __restrict__ hn,float* __restrict__ scratch,const float* __restrict__ wih0,const float* __restrict__ whh0,const float* __restrict__ bih0,const float* __restrict__ bhh0,const float* __restrict__ wih1,const float* __restrict__ whh1,const float* __restrict__ bih1,const float* __restrict__ bhh1,const float* __restrict__ wih2,const float* __restrict__ whh2,const float* __restrict__ bih2,const float* __restrict__ bhh2,const float* __restrict__ wih3,const float* __restrict__ whh3,const float* __restrict__ bih3,const float* __restrict__ bhh3,const float* __restrict__ wih4,const float* __restrict__ whh4,const float* __restrict__ bih4,const float* __restrict__ bhh4,const float* __restrict__ wih5,const float* __restrict__ whh5,const float* __restrict__ bih5,const float* __restrict__ bhh5,int S,int B,int I,int batch_first){\n cg::grid_group grid=cg::this_grid(); int bg=blockIdx.x,tile=blockIdx.y,tid=threadIdx.x; int row_in_tile=tid/LANES,lane=tid&(LANES-1),row=tile*TILE+row_in_tile; __shared__ float sh_h[BPER][HSIZE]; __shared__ float sh_in[BPER][HSIZE];\n for(int l=0;l<NLAYER;l++) for(int bb=0;bb<BPER;bb++){int b=bg*BPER+bb; if(b<B && tid<TILE){int r=tile*TILE+tid; hn[(l*B+b)*HSIZE+r]=h0[(l*B+b)*HSIZE+r];}} grid.sync();\n const float* wihs[NLAYER]={wih0,wih1,wih2,wih3,wih4,wih5}; const float* whhs[NLAYER]={whh0,whh1,whh2,whh3,whh4,whh5}; const float* bihs[NLAYER]={bih0,bih1,bih2,bih3,bih4,bih5}; const float* bhhs[NLAYER]={bhh0,bhh1,bhh2,bhh3,bhh4,bhh5};\n for(int l=0;l<NLAYER;l++){const float* __restrict__ wih=wihs[l]; const float* __restrict__ whh=whhs[l]; const float* __restrict__ bih=bihs[l]; const float* __restrict__ bhh=bhhs[l]; int in_dim=(l==0?I:HSIZE), wb=l&1, rb=(l-1)&1;\n for(int t=0;t<S;t++){\n #pragma unroll\n for(int bb=0;bb<BPER;bb++){int b=bg*BPER+bb; if(b<B){sh_h[bb][tid]=hn[(l*B+b)*HSIZE+tid]; sh_h[bb][tid+128]=hn[(l*B+b)*HSIZE+tid+128]; if(l==0){ if(tid<I){int idx=batch_first?((b*S+t)*I+tid):((t*B+b)*I+tid); sh_in[bb][tid]=x[idx];}} else {sh_in[bb][tid]=scratch[((rb*S+t)*B+b)*HSIZE+tid]; sh_in[bb][tid+128]=scratch[((rb*S+t)*B+b)*HSIZE+tid+128];}}}\n __syncthreads(); float ar[BPER]={0.f,0.f},az[BPER]={0.f,0.f},ain[BPER]={0.f,0.f},ahn[BPER]={0.f,0.f};\n for(int k=lane;k<in_dim;k+=LANES){float wr=wih[row*in_dim+k], wz=wih[(HSIZE+row)*in_dim+k], wn=wih[(2*HSIZE+row)*in_dim+k]; #pragma unroll\n for(int bb=0;bb<BPER;bb++){float xv=sh_in[bb][k]; ar[bb]+=wr*xv; az[bb]+=wz*xv; ain[bb]+=wn*xv;}}\n for(int k=lane;k<HSIZE;k+=LANES){float wr=whh[row*HSIZE+k], wz=whh[(HSIZE+row)*HSIZE+k], wn=whh[(2*HSIZE+row)*HSIZE+k]; #pragma unroll\n for(int bb=0;bb<BPER;bb++){float hv=sh_h[bb][k]; ar[bb]+=wr*hv; az[bb]+=wz*hv; ahn[bb]+=wn*hv;}}\n #pragma unroll\n for(int bb=0;bb<BPER;bb++){ar[bb]=red8(ar[bb]); az[bb]=red8(az[bb]); ain[bb]=red8(ain[bb]); ahn[bb]=red8(ahn[bb]);}\n if(lane==0){#pragma unroll\n for(int bb=0;bb<BPER;bb++){int b=bg*BPER+bb; if(b<B){float hprev=sh_h[bb][row]; float r=sigm(ar[bb]+bih[row]+bhh[row]); float z=sigm(az[bb]+bih[HSIZE+row]+bhh[HSIZE+row]); float n=tanhf(ain[bb]+bih[2*HSIZE+row]+r*(ahn[bb]+bhh[2*HSIZE+row])); float hnew=(1.f-z)*n+z*hprev; hn[(l*B+b)*HSIZE+row]=hnew; scratch[((wb*S+t)*B+b)*HSIZE+row]=hnew;}}}\n grid.sync();\n } grid.sync();\n }}\ntorch::Tensor gru_forward(torch::Tensor x, torch::Tensor h0, torch::Tensor wih0, torch::Tensor whh0, torch::Tensor bih0, torch::Tensor bhh0, torch::Tensor wih1, torch::Tensor whh1, torch::Tensor bih1, torch::Tensor bhh1, torch::Tensor wih2, torch::Tensor whh2, torch::Tensor bih2, torch::Tensor bhh2, torch::Tensor wih3, torch::Tensor whh3, torch::Tensor bih3, torch::Tensor bhh3, torch::Tensor wih4, torch::Tensor whh4, torch::Tensor bih4, torch::Tensor bhh4, torch::Tensor wih5, torch::Tensor whh5, torch::Tensor bih5, torch::Tensor bhh5, bool batch_first){int S=(int)(batch_first?x.size(1):x.size(0));int B=(int)(batch_first?x.size(0):x.size(1));int I=(int)x.size(2);auto hn=torch::empty_like(h0);auto scratch=torch::empty({2,S,B,(int64_t)HSIZE},x.options());dim3 grid((B+BPER-1)/BPER,HSIZE/TILE),block(TILE*LANES);const float*xp=x.data_ptr<float>(),*h0p=h0.data_ptr<float>();float*hnp=hn.data_ptr<float>(),*sp=scratch.data_ptr<float>();const float*p_wih0=wih0.data_ptr<float>(),*p_whh0=whh0.data_ptr<float>(),*p_bih0=bih0.data_ptr<float>(),*p_bhh0=bhh0.data_ptr<float>(),*p_wih1=wih1.data_ptr<float>(),*p_whh1=whh1.data_ptr<float>(),*p_bih1=bih1.data_ptr<float>(),*p_bhh1=bhh1.data_ptr<float>(),*p_wih2=wih2.data_ptr<float>(),*p_whh2=whh2.data_ptr<float>(),*p_bih2=bih2.data_ptr<float>(),*p_bhh2=bhh2.data_ptr<float>(),*p_wih3=wih3.data_ptr<float>(),*p_whh3=whh3.data_ptr<float>(),*p_bih3=bih3.data_ptr<float>(),*p_bhh3=bhh3.data_ptr<float>(),*p_wih4=wih4.data_ptr<float>(),*p_whh4=whh4.data_ptr<float>(),*p_bih4=bih4.data_ptr<float>(),*p_bhh4=bhh4.data_ptr<float>(),*p_wih5=wih5.data_ptr<float>(),*p_whh5=whh5.data_ptr<float>(),*p_bih5=bih5.data_ptr<float>(),*p_bhh5=bhh5.data_ptr<float>();int bf=batch_first?1:0;void*args[]={&xp,&h0p,&hnp,&sp,&p_wih0,&p_whh0,&p_bih0,&p_bhh0,&p_wih1,&p_whh1,&p_bih1,&p_bhh1,&p_wih2,&p_whh2,&p_bih2,&p_bhh2,&p_wih3,&p_whh3,&p_bih3,&p_bhh3,&p_wih4,&p_whh4,&p_bih4,&p_bhh4,&p_wih5,&p_whh5,&p_bih5,&p_bhh5,&S,&B,&I,&bf};cudaLaunchCooperativeKernel((void*)gru_kernel,grid,block,args,0,at::cuda::getCurrentCUDAStream());return hn;}\n'''\n_ext=load_inline(name='gru_custom_ext_bper2',cpp_sources=_cpp,cuda_sources=_cuda,functions=['gru_forward'],extra_cuda_cflags=['-O3'],extra_cflags=['-O3'],verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self,input_size,hidden_size,num_layers=3,bias=True,batch_first=False): super().__init__(); self.gru=nn.GRU(input_size,hidden_size,num_layers,bias,batch_first,dropout=0,bidirectional=False); self.batch_first=batch_first\n def forward(self,x,h0): return _ext.gru_forward(x,h0,self.gru.weight_ih_l0,self.gru.weight_hh_l0,self.gru.bias_ih_l0,self.gru.bias_hh_l0,self.gru.weight_ih_l1,self.gru.weight_hh_l1,self.gru.bias_ih_l1,self.gru.bias_hh_l1,self.gru.weight_ih_l2,self.gru.weight_hh_l2,self.gru.bias_ih_l2,self.gru.bias_hh_l2,self.gru.weight_ih_l3,self.gru.weight_hh_l3,self.gru.bias_ih_l3,self.gru.bias_hh_l3,self.gru.weight_ih_l4,self.gru.weight_hh_l4,self.gru.bias_ih_l4,self.gru.bias_hh_l4,self.gru.weight_ih_l5,self.gru.weight_hh_l5,self.gru.bias_ih_l5,self.gru.bias_hh_l5,self.batch_first)\n"
}