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>\ntorch::Tensor gru_forward_cuda(torch::Tensor x, torch::Tensor h0,std::vector<torch::Tensor> w_ih,std::vector<torch::Tensor> w_hh,std::vector<torch::Tensor> b_ih,std::vector<torch::Tensor> b_hh,bool batch_first);\ntorch::Tensor gru_forward(torch::Tensor x, torch::Tensor h0,std::vector<torch::Tensor> w_ih,std::vector<torch::Tensor> w_hh,std::vector<torch::Tensor> b_ih,std::vector<torch::Tensor> b_hh,bool batch_first){return gru_forward_cuda(x,h0,w_ih,w_hh,b_ih,b_hh,batch_first);}'''\n_cuda_src=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 <cooperative_groups.h>\n#include <vector>\nnamespace cg=cooperative_groups;\n__device__ __forceinline__ float sigm(float x){return 1.0f/(1.0f+__expf(-x));}\n__global__ void gru_layer_kernel(const float* __restrict__ input,const float* __restrict__ h0,const float* __restrict__ w_ih,const float* __restrict__ w_hh,const float* __restrict__ b_ih,const float* __restrict__ b_hh,float* __restrict__ out,float* __restrict__ hs0,float* __restrict__ hs1,float* __restrict__ hn,int T,int B,int in_dim,int H,int layer,int batch_first,int is_first_layer){cg::grid_group grid=cg::this_grid(); int b=blockIdx.x,tile=blockIdx.y,tid=threadIdx.x,h=tile*blockDim.x+tid; if(h<H) hs0[b*H+h]=h0[(layer*B+b)*H+h]; grid.sync(); for(int t=0;t<T;++t){const float* hprev=(t&1)?hs1+b*H:hs0+b*H; float* hcur=(t&1)?hs0+b*H:hs1+b*H; if(h<H){float hp=hprev[h]; float gr=b_ih[h]+b_hh[h],gz=b_ih[H+h]+b_hh[H+h],gi=b_ih[2*H+h],gh=b_hh[2*H+h]; const float* xbase; if(is_first_layer) xbase=batch_first?input+(b*T+t)*in_dim:input+(t*B+b)*in_dim; else xbase=input+(t*B+b)*in_dim; const float* wr=w_ih+h*in_dim; const float* wz=w_ih+(H+h)*in_dim; const float* wn=w_ih+(2*H+h)*in_dim; for(int k=0;k<in_dim;++k){float xv=xbase[k]; gr=fmaf(wr[k],xv,gr); gz=fmaf(wz[k],xv,gz); gi=fmaf(wn[k],xv,gi);} const float* whr=w_hh+h*H; const float* whz=w_hh+(H+h)*H; const float* whn=w_hh+(2*H+h)*H; for(int k=0;k<H;++k){float hv=hprev[k]; gr=fmaf(whr[k],hv,gr); gz=fmaf(whz[k],hv,gz); gh=fmaf(whn[k],hv,gh);} float r=sigm(gr),z=sigm(gz); float n=tanhf(gi+r*gh); float hnew=fmaf(z,hp-n,n); hcur[h]=hnew; out[(t*B+b)*H+h]=hnew; if(t==T-1) hn[(layer*B+b)*H+h]=hnew;} grid.sync();}}\nstatic void launch_layer(const float* input,const float* h0,const float* w_ih,const float* w_hh,const float* b_ih,const float* b_hh,float* out,float* hs0,float* hs1,float* hn,int T,int B,int in_dim,int H,int layer,bool batch_first,bool is_first_layer,cudaStream_t stream){int threads=32; dim3 block(threads),grid(B,(H+threads-1)/threads); int bf=batch_first?1:0,first=is_first_layer?1:0; void* args[]={(void*)&input,(void*)&h0,(void*)&w_ih,(void*)&w_hh,(void*)&b_ih,(void*)&b_hh,(void*)&out,(void*)&hs0,(void*)&hs1,(void*)&hn,(void*)&T,(void*)&B,(void*)&in_dim,(void*)&H,(void*)&layer,(void*)&bf,(void*)&first}; cudaLaunchCooperativeKernel((void*)gru_layer_kernel,grid,block,args,0,stream);}\ntorch::Tensor gru_forward_cuda(torch::Tensor x,torch::Tensor h0,std::vector<torch::Tensor> w_ih,std::vector<torch::Tensor> w_hh,std::vector<torch::Tensor> b_ih,std::vector<torch::Tensor> b_hh,bool batch_first){const at::cuda::OptionalCUDAGuard device_guard(device_of(x)); int64_t L=h0.size(0); int T=batch_first?(int)x.size(1):(int)x.size(0),B=batch_first?(int)x.size(0):(int)x.size(1),I=(int)x.size(2),H=(int)h0.size(2); auto opts=x.options(); torch::Tensor hn=torch::empty({L,B,H},opts),buf1=torch::empty({T,B,H},opts),buf2=torch::empty({T,B,H},opts),hs0=torch::empty({B,H},opts),hs1=torch::empty({B,H},opts); cudaStream_t stream=at::cuda::getCurrentCUDAStream(); for(int l=0;l<L;++l){torch::Tensor& out=(l%2==0)?buf1:buf2; const float* inp=(l==0)?x.data_ptr<float>():((l%2==1)?buf1.data_ptr<float>():buf2.data_ptr<float>()); int in_dim=(l==0)?I:H; launch_layer(inp,h0.data_ptr<float>(),w_ih[l].data_ptr<float>(),w_hh[l].data_ptr<float>(),b_ih[l].data_ptr<float>(),b_hh[l].data_ptr<float>(),out.data_ptr<float>(),hs0.data_ptr<float>(),hs1.data_ptr<float>(),hn.data_ptr<float>(),T,B,in_dim,H,l,batch_first,l==0,stream); C10_CUDA_KERNEL_LAUNCH_CHECK();} return hn;}\n'''\n_ext=load_inline(name='gru_custom_ext_v4',cpp_sources=_cpp_src,cuda_sources=_cuda_src,functions=['gru_forward'],extra_cuda_cflags=['-O3','--use_fast_math'],verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self,input_size,hidden_size,num_layers=3,bias=True,batch_first=False):\n super().__init__(); self.gru=nn.GRU(input_size,hidden_size,num_layers,bias,batch_first,dropout=0,bidirectional=False); self.batch_first=batch_first; self.num_layers=num_layers; self.bias=bias\n def forward(self,x,h0):\n w_ih=[getattr(self.gru,f'weight_ih_l{i}') for i in range(self.num_layers)]; w_hh=[getattr(self.gru,f'weight_hh_l{i}') for i in range(self.num_layers)]\n if self.bias:\n b_ih=[getattr(self.gru,f'bias_ih_l{i}') for i in range(self.num_layers)]; b_hh=[getattr(self.gru,f'bias_hh_l{i}') for i in range(self.num_layers)]\n else:\n b_ih=[torch.zeros(3*self.gru.hidden_size,device=x.device,dtype=x.dtype) for _ in range(self.num_layers)]; b_hh=[torch.zeros(3*self.gru.hidden_size,device=x.device,dtype=x.dtype) for _ in range(self.num_layers)]\n return _ext.gru_forward(x,h0,w_ih,w_hh,b_ih,b_hh,self.batch_first)\n"
}