call → run_correctness
callrun_correctness
{
"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>\ntorch::Tensor rnn_forward_cuda(torch::Tensor x, torch::Tensor h0,\n torch::Tensor wi, torch::Tensor bi,\n torch::Tensor wo, torch::Tensor bo);\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>\nnamespace cg = cooperative_groups;\n__global__ void rnn_coop_kernel(const float* __restrict__ x,const float* __restrict__ h0,const float* __restrict__ wi,const float* __restrict__ bi,const float* __restrict__ wo,const float* __restrict__ bo,float* __restrict__ out,float* __restrict__ buf0,float* __restrict__ buf1,int T,int B,int I,int H,int O){\n cg::grid_group grid=cg::this_grid(); int tid=threadIdx.x,lane=tid&31,warp_in_block=tid>>5,wpb=blockDim.x>>5; int gw=blockIdx.x*wpb+warp_in_block, tw=gridDim.x*wpb, tt=gridDim.x*blockDim.x;\n for(int idx=blockIdx.x*blockDim.x+tid; idx<B*H; idx+=tt) buf0[idx]=h0[idx];\n grid.sync(); float* oldh=buf0; float* newh=buf1; int IH=I+H;\n for(int t=0;t<T;++t){\n for(int task=gw; task<B*H; task+=tw){\n int hh=task / B; int b=task - hh*B;\n const float* wrow=wi+hh*IH; const float* xrow=x+((t*B+b)*I); const float* hrow=oldh+b*H;\n float sum=(lane==0)?bi[hh]:0.0f;\n for(int k=lane;k<I;k+=32) sum=fmaf(xrow[k],wrow[k],sum);\n for(int k=lane;k<H;k+=32) sum=fmaf(hrow[k],wrow[I+k],sum);\n #pragma unroll\n for(int off=16;off>0;off>>=1) sum+=__shfl_down_sync(0xffffffff,sum,off);\n if(lane==0) newh[b*H+hh]=tanhf(sum);\n }\n grid.sync();\n for(int task=gw; task<B*O; task+=tw){\n int oo=task / B; int b=task - oo*B;\n const float* wrow=wo+oo*H; const float* hrow=newh+b*H; float sum=(lane==0)?bo[oo]:0.0f;\n for(int k=lane;k<H;k+=32) sum=fmaf(hrow[k],wrow[k],sum);\n #pragma unroll\n for(int off=16;off>0;off>>=1) sum+=__shfl_down_sync(0xffffffff,sum,off);\n if(lane==0) out[(t*B+b)*O+oo]=sum;\n }\n grid.sync(); float* tmp=oldh; oldh=newh; newh=tmp;\n }\n}\ntorch::Tensor rnn_forward_cuda(torch::Tensor x,torch::Tensor h0,torch::Tensor wi,torch::Tensor bi,torch::Tensor wo,torch::Tensor bo){\n int64_t T64=x.size(0),B64=x.size(1),I64=x.size(2),H64=h0.size(1),O64=bo.size(0); auto out=torch::empty({T64,B64,O64},x.options()); auto buf0=torch::empty({B64,H64},x.options()); auto buf1=torch::empty({B64,H64},x.options());\n int T=(int)T64,B=(int)B64,I=(int)I64,H=(int)H64,O=(int)O64; const int threads=256; int blocks=128; int dev=x.get_device(),sm=0; cudaDeviceGetAttribute(&sm,cudaDevAttrMultiProcessorCount,dev); if(blocks>sm) blocks=sm; if(blocks<1) blocks=1;\n const float *xp=x.data_ptr<float>(),*h0p=h0.data_ptr<float>(),*wip=wi.data_ptr<float>(),*bip=bi.data_ptr<float>(),*wop=wo.data_ptr<float>(),*bop=bo.data_ptr<float>(); float *outp=out.data_ptr<float>(),*b0p=buf0.data_ptr<float>(),*b1p=buf1.data_ptr<float>();\n void* args[]={&xp,&h0p,&wip,&bip,&wop,&bop,&outp,&b0p,&b1p,&T,&B,&I,&H,&O}; cudaStream_t stream=at::cuda::getCurrentCUDAStream(); C10_CUDA_CHECK(cudaLaunchCooperativeKernel((void*)rnn_coop_kernel,blocks,threads,args,0,stream)); C10_CUDA_KERNEL_LAUNCH_CHECK(); return out;\n}\n'''\n_ext = load_inline(name='rnn_custom_coop_hmajor', cpp_sources=[_cpp_src], cuda_sources=[_cuda_src], functions=['rnn_forward_cuda'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], with_cuda=True, verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self,input_size:int,hidden_size:int,output_size:int):\n super(ModelNew,self).__init__(); self.input_size=input_size; self.hidden_size=hidden_size; self.output_size=output_size; self.i2h=nn.Linear(input_size+hidden_size,hidden_size); self.h2o=nn.Linear(hidden_size,output_size); self.tanh=nn.Tanh()\n def forward(self,x:torch.Tensor,h0:torch.Tensor)->torch.Tensor:\n h0d=h0.to(x.device); return _ext.rnn_forward_cuda(x.contiguous(),h0d.contiguous(),self.i2h.weight.contiguous(),self.i2h.bias.contiguous(),self.h2o.weight.contiguous(),self.h2o.bias.contiguous())\n"
}