call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n# Same as v2 but with double pointwise via replacing snippets for brevity\ncpp_source = r'''\n#include <torch/extension.h>\n#include <vector>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <ATen/cuda/CUDAContext.h>\nvoid launch_gru_layer(torch::Tensor input, torch::Tensor output, torch::Tensor h0, torch::Tensor hbuf, torch::Tensor wih, torch::Tensor whh, torch::Tensor bih, torch::Tensor bhh, int S, int B, int K, int H, int input_layout, int output_layout, bool has_bias);\ntorch::Tensor gru_forward_cuda(torch::Tensor x, torch::Tensor h0, std::vector<torch::Tensor> wihs, std::vector<torch::Tensor> whhs, std::vector<torch::Tensor> bihs, std::vector<torch::Tensor> bhhs, bool batch_first, bool has_bias){x=x.contiguous(); h0=h0.contiguous(); long L=h0.size(0),B=batch_first?x.size(0):x.size(1),S=batch_first?x.size(1):x.size(0),I=x.size(2),H=h0.size(2); auto opts=x.options(); torch::Tensor tmp1,tmp2,out=batch_first?torch::empty({B,S,H},opts):torch::empty({S,B,H},opts); if(L>1){tmp1=torch::empty({S,B,H},opts); if(L>2) tmp2=torch::empty({S,B,H},opts);} torch::Tensor prev=x; int pl=batch_first?1:0; for(int l=0;l<L;l++){torch::Tensor o; int ol; if(l==L-1){o=out; ol=batch_first?1:0;}else{o=(l%2==0)?tmp1:tmp2; ol=0;} torch::Tensor hb=torch::empty({2,B,H},opts); torch::Tensor bi=has_bias?bihs[l].contiguous():torch::empty({0},opts), bh=has_bias?bhhs[l].contiguous():torch::empty({0},opts); launch_gru_layer(prev,o,h0[l],hb,wihs[l].contiguous(),whhs[l].contiguous(),bi,bh,(int)S,(int)B,l==0?(int)I:(int)H,(int)H,pl,ol,has_bias); prev=o; pl=ol;} return out;}\n'''\ncuda_source = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cooperative_groups.h>\n#include <ATen/cuda/CUDAContext.h>\nnamespace cg=cooperative_groups;\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 gru_layer_kernel(const float* __restrict__ inp,float* __restrict__ out,const float* __restrict__ h0,float* __restrict__ hbuf,const float* __restrict__ wih,const float* __restrict__ whh,const float* __restrict__ bih,const float* __restrict__ bhh,int S,int B,int K,int H,int input_layout,int output_layout,int has_bias){cg::grid_group grid=cg::this_grid();int b=blockIdx.x,tile=blockIdx.y;const int TH=16,jbase=tile*TH;int tid=threadIdx.x,warp=tid>>5,lane=tid&31;__shared__ float sr[16],sz[16],si[16],sh[16];if(tid<TH){int j=jbase+tid;if(j<H){float v=h0[b*H+j];hbuf[b*H+j]=v;hbuf[B*H+b*H+j]=v;}}grid.sync();for(int t=0;t<S;t++){const float* hr=hbuf+((t&1)?B*H:0);float* hw=hbuf+((t&1)?0:B*H);for(int task=warp;task<48;task+=8){int gt=task>>4,jj=task&15,j=jbase+jj;if(j<H){int gr=gt*H+j;float acci=0,acch=0;for(int k=lane;k<K;k+=32){float xv=input_layout==0?inp[(t*B+b)*K+k]:inp[(b*S+t)*K+k];acci=fmaf(wih[gr*K+k],xv,acci);}for(int k=lane;k<H;k+=32)acch=fmaf(whh[gr*H+k],hr[b*H+k],acch);acci=warp_sum(acci);acch=warp_sum(acch);if(lane==0){float ib=has_bias?bih[gr]:0,hb=has_bias?bhh[gr]:0;if(gt==0)sr[jj]=ib+acci+hb+acch;else if(gt==1)sz[jj]=ib+acci+hb+acch;else{si[jj]=ib+acci;sh[jj]=hb+acch;}}}}__syncthreads();if(tid<TH){int j=jbase+tid;if(j<H){double oldh=hr[b*H+j];double r=1.0/(1.0+exp(-(double)sr[tid]));double z=1.0/(1.0+exp(-(double)sz[tid]));double n=tanh((double)si[tid]+r*(double)sh[tid]);float nh=(float)((1.0-z)*n+z*oldh);hw[b*H+j]=nh;if(output_layout==0)out[(t*B+b)*H+j]=nh;else out[(b*S+t)*H+j]=nh;}}__syncthreads();grid.sync();}}\nvoid launch_gru_layer(torch::Tensor input,torch::Tensor output,torch::Tensor h0,torch::Tensor hbuf,torch::Tensor wih,torch::Tensor whh,torch::Tensor bih,torch::Tensor bhh,int S,int B,int K,int H,int il,int ol,bool has_bias){dim3 block(256),grid(B,(H+15)/16);const float* ip=input.data_ptr<float>();float* op=output.data_ptr<float>();const float* h0p=h0.data_ptr<float>();float* hbp=hbuf.data_ptr<float>();const float* wip=wih.data_ptr<float>();const float* whp=whh.data_ptr<float>();const float* bip=has_bias?bih.data_ptr<float>():nullptr;const float* bhp=has_bias?bhh.data_ptr<float>():nullptr;int hb=has_bias?1:0;void* args[]={&ip,&op,&h0p,&hbp,&wip,&whp,&bip,&bhp,&S,&B,&K,&H,&il,&ol,&hb};C10_CUDA_CHECK(cudaLaunchCooperativeKernel((void*)gru_layer_kernel,grid,block,args,0,at::cuda::getCurrentCUDAStream()));}\n'''\n_ext=load_inline(name='gru_custom_ext_v4p', cpp_sources=cpp_source, cuda_sources=cuda_source, functions=['gru_forward_cuda'], 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; self.bias=bias; self.num_layers=num_layers\n def forward(self,x,h0):\n wihs=[getattr(self.gru,f'weight_ih_l{i}') for i in range(self.num_layers)]; whhs=[getattr(self.gru,f'weight_hh_l{i}') for i in range(self.num_layers)]\n bihs=[getattr(self.gru,f'bias_ih_l{i}') for i in range(self.num_layers)] if self.bias else []; bhhs=[getattr(self.gru,f'bias_hh_l{i}') for i in range(self.num_layers)] if self.bias else []\n return _ext.gru_forward_cuda(x,h0,wihs,whhs,bihs,bhhs,self.batch_first,self.bias)\n"
}