call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_source = r'''\n#include <torch/extension.h>\ntorch::Tensor conv2d_forward_cuda(torch::Tensor x, torch::Tensor w, torch::Tensor bias,int stride_h,int stride_w,int pad_h,int pad_w,int dil_h,int dil_w,bool has_bias);\n'''\n\ncuda_source = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <mma.h>\nusing namespace nvcuda;\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be CUDA\")\n#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x \" must be contiguous\")\nconstexpr int WM=16, WN=16, WK=8, WARPS_M=8, OC_TILES=8, THREADS=WARPS_M*32;\n__global__ __launch_bounds__(THREADS,2)\nvoid conv2d_tf32_128oc_kernel(const float* __restrict__ x,const float* __restrict__ w,const float* __restrict__ bias,float* __restrict__ y,int N,int C,int H,int W,int OC,int KH,int KW,int OH,int OW,int stride_h,int stride_w,int pad_h,int pad_w,int dil_h,int dil_w,int has_bias){\n extern __shared__ float sh[]; float* As=sh; float* Bs=As+WARPS_M*WM*WK; int tid=threadIdx.x; int warp=tid>>5; int block_m0=blockIdx.x*(WARPS_M*WM);\n wmma::fragment<wmma::accumulator,WM,WN,WK,float> acc0,acc1,acc2,acc3,acc4,acc5,acc6,acc7; wmma::fill_fragment(acc0,0.0f); wmma::fill_fragment(acc1,0.0f); wmma::fill_fragment(acc2,0.0f); wmma::fill_fragment(acc3,0.0f); wmma::fill_fragment(acc4,0.0f); wmma::fill_fragment(acc5,0.0f); wmma::fill_fragment(acc6,0.0f); wmma::fill_fragment(acc7,0.0f);\n int Ktot=C*KH*KW; int Mtot=N*OH*OW;\n for(int kt=0;kt<Ktot;kt+=WK){\n for(int idx=tid;idx<OC_TILES*WN*WK;idx+=THREADS){int kk=idx&7; int tmp=idx>>3; int nn=tmp&15; int ot=tmp>>4; int oc=ot*16+nn; int k=kt+kk; float val=0.0f; if(k<Ktot){int t=k; int kw=t%KW; t/=KW; int kh=t%KH; t/=KH; int c=t; val=w[((oc*C+c)*KH+kh)*KW+kw];} Bs[idx]=val;}\n for(int idx=tid;idx<WARPS_M*WM*WK;idx+=THREADS){int kk=idx&7; int tmp=idx>>3; int mi=tmp&15; int wp=tmp>>4; int m=block_m0+wp*WM+mi; int k=kt+kk; float val=0.0f; if(m<Mtot && k<Ktot){int ow=m%OW; int t2=m/OW; int oh=t2%OH; int n=t2/OH; int t=k; int kw=t%KW; t/=KW; int kh=t%KH; t/=KH; int c=t; int ih=oh*stride_h-pad_h+kh*dil_h; int iw=ow*stride_w-pad_w+kw*dil_w; if((unsigned)ih<(unsigned)H && (unsigned)iw<(unsigned)W) val=x[((n*C+c)*H+ih)*W+iw];} As[idx]=val;}\n __syncthreads(); wmma::fragment<wmma::matrix_a,WM,WN,WK,wmma::precision::tf32,wmma::row_major> a; wmma::fragment<wmma::matrix_b,WM,WN,WK,wmma::precision::tf32,wmma::col_major> b; wmma::load_matrix_sync(a,As+warp*WM*WK,WK); wmma::load_matrix_sync(b,Bs+0*WN*WK,WK); wmma::mma_sync(acc0,a,b,acc0); wmma::load_matrix_sync(b,Bs+1*WN*WK,WK); wmma::mma_sync(acc1,a,b,acc1); wmma::load_matrix_sync(b,Bs+2*WN*WK,WK); wmma::mma_sync(acc2,a,b,acc2); wmma::load_matrix_sync(b,Bs+3*WN*WK,WK); wmma::mma_sync(acc3,a,b,acc3); wmma::load_matrix_sync(b,Bs+4*WN*WK,WK); wmma::mma_sync(acc4,a,b,acc4); wmma::load_matrix_sync(b,Bs+5*WN*WK,WK); wmma::mma_sync(acc5,a,b,acc5); wmma::load_matrix_sync(b,Bs+6*WN*WK,WK); wmma::mma_sync(acc6,a,b,acc6); wmma::load_matrix_sync(b,Bs+7*WN*WK,WK); wmma::mma_sync(acc7,a,b,acc7); __syncthreads(); }\n float* Cs=As; wmma::store_matrix_sync(Cs+(warp*OC_TILES+0)*WM*WN,acc0,WN,wmma::mem_row_major); wmma::store_matrix_sync(Cs+(warp*OC_TILES+1)*WM*WN,acc1,WN,wmma::mem_row_major); wmma::store_matrix_sync(Cs+(warp*OC_TILES+2)*WM*WN,acc2,WN,wmma::mem_row_major); wmma::store_matrix_sync(Cs+(warp*OC_TILES+3)*WM*WN,acc3,WN,wmma::mem_row_major); wmma::store_matrix_sync(Cs+(warp*OC_TILES+4)*WM*WN,acc4,WN,wmma::mem_row_major); wmma::store_matrix_sync(Cs+(warp*OC_TILES+5)*WM*WN,acc5,WN,wmma::mem_row_major); wmma::store_matrix_sync(Cs+(warp*OC_TILES+6)*WM*WN,acc6,WN,wmma::mem_row_major); wmma::store_matrix_sync(Cs+(warp*OC_TILES+7)*WM*WN,acc7,WN,wmma::mem_row_major); __syncthreads();\n for(int idx=tid;idx<WARPS_M*OC_TILES*WM*WN;idx+=THREADS){int col=idx&15; int tmp=idx>>4; int row=tmp&15; tmp>>=4; int ot=tmp&7; int wp=tmp>>3; int m=block_m0+wp*WM+row; int oc=ot*16+col; if(m<Mtot){int ow=m%OW; int t2=m/OW; int oh=t2%OH; int n=t2/OH; float val=Cs[((wp*OC_TILES+ot)*WM+row)*WN+col]; if(has_bias) val+=bias[oc]; y[((n*OC+oc)*OH+oh)*OW+ow]=val;}}\n}\n__global__ void conv2d_direct_kernel(const float* x,const float* w,const float* bias,float* y,int N,int C,int H,int W,int OC,int KH,int KW,int OH,int OW,int sh,int sw,int ph,int pw,int dh,int dw,int has_bias){int idx=blockIdx.x*blockDim.x+threadIdx.x; int total=N*OC*OH*OW; if(idx>=total)return; int ow=idx%OW; int t=idx/OW; int oh=t%OH; t/=OH; int oc=t%OC; int n=t/OC; float sum=has_bias?bias[oc]:0.0f; for(int c=0;c<C;c++)for(int kh=0;kh<KH;kh++)for(int kw=0;kw<KW;kw++){int ih=oh*sh-ph+kh*dh; int iw=ow*sw-pw+kw*dw; if((unsigned)ih<(unsigned)H && (unsigned)iw<(unsigned)W) sum+=x[((n*C+c)*H+ih)*W+iw]*w[((oc*C+c)*KH+kh)*KW+kw];} y[idx]=sum;}\ntorch::Tensor conv2d_forward_cuda(torch::Tensor x,torch::Tensor w,torch::Tensor bias,int stride_h,int stride_w,int pad_h,int pad_w,int dil_h,int dil_w,bool has_bias){CHECK_CUDA(x); CHECK_CUDA(w); CHECK_CONTIGUOUS(x); CHECK_CONTIGUOUS(w); int N=x.size(0),C=x.size(1),H=x.size(2),Wd=x.size(3); int OC=w.size(0),KH=w.size(2),KW=w.size(3); int OH=(H+2*pad_h-dil_h*(KH-1)-1)/stride_h+1; int OW=(Wd+2*pad_w-dil_w*(KW-1)-1)/stride_w+1; auto y=torch::empty({N,OC,OH,OW},x.options()); cudaStream_t stream=at::cuda::getCurrentCUDAStream(); if(OC==128 && x.scalar_type()==torch::kFloat32){int Mtot=N*OH*OW; dim3 grid((Mtot+WARPS_M*WM-1)/(WARPS_M*WM)); size_t smem=(WARPS_M*OC_TILES*WM*WN)*sizeof(float); static bool attr=false; if(!attr){cudaFuncSetAttribute(conv2d_tf32_128oc_kernel,cudaFuncAttributeMaxDynamicSharedMemorySize,(int)smem); attr=true;} conv2d_tf32_128oc_kernel<<<grid,THREADS,smem,stream>>>(x.data_ptr<float>(),w.data_ptr<float>(),has_bias?bias.data_ptr<float>():nullptr,y.data_ptr<float>(),N,C,H,Wd,OC,KH,KW,OH,OW,stride_h,stride_w,pad_h,pad_w,dil_h,dil_w,has_bias?1:0);} else {int total=N*OC*OH*OW; conv2d_direct_kernel<<<(total+255)/256,256,0,stream>>>(x.data_ptr<float>(),w.data_ptr<float>(),has_bias?bias.data_ptr<float>():nullptr,y.data_ptr<float>(),N,C,H,Wd,OC,KH,KW,OH,OW,stride_h,stride_w,pad_h,pad_w,dil_h,dil_w,has_bias?1:0);} return y;}\n'''\n_ext=load_inline(name='conv2d_tf32_ext_v4',cpp_sources=cpp_source,cuda_sources=cuda_source,functions=['conv2d_forward_cuda'],extra_cuda_cflags=['-O3','--use_fast_math'],verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self,in_channels:int,out_channels:int,kernel_size:tuple,stride:tuple=(1,1),padding:tuple=(0,0),dilation:tuple=(1,1),groups:int=1,bias:bool=False):\n super(ModelNew,self).__init__(); self.conv2d=nn.Conv2d(in_channels,out_channels,kernel_size,stride=stride,padding=padding,dilation=dilation,groups=groups,bias=bias); self.stride=stride; self.padding=padding; self.dilation=dilation; self.groups=groups\n def forward(self,x:torch.Tensor)->torch.Tensor:\n b=self.conv2d.bias if self.conv2d.bias is not None else torch.empty(0,device=x.device,dtype=x.dtype)\n return _ext.conv2d_forward_cuda(x.contiguous(),self.conv2d.weight.contiguous(),b,int(self.stride[0]),int(self.stride[1]),int(self.padding[0]),int(self.padding[1]),int(self.dilation[0]),int(self.dilation[1]),self.conv2d.bias is not None)\n"
}