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>\ntorch::Tensor conv3d_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias,\n int64_t stride, int64_t padding, int64_t dilation, int64_t groups);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__constant__ float c_weight[8192];\n\n__global__ void conv3d_c3k3s1p0_vec4_const_kernel(const float* __restrict__ x,\n const float* __restrict__ b,\n float* __restrict__ out,\n int N, int D, int H, int W,\n int OC, int OD, int OH, int OW,\n int has_bias) {\n int groupsW = (OW + 3) >> 2;\n long long total = (long long)N * OC * OD * OH * groupsW;\n long long tid = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int gw = tid % groupsW;\n long long t = tid / groupsW;\n int oh = t % OH; t /= OH;\n int od = t % OD; t /= OD;\n int oc = t % OC; t /= OC;\n int n = (int)t;\n int ow = gw << 2;\n float a0 = has_bias ? b[oc] : 0.0f;\n float a1 = a0, a2 = a0, a3 = a0;\n const int HW = H * W;\n const int DHW = D * HW;\n const float* xbase = x + ((long long)n * 3 * D + od) * HW + oh * W + ow;\n int wbase = oc * 81;\n if (ow + 3 < OW) {\n #pragma unroll\n for (int c = 0; c < 3; ++c) {\n const float* xc = xbase + (long long)c * DHW;\n #pragma unroll\n for (int kz = 0; kz < 3; ++kz) {\n #pragma unroll\n for (int ky = 0; ky < 3; ++ky) {\n const float* xp = xc + kz * HW + ky * W;\n float x0 = __ldg(xp + 0), x1 = __ldg(xp + 1), x2 = __ldg(xp + 2);\n float x3 = __ldg(xp + 3), x4 = __ldg(xp + 4), x5 = __ldg(xp + 5);\n int wo = wbase + c*27 + kz*9 + ky*3;\n float w0 = c_weight[wo + 0], w1 = c_weight[wo + 1], w2 = c_weight[wo + 2];\n a0 = fmaf(w0, x0, a0); a0 = fmaf(w1, x1, a0); a0 = fmaf(w2, x2, a0);\n a1 = fmaf(w0, x1, a1); a1 = fmaf(w1, x2, a1); a1 = fmaf(w2, x3, a1);\n a2 = fmaf(w0, x2, a2); a2 = fmaf(w1, x3, a2); a2 = fmaf(w2, x4, a2);\n a3 = fmaf(w0, x3, a3); a3 = fmaf(w1, x4, a3); a3 = fmaf(w2, x5, a3);\n }\n }\n }\n float* op = out + ((((long long)n * OC + oc) * OD + od) * OH + oh) * OW + ow;\n op[0] = a0; op[1] = a1; op[2] = a2; op[3] = a3;\n } else {\n #pragma unroll\n for (int c = 0; c < 3; ++c) {\n const float* xc = xbase + (long long)c * DHW;\n #pragma unroll\n for (int kz = 0; kz < 3; ++kz) {\n #pragma unroll\n for (int ky = 0; ky < 3; ++ky) {\n const float* xp = xc + kz * HW + ky * W;\n float x0 = __ldg(xp + 0), x1 = __ldg(xp + 1), x2 = __ldg(xp + 2);\n float x3 = (ow + 1 < OW) ? __ldg(xp + 3) : 0.0f;\n int wo = wbase + c*27 + kz*9 + ky*3;\n float w0 = c_weight[wo + 0], w1 = c_weight[wo + 1], w2 = c_weight[wo + 2];\n a0 = fmaf(w0, x0, a0); a0 = fmaf(w1, x1, a0); a0 = fmaf(w2, x2, a0);\n if (ow + 1 < OW) { a1 = fmaf(w0, x1, a1); a1 = fmaf(w1, x2, a1); a1 = fmaf(w2, x3, a1); }\n }\n }\n }\n float* op = out + ((((long long)n * OC + oc) * OD + od) * OH + oh) * OW + ow;\n op[0] = a0; if (ow + 1 < OW) op[1] = a1;\n }\n}\n\n__global__ void conv3d_c3k3s1p0_vec4_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ b,\n float* __restrict__ out,\n int N, int D, int H, int W,\n int OC, int OD, int OH, int OW,\n int has_bias) {\n int groupsW = (OW + 3) >> 2;\n long long total = (long long)N * OC * OD * OH * groupsW;\n long long tid = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int gw = tid % groupsW;\n long long t = tid / groupsW;\n int oh = t % OH; t /= OH; int od = t % OD; t /= OD; int oc = t % OC; t /= OC; int n = (int)t;\n int ow = gw << 2;\n float a0 = has_bias ? b[oc] : 0.0f; float a1 = a0, a2 = a0, a3 = a0;\n const int HW = H * W, DHW = D * HW;\n const float* xbase = x + ((long long)n * 3 * D + od) * HW + oh * W + ow;\n const float* wp = w + (long long)oc * 81;\n if (ow + 3 < OW) {\n #pragma unroll\n for (int c=0;c<3;++c){ const float* xc=xbase+(long long)c*DHW;\n #pragma unroll\n for(int kz=0;kz<3;++kz){\n #pragma unroll\n for(int ky=0;ky<3;++ky){ const float* xp=xc+kz*HW+ky*W;\n float x0=__ldg(xp),x1=__ldg(xp+1),x2=__ldg(xp+2),x3=__ldg(xp+3),x4=__ldg(xp+4),x5=__ldg(xp+5);\n float w0=__ldg(wp+c*27+kz*9+ky*3),w1=__ldg(wp+c*27+kz*9+ky*3+1),w2=__ldg(wp+c*27+kz*9+ky*3+2);\n a0=fmaf(w0,x0,a0);a0=fmaf(w1,x1,a0);a0=fmaf(w2,x2,a0);\n a1=fmaf(w0,x1,a1);a1=fmaf(w1,x2,a1);a1=fmaf(w2,x3,a1);\n a2=fmaf(w0,x2,a2);a2=fmaf(w1,x3,a2);a2=fmaf(w2,x4,a2);\n a3=fmaf(w0,x3,a3);a3=fmaf(w1,x4,a3);a3=fmaf(w2,x5,a3);\n }}}\n float* op=out+((((long long)n*OC+oc)*OD+od)*OH+oh)*OW+ow; op[0]=a0;op[1]=a1;op[2]=a2;op[3]=a3;\n } else {\n #pragma unroll\n for (int c=0;c<3;++c){ const float* xc=xbase+(long long)c*DHW;\n #pragma unroll\n for(int kz=0;kz<3;++kz){\n #pragma unroll\n for(int ky=0;ky<3;++ky){ const float* xp=xc+kz*HW+ky*W;\n float x0=__ldg(xp),x1=__ldg(xp+1),x2=__ldg(xp+2),x3=(ow+1<OW)?__ldg(xp+3):0.0f;\n float w0=__ldg(wp+c*27+kz*9+ky*3),w1=__ldg(wp+c*27+kz*9+ky*3+1),w2=__ldg(wp+c*27+kz*9+ky*3+2);\n a0=fmaf(w0,x0,a0);a0=fmaf(w1,x1,a0);a0=fmaf(w2,x2,a0); if(ow+1<OW){a1=fmaf(w0,x1,a1);a1=fmaf(w1,x2,a1);a1=fmaf(w2,x3,a1);} \n }}}\n float* op=out+((((long long)n*OC+oc)*OD+od)*OH+oh)*OW+ow; op[0]=a0; if(ow+1<OW) op[1]=a1;\n }\n}\n\n__global__ void conv3d_generic_kernel(const float* __restrict__ x,const float* __restrict__ w,const float* __restrict__ b,float* __restrict__ out,int N,int C,int D,int H,int W,int OC,int KD,int KH,int KW,int OD,int OH,int OW,int stride,int padding,int dilation,int has_bias){\n long long total=(long long)N*OC*OD*OH*OW; long long idx=(long long)blockIdx.x*blockDim.x+threadIdx.x; if(idx>=total)return;\n int ow=idx%OW; long long t=idx/OW; int oh=t%OH; t/=OH; int od=t%OD; t/=OD; int oc=t%OC; t/=OC; int n=(int)t; float sum=has_bias?b[oc]:0.0f;\n for(int c=0;c<C;++c) for(int kz=0;kz<KD;++kz){int iz=od*stride-padding+kz*dilation; if((unsigned)iz>=(unsigned)D)continue; for(int ky=0;ky<KH;++ky){int iy=oh*stride-padding+ky*dilation; if((unsigned)iy>=(unsigned)H)continue; for(int kx=0;kx<KW;++kx){int ix=ow*stride-padding+kx*dilation; if((unsigned)ix>=(unsigned)W)continue; float xv=x[(((long long)n*C+c)*D+iz)*H*W+iy*W+ix]; float wv=w[(((long long)oc*C+c)*KD+kz)*KH*KW+ky*KW+kx]; sum=fmaf(wv,xv,sum);}}}\n out[idx]=sum;\n}\n\ntorch::Tensor conv3d_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias,\n int64_t stride64, int64_t padding64, int64_t dilation64, int64_t groups64) {\n TORCH_CHECK(x.is_cuda(), \"x must be CUDA\"); TORCH_CHECK(weight.is_cuda(), \"weight must be CUDA\");\n x=x.contiguous(); weight=weight.contiguous();\n int N=(int)x.size(0), C=(int)x.size(1), D=(int)x.size(2), H=(int)x.size(3), W=(int)x.size(4);\n int OC=(int)weight.size(0), KD=(int)weight.size(2), KH=(int)weight.size(3), KW=(int)weight.size(4);\n int stride=(int)stride64, padding=(int)padding64, dilation=(int)dilation64;\n int OD=(D+2*padding-dilation*(KD-1)-1)/stride+1, OH=(H+2*padding-dilation*(KH-1)-1)/stride+1, OW=(W+2*padding-dilation*(KW-1)-1)/stride+1;\n auto out=torch::empty({N,OC,OD,OH,OW}, x.options());\n int has_bias=(bias.defined() && bias.numel()>0)?1:0; const float* bp=has_bias?bias.contiguous().data_ptr<float>():nullptr;\n const int threads=256;\n if(C==3 && KD==3 && KH==3 && KW==3 && stride==1 && padding==0 && dilation==1 && groups64==1 && x.scalar_type()==torch::kFloat32){\n int groupsW=(OW+3)>>2; long long total=(long long)N*OC*OD*OH*groupsW; int blocks=(int)((total+threads-1)/threads);\n if (OC*81 <= 8192) {\n cudaMemcpyToSymbol(c_weight, weight.data_ptr<float>(), (size_t)OC*81*sizeof(float), 0, cudaMemcpyDeviceToDevice);\n conv3d_c3k3s1p0_vec4_const_kernel<<<blocks,threads>>>(x.data_ptr<float>(), bp, out.data_ptr<float>(), N,D,H,W,OC,OD,OH,OW,has_bias);\n } else {\n conv3d_c3k3s1p0_vec4_kernel<<<blocks,threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bp, out.data_ptr<float>(), N,D,H,W,OC,OD,OH,OW,has_bias);\n }\n } else {\n long long total=(long long)N*OC*OD*OH*OW; int blocks=(int)((total+threads-1)/threads);\n conv3d_generic_kernel<<<blocks,threads>>>(x.data_ptr<float>(),weight.data_ptr<float>(),bp,out.data_ptr<float>(),N,C,D,H,W,OC,KD,KH,KW,OD,OH,OW,stride,padding,dilation,has_bias);\n }\n return out;\n}\n\"\"\"\n\n_ext = load_inline(name=\"conv3d_c3k3_ext_v2\", cpp_sources=_cpp_src, cuda_sources=_cuda_src,\n functions=[\"conv3d_forward\"], extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"], verbose=False)\n\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, groups: int = 1, bias: bool = False):\n super(ModelNew, self).__init__()\n self.conv3d = nn.Conv3d(in_channels, out_channels, (kernel_size, kernel_size, kernel_size), stride=stride, padding=padding, dilation=dilation, groups=groups, bias=bias)\n self.stride = stride; self.padding = padding; self.dilation = dilation; self.groups = groups\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n b = self.conv3d.bias if self.conv3d.bias is not None else torch.empty(0, device=x.device, dtype=x.dtype)\n return _ext.conv3d_forward(x, self.conv3d.weight, b, int(self.stride), int(self.padding), int(self.dilation), int(self.groups))\n"
}