call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_sources = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <ATen/cuda/CUDABlas.h>\n#include <cublas_v2.h>\nvoid depthwise_kernel_launcher(const float*,const float*,const float*,float*,int,int,int,int,int,int,int,int,int,int,bool,cudaStream_t);\nvoid add_bias_launcher(float*,const float*,int,long,long,cudaStream_t);\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be CUDA\")\n#define CHECK_FLOAT(x) TORCH_CHECK(x.scalar_type()==at::kFloat, #x \" must be float32\")\n#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x \" must be contiguous\")\nat::Tensor depthwise_sep_forward(at::Tensor x, at::Tensor dw_w, at::Tensor pw_w, at::Tensor dw_b, at::Tensor pw_b, int64_t stride, int64_t padding, int64_t dilation){\n CHECK_CUDA(x); CHECK_CUDA(dw_w); CHECK_CUDA(pw_w); CHECK_CUDA(dw_b); CHECK_CUDA(pw_b);\n CHECK_FLOAT(x); CHECK_FLOAT(dw_w); CHECK_FLOAT(pw_w); CHECK_FLOAT(dw_b); CHECK_FLOAT(pw_b);\n CHECK_CONTIGUOUS(x); CHECK_CONTIGUOUS(dw_w); CHECK_CONTIGUOUS(pw_w); CHECK_CONTIGUOUS(dw_b); CHECK_CONTIGUOUS(pw_b);\n int N=x.size(0), C=x.size(1), H=x.size(2), W=x.size(3), K=dw_w.size(2), OC=pw_w.size(0);\n int Ho=(H+2*(int)padding-(int)dilation*(K-1)-1)/(int)stride+1;\n int Wo=(W+2*(int)padding-(int)dilation*(K-1)-1)/(int)stride+1;\n auto inter=at::empty({N,C,Ho,Wo}, x.options());\n auto out=at::empty({N,OC,Ho,Wo}, x.options());\n cudaStream_t stream=at::cuda::getCurrentCUDAStream();\n const float* db=dw_b.numel()?dw_b.data_ptr<float>():nullptr;\n depthwise_kernel_launcher(x.data_ptr<float>(), dw_w.data_ptr<float>(), db, inter.data_ptr<float>(), N,C,H,W,K,(int)stride,(int)padding,(int)dilation,Ho,Wo,dw_b.numel()!=0,stream);\n cublasHandle_t handle=at::cuda::getCurrentCUDABlasHandle();\n cublasSetStream(handle, stream);\n cublasSetMathMode(handle, CUBLAS_TF32_TENSOR_OP_MATH);\n const float alpha=1.0f, beta=0.0f; long long S=(long long)Ho*Wo;\n cublasStatus_t stat=cublasSgemmStridedBatched(handle, CUBLAS_OP_N, CUBLAS_OP_N,\n (int)S, OC, C, &alpha,\n inter.data_ptr<float>(), (int)S, (long long)C*S,\n pw_w.data_ptr<float>(), C, 0LL,\n &beta,\n out.data_ptr<float>(), (int)S, (long long)OC*S,\n N);\n TORCH_CHECK(stat==CUBLAS_STATUS_SUCCESS, \"cublasSgemmStridedBatched failed\");\n if(pw_b.numel()) add_bias_launcher(out.data_ptr<float>(), pw_b.data_ptr<float>(), OC, S, (long long)N*OC*S, stream);\n return out;\n}\n'''\n\ncuda_sources = r'''\n#include <cuda_runtime.h>\n__global__ void dw3(const float* __restrict__ x,const float* __restrict__ w,const float* __restrict__ b,float* __restrict__ y,int N,int C,int H,int W,bool has_bias){\n const int ITEMS=4; int plane=blockIdx.y; int n=plane/C; int c=plane-n*C; int base=(blockIdx.x*blockDim.x+threadIdx.x)*ITEMS; int S=H*W;\n const float* xb=x+((long)n*C+c)*S; const float* wb=w+(long)c*9; float* yb=y+((long)n*C+c)*S;\n float w00=wb[0],w01=wb[1],w02=wb[2],w10=wb[3],w11=wb[4],w12=wb[5],w20=wb[6],w21=wb[7],w22=wb[8];\n #pragma unroll\n for(int it=0;it<ITEMS;++it){int idx=base+it; if(idx<S){int h=idx/W; int col=idx-h*W; float acc=has_bias?b[c]:0.f;\n if(h>0){int r=idx-W; if(col>0) acc=fmaf(xb[r-1],w00,acc); acc=fmaf(xb[r],w01,acc); if(col<W-1) acc=fmaf(xb[r+1],w02,acc);} \n if(col>0) acc=fmaf(xb[idx-1],w10,acc); acc=fmaf(xb[idx],w11,acc); if(col<W-1) acc=fmaf(xb[idx+1],w12,acc);\n if(h<H-1){int r=idx+W; if(col>0) acc=fmaf(xb[r-1],w20,acc); acc=fmaf(xb[r],w21,acc); if(col<W-1) acc=fmaf(xb[r+1],w22,acc);} yb[idx]=acc;}}\n}\n__global__ void dwgen(const float* __restrict__ x,const float* __restrict__ w,const float* __restrict__ b,float* __restrict__ y,int N,int C,int H,int W,int K,int stride,int pad,int dil,int Ho,int Wo,bool has_bias){\n const int ITEMS=2; int plane=blockIdx.y; int n=plane/C; int c=plane-n*C; int base=(blockIdx.x*blockDim.x+threadIdx.x)*ITEMS; int S=Ho*Wo; const float* xb=x+((long)n*C+c)*H*W; const float* wb=w+(long)c*K*K; float* yb=y+((long)n*C+c)*S;\n #pragma unroll\n for(int it=0;it<ITEMS;++it){int idx=base+it; if(idx<S){int oh=idx/Wo, ow=idx-oh*Wo; float acc=has_bias?b[c]:0.f; int ih0=oh*stride-pad, iw0=ow*stride-pad; for(int kh=0;kh<K;++kh){int ih=ih0+kh*dil; if((unsigned)ih<(unsigned)H){for(int kw=0;kw<K;++kw){int iw=iw0+kw*dil; if((unsigned)iw<(unsigned)W) acc=fmaf(xb[ih*W+iw], wb[kh*K+kw], acc);}}} yb[idx]=acc;}}\n}\n__global__ void add_bias(float* __restrict__ y,const float* __restrict__ b,int OC,long S,long total){long idx=(long)blockIdx.x*blockDim.x+threadIdx.x; if(idx<total){int oc=(int)((idx/S)%OC); y[idx]+=b[oc];}}\nvoid depthwise_kernel_launcher(const float* x,const float* w,const float* b,float* y,int N,int C,int H,int W,int K,int stride,int pad,int dil,int Ho,int Wo,bool has_bias,cudaStream_t stream){dim3 block(256); int S=Ho*Wo; if(K==3&&stride==1&&pad==1&&dil==1&&Ho==H&&Wo==W){dim3 grid((S+block.x*4-1)/(block.x*4),N*C); dw3<<<grid,block,0,stream>>>(x,w,b,y,N,C,H,W,has_bias);} else {dim3 grid((S+block.x*2-1)/(block.x*2),N*C); dwgen<<<grid,block,0,stream>>>(x,w,b,y,N,C,H,W,K,stride,pad,dil,Ho,Wo,has_bias);}}\nvoid add_bias_launcher(float* y,const float* b,int OC,long S,long total,cudaStream_t stream){dim3 block(256); dim3 grid((total+255)/256); add_bias<<<grid,block,0,stream>>>(y,b,OC,S,total);}\n'''\n_ext=load_inline(name='dwsep_ext_finaltest', cpp_sources=cpp_sources, cuda_sources=cuda_sources, functions=['depthwise_sep_forward'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], extra_ldflags=['-lcublas'], verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self, in_channels:int, out_channels:int, kernel_size:int, stride:int=1, padding:int=0, dilation:int=1, bias:bool=False):\n super().__init__(); self.depthwise=nn.Conv2d(in_channels,in_channels,kernel_size,stride=stride,padding=padding,dilation=dilation,groups=in_channels,bias=bias); self.pointwise=nn.Conv2d(in_channels,out_channels,1,bias=bias); self.stride=stride; self.padding=padding; self.dilation=dilation; self._empty=None\n def forward(self,x:torch.Tensor)->torch.Tensor:\n if self._empty is None or self._empty.device!=x.device or self._empty.dtype!=x.dtype: self._empty=torch.empty(0,device=x.device,dtype=x.dtype)\n return _ext.depthwise_sep_forward(x,self.depthwise.weight,self.pointwise.weight,self.depthwise.bias if self.depthwise.bias is not None else self._empty,self.pointwise.bias if self.pointwise.bias is not None else self._empty,self.stride,self.padding,self.dilation)\n"
}