call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\ncpp_src=r'''\n#include <torch/extension.h>\n#include <vector>\nstd::vector<torch::Tensor> gru_layer_cuda(torch::Tensor input, torch::Tensor h0_fw, torch::Tensor h0_bw, torch::Tensor wih_fw, torch::Tensor whh_fw, torch::Tensor bih_fw, torch::Tensor bhh_fw, torch::Tensor wih_bw, torch::Tensor whh_bw, torch::Tensor bih_bw, torch::Tensor bhh_bw);\n'''\ncuda_src=r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.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 sig(float x){return 1.f/(1.f+expf(-x));}\n__global__ void coop_kern(const float* __restrict__ gf,const float* __restrict__ gb,const float* __restrict__ h0f,const float* __restrict__ h0b,const float* __restrict__ whf,const float* __restrict__ whb,const float* __restrict__ bhf,const float* __restrict__ bhb,float* __restrict__ out,float* __restrict__ hn,float* __restrict__ buf,int T,int B,int H,int tiles){\n cg::grid_group grid=cg::this_grid(); int bid=blockIdx.x; int tile=bid%tiles; int seq=bid/tiles; int b=seq%B; int dir=seq/B; int j=tile*blockDim.x+threadIdx.x; int base=(dir*B+b)*H; const float*h0=dir?h0b:h0f; if(j<H) buf[base+j]=h0[b*H+j]; grid.sync();\n for(int s=0;s<T;s++){int t=dir?(T-1-s):s; float* cur=buf+((s&1)?(2*B*H):0); float* nxt=buf+((s&1)?0:(2*B*H)); if(j<H){const float*g=(dir?gb:gf)+((t*B+b)*(3*H)); const float*w=dir?whb:whf; const float*bh=dir?bhb:bhf; float sr=0,sz=0,sn=0; const float*wr=w+j*H; const float*wz=w+(H+j)*H; const float*wn=w+(2*H+j)*H; const float*hc=cur+base; for(int k=0;k<H;k++){float hv=hc[k]; sr+=wr[k]*hv; sz+=wz[k]*hv; sn+=wn[k]*hv;} float r=sig(g[j]+bh[j]+sr); float z=sig(g[H+j]+bh[H+j]+sz); float n=tanhf(g[2*H+j]+r*(bh[2*H+j]+sn)); float nh=n+z*(hc[j]-n); nxt[base+j]=nh; out[(t*B+b)*(2*H)+dir*H+j]=nh;} grid.sync(); }\n float* final=buf+((T&1)?(2*B*H):0); if(j<H) hn[base+j]=final[base+j]; }\nstd::vector<torch::Tensor> gru_layer_cuda(torch::Tensor input, torch::Tensor h0_fw, torch::Tensor h0_bw, torch::Tensor wih_fw, torch::Tensor whh_fw, torch::Tensor bih_fw, torch::Tensor bhh_fw, torch::Tensor wih_bw, torch::Tensor whh_bw, torch::Tensor bih_bw, torch::Tensor bhh_bw){int64_t T=input.size(0),B=input.size(1),H=h0_fw.size(1);auto flat=input.reshape({T*B,input.size(2)});auto gf=at::addmm(bih_fw,flat,wih_fw.t());auto gb=at::addmm(bih_bw,flat,wih_bw.t());auto out=torch::empty({T,B,2*H},input.options());auto hn=torch::empty({2,B,H},input.options());auto buf=torch::empty({2,2,B,H},input.options());int block=32;int tiles=(H+block-1)/block;dim3 grid(B*2*tiles);void* args[]={&gf,&gb,&h0_fw,&h0_bw,&whh_fw,&whh_bw,&bhh_fw,&bhh_bw,&out,&hn,&buf,&T,&B,&H,&tiles};\n const float* pgf=gf.data_ptr<float>(); const float* pgb=gb.data_ptr<float>(); const float* ph0f=h0_fw.data_ptr<float>(); const float* ph0b=h0_bw.data_ptr<float>(); const float* pwhf=whh_fw.data_ptr<float>(); const float* pwhb=whh_bw.data_ptr<float>(); const float* pbhf=bhh_fw.data_ptr<float>(); const float* pbhb=bhh_bw.data_ptr<float>(); float* pout=out.data_ptr<float>(); float* phn=hn.data_ptr<float>(); float* pbuf=buf.data_ptr<float>(); int iT=(int)T,iB=(int)B,iH=(int)H,itiles=tiles; void* kargs[]={&pgf,&pgb,&ph0f,&ph0b,&pwhf,&pwhb,&pbhf,&pbhb,&pout,&phn,&pbuf,&iT,&iB,&iH,&itiles}; cudaLaunchCooperativeKernel((void*)coop_kern, grid, dim3(block), kargs, 0, at::cuda::getCurrentCUDAStream()); return {out,hn};}\n'''\n_ext=load_inline(name='gru_custom_ext_coop1',cpp_sources=cpp_src,cuda_sources=cuda_src,functions=['gru_layer_cuda'],verbose=False,extra_cuda_cflags=['-O3'],extra_cflags=['-O3'])\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=True);self.num_layers=num_layers;self.batch_first=batch_first\n def forward(self,x,h0):\n inp=x.transpose(0,1).contiguous() if self.batch_first else x.contiguous();hs=[]\n for l in range(self.num_layers):\n s=str(l);r=_ext.gru_layer_cuda(inp,h0[2*l].contiguous(),h0[2*l+1].contiguous(),getattr(self.gru,'weight_ih_l'+s),getattr(self.gru,'weight_hh_l'+s),getattr(self.gru,'bias_ih_l'+s),getattr(self.gru,'bias_hh_l'+s),getattr(self.gru,'weight_ih_l'+s+'_reverse'),getattr(self.gru,'weight_hh_l'+s+'_reverse'),getattr(self.gru,'bias_ih_l'+s+'_reverse'),getattr(self.gru,'bias_hh_l'+s+'_reverse'))\n inp=r[0];hs += [r[1][0],r[1][1]]\n return torch.stack(hs,0)\n"
}