call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r'''\n#include <torch/extension.h>\n#include <vector>\nvoid gru_forward_cuda_launcher(const torch::Tensor& x, const torch::Tensor& h0, const std::vector<torch::Tensor>& params, torch::Tensor& output, torch::Tensor& buf1, torch::Tensor& buf2, torch::Tensor& hstate, torch::Tensor& gi, torch::Tensor& gh, int64_t input_size, int64_t hidden_size, int64_t num_layers, bool batch_first);\ntorch::Tensor gru_forward(torch::Tensor x, torch::Tensor h0, std::vector<torch::Tensor> params, int64_t input_size, int64_t hidden_size, int64_t num_layers, bool batch_first) {\n int64_t S = batch_first ? x.size(1) : x.size(0);\n int64_t B = batch_first ? x.size(0) : x.size(1);\n auto opts = x.options();\n torch::Tensor output = batch_first ? torch::empty({B, S, 2*hidden_size}, opts) : torch::empty({S, B, 2*hidden_size}, opts);\n torch::Tensor buf1 = torch::empty({S, B, 2*hidden_size}, opts);\n torch::Tensor buf2 = torch::empty({S, B, 2*hidden_size}, opts);\n torch::Tensor hstate = torch::empty({B, hidden_size}, opts);\n torch::Tensor gi = torch::empty({3*hidden_size, B}, opts);\n torch::Tensor gh = torch::empty({3*hidden_size, B}, opts);\n gru_forward_cuda_launcher(x, h0, params, output, buf1, buf2, hstate, gi, gh, input_size, hidden_size, num_layers, batch_first);\n return output;\n}\n'''\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAException.h>\n#include <cuda_runtime.h>\n#include <cooperative_groups.h>\n#include <vector>\nnamespace cg = cooperative_groups;\n__device__ __forceinline__ float warp_sum(float v){for(int off=16;off>0;off>>=1)v+=__shfl_down_sync(0xffffffff,v,off);return v;}\n__device__ __forceinline__ float sig(float x){return 1.0f/(1.0f+expf(-x));}\n__device__ __forceinline__ float rin(const float* inp,const float* x,int layer,bool bf,int t,int b,int k,int S,int B,int inf,int isz){return layer==0?(bf?x[(b*S+t)*isz+k]:x[(t*B+b)*isz+k]):inp[(t*B+b)*inf+k];}\nextern \"C\" __global__ void gru_dir_kernel(const float* xbase,const float* inp,const float* h0,const float* w_ih,const float* w_hh,const float* b_ih,const float* b_hh,float* out,float* hstate,float* gi,float* gh,int S,int B,int input_size,int in_feat,int H,int layer,int dir,int num_layers,bool batch_first,bool final_layer){\n cg::grid_group grid=cg::this_grid(); int tid=blockIdx.x*blockDim.x+threadIdx.x; int nthreads=gridDim.x*blockDim.x;\n for(int idx=tid;idx<B*H;idx+=nthreads){int b=idx/H,h=idx-b*H; hstate[idx]=h0[((layer*2+dir)*B+b)*H+h];} grid.sync();\n int lane=threadIdx.x&31; int warp_global=(blockIdx.x*blockDim.x+threadIdx.x)>>5; int nwarps=(gridDim.x*blockDim.x)>>5; int rows=3*H;\n for(int step=0;step<S;++step){int t=dir==0?step:S-1-step; for(int row=warp_global;row<rows;row+=nwarps){float acci[10]; float acch[10];\n #pragma unroll\n for(int bb=0;bb<10;++bb){acci[bb]=0.0f;acch[bb]=0.0f;} const float* wi=w_ih+row*in_feat; const float* wh=w_hh+row*H;\n for(int k=lane;k<in_feat;k+=32){float w=wi[k]; #pragma unroll\n for(int bb=0;bb<10;++bb) if(bb<B) acci[bb]+=w*rin(inp,xbase,layer,batch_first,t,bb,k,S,B,in_feat,input_size);}\n for(int k=lane;k<H;k+=32){float w=wh[k]; #pragma unroll\n for(int bb=0;bb<10;++bb) if(bb<B) acch[bb]+=w*hstate[bb*H+k];}\n #pragma unroll\n for(int bb=0;bb<10;++bb){float si=warp_sum(acci[bb]); float sh=warp_sum(acch[bb]); if(lane==0 && bb<B){gi[row*B+bb]=si+b_ih[row]; gh[row*B+bb]=sh+b_hh[row];}}\n } grid.sync();\n for(int idx=tid;idx<B*H;idx+=nthreads){int b=idx/H,h=idx-b*H; float hp=hstate[idx]; float r=sig(gi[h*B+b]+gh[h*B+b]); float z=sig(gi[(H+h)*B+b]+gh[(H+h)*B+b]); float n=tanhf(gi[(2*H+h)*B+b]+r*gh[(2*H+h)*B+b]); float hn=(1.0f-z)*n+z*hp; hstate[idx]=hn; if(final_layer){if(batch_first) out[(b*S+t)*(2*H)+dir*H+h]=hn; else out[(t*B+b)*(2*H)+dir*H+h]=hn;} else out[(t*B+b)*(2*H)+dir*H+h]=hn;} grid.sync(); }\n}\nstatic void launch_one(const torch::Tensor& x,const torch::Tensor& inp,const torch::Tensor& h0,const torch::Tensor& w_ih,const torch::Tensor& w_hh,const torch::Tensor& b_ih,const torch::Tensor& b_hh,torch::Tensor& out,torch::Tensor& hstate,torch::Tensor& gi,torch::Tensor& gh,int S,int B,int input_size,int in_feat,int H,int layer,int dir,int num_layers,bool batch_first,bool final_layer){\n cudaDeviceProp prop; int dev; C10_CUDA_CHECK(cudaGetDevice(&dev)); C10_CUDA_CHECK(cudaGetDeviceProperties(&prop,dev)); int block=256, grid=prop.multiProcessorCount;\n const float *xptr=x.data_ptr<float>(),*inptr=inp.data_ptr<float>(),*h0ptr=h0.data_ptr<float>(),*wiptr=w_ih.data_ptr<float>(),*whptr=w_hh.data_ptr<float>(),*biptr=b_ih.data_ptr<float>(),*bhptr=b_hh.data_ptr<float>(); float *outptr=out.data_ptr<float>(),*hptr=hstate.data_ptr<float>(),*giptr=gi.data_ptr<float>(),*ghptr=gh.data_ptr<float>();\n void* args[]={&xptr,&inptr,&h0ptr,&wiptr,&whptr,&biptr,&bhptr,&outptr,&hptr,&giptr,&ghptr,&S,&B,&input_size,&in_feat,&H,&layer,&dir,&num_layers,&batch_first,&final_layer};\n C10_CUDA_CHECK(cudaLaunchCooperativeKernel((void*)gru_dir_kernel,dim3(grid),dim3(block),args,0,at::cuda::getCurrentCUDAStream()));}\nvoid gru_forward_cuda_launcher(const torch::Tensor& x,const torch::Tensor& h0,const std::vector<torch::Tensor>& params,torch::Tensor& output,torch::Tensor& buf1,torch::Tensor& buf2,torch::Tensor& hstate,torch::Tensor& gi,torch::Tensor& gh,int64_t input_size64,int64_t hidden_size64,int64_t num_layers64,bool batch_first){int S=batch_first?x.size(1):x.size(0); int B=batch_first?x.size(0):x.size(1); int input_size=input_size64,H=hidden_size64,L=num_layers64; for(int layer=0;layer<L;++layer){int in_feat=layer==0?input_size:2*H; const torch::Tensor& inp=layer==0?x:((layer%2==1)?buf1:buf2); torch::Tensor& out=(layer==L-1)?output:((layer%2==0)?buf1:buf2); bool final_layer=layer==L-1; int base=layer*8; launch_one(x,inp,h0,params[base],params[base+1],params[base+2],params[base+3],out,hstate,gi,gh,S,B,input_size,in_feat,H,layer,0,L,batch_first,final_layer); launch_one(x,inp,h0,params[base+4],params[base+5],params[base+6],params[base+7],out,hstate,gi,gh,S,B,input_size,in_feat,H,layer,1,L,batch_first,final_layer);}}\n'''\n_ext=load_inline(name='gru_custom_ext_v3',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.input_size=input_size; self.hidden_size=hidden_size; self.num_layers=num_layers; self.batch_first=batch_first; self.bias=bias; self.gru=nn.GRU(input_size,hidden_size,num_layers,bias=bias,batch_first=batch_first,dropout=0,bidirectional=True)\n def forward(self,x,h0):\n return _ext.gru_forward(x.contiguous(),h0.contiguous(),list(self.gru._flat_weights),self.input_size,self.hidden_size,self.num_layers,self.batch_first)\n"
}