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 = r'''\n#include <torch/extension.h>\n\ntorch::Tensor dsconv_forward(torch::Tensor x,\n torch::Tensor pw_w, torch::Tensor pw_b,\n torch::Tensor dw_w, torch::Tensor dw_b,\n torch::Tensor pr_w, torch::Tensor pr_b);\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAGuard.h>\n#include <cublas_v2.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cmath>\n\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be a CUDA tensor\")\n#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x \" must be contiguous\")\n#define CHECK_FLOAT(x) TORCH_CHECK(x.scalar_type() == at::kFloat, #x \" must be float32\")\n\nstatic inline void checkCublas(cublasStatus_t status) {\n TORCH_CHECK(status == CUBLAS_STATUS_SUCCESS, \"cuBLAS error\");\n}\n\n__global__ void depthwise_gelu_kernel(const float* __restrict__ pw,\n const float* __restrict__ pw_b,\n const float* __restrict__ dw_w,\n const float* __restrict__ dw_b,\n float* __restrict__ act,\n int N, int E, int L, int K) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)N * E * L;\n if (idx >= total) return;\n int l = (int)(idx % L);\n long long t = idx / L;\n int e = (int)(t % E);\n // int n = (int)(t / E);\n int pad = K >> 1;\n const float* base = pw + t * (long long)L;\n const float* w = dw_w + (long long)e * K;\n float bp = pw_b[e];\n float sum = dw_b[e];\n #pragma unroll\n for (int j = 0; j < 9; ++j) {\n if (j < K) {\n int ll = l + j - pad;\n if ((unsigned)ll < (unsigned)L) {\n sum = fmaf(w[j], base[ll] + bp, sum);\n }\n }\n }\n const float inv_sqrt2 = 0.70710678118654752440f;\n float y = 0.5f * sum * (1.0f + erff(sum * inv_sqrt2));\n act[idx] = y;\n}\n\n__global__ void add_residual_bias_kernel(float* __restrict__ out,\n const float* __restrict__ residual,\n const float* __restrict__ bias,\n long long total, int C, int L) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int c = (int)((idx / L) % C);\n out[idx] = out[idx] + bias[c] + residual[idx];\n}\n\ntorch::Tensor dsconv_forward(torch::Tensor x,\n torch::Tensor pw_w, torch::Tensor pw_b,\n torch::Tensor dw_w, torch::Tensor dw_b,\n torch::Tensor pr_w, torch::Tensor pr_b) {\n CHECK_CUDA(x); CHECK_CUDA(pw_w); CHECK_CUDA(pw_b); CHECK_CUDA(dw_w); CHECK_CUDA(dw_b); CHECK_CUDA(pr_w); CHECK_CUDA(pr_b);\n CHECK_CONTIGUOUS(x); CHECK_CONTIGUOUS(pw_w); CHECK_CONTIGUOUS(pw_b); CHECK_CONTIGUOUS(dw_w); CHECK_CONTIGUOUS(dw_b); CHECK_CONTIGUOUS(pr_w); CHECK_CONTIGUOUS(pr_b);\n CHECK_FLOAT(x); CHECK_FLOAT(pw_w); CHECK_FLOAT(pw_b); CHECK_FLOAT(dw_w); CHECK_FLOAT(dw_b); CHECK_FLOAT(pr_w); CHECK_FLOAT(pr_b);\n const int N = (int)x.size(0);\n const int C = (int)x.size(1);\n const int L = (int)x.size(2);\n const int E = (int)pw_w.size(0);\n const int K = (int)dw_w.size(2);\n TORCH_CHECK(pw_w.size(1) == C && pr_w.size(0) == C && pr_w.size(1) == E, \"bad weight shapes\");\n c10::cuda::CUDAGuard device_guard(x.device());\n auto opts = x.options();\n auto pw = torch::empty({N, E, L}, opts);\n auto act = torch::empty({N, E, L}, opts);\n auto out = torch::empty({N, C, L}, opts);\n\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n cublasHandle_t handle = at::cuda::getCurrentCUDABlasHandle();\n checkCublas(cublasSetStream(handle, stream));\n checkCublas(cublasSetMathMode(handle, CUBLAS_DEFAULT_MATH));\n const float alpha = 1.0f, beta = 0.0f;\n\n // Per-batch row-major GEMM: pw[n] = pw_w(E,C) @ x[n](C,L)\n checkCublas(cublasSgemmStridedBatched(handle, CUBLAS_OP_N, CUBLAS_OP_N,\n L, E, C,\n &alpha,\n x.data_ptr<float>(), L, (long long)C * L,\n pw_w.data_ptr<float>(), C, 0,\n &beta,\n pw.data_ptr<float>(), L, (long long)E * L,\n N));\n\n long long etotal = (long long)N * E * L;\n int threads = 256;\n int blocks = (int)((etotal + threads - 1) / threads);\n depthwise_gelu_kernel<<<blocks, threads, 0, stream>>>(pw.data_ptr<float>(), pw_b.data_ptr<float>(),\n dw_w.data_ptr<float>(), dw_b.data_ptr<float>(),\n act.data_ptr<float>(), N, E, L, K);\n C10_CUDA_KERNEL_LAUNCH_CHECK();\n\n // out[n] = pr_w(C,E) @ act[n](E,L)\n checkCublas(cublasSgemmStridedBatched(handle, CUBLAS_OP_N, CUBLAS_OP_N,\n L, C, E,\n &alpha,\n act.data_ptr<float>(), L, (long long)E * L,\n pr_w.data_ptr<float>(), E, 0,\n &beta,\n out.data_ptr<float>(), L, (long long)C * L,\n N));\n\n long long ototal = (long long)N * C * L;\n int oblocks = (int)((ototal + threads - 1) / threads);\n add_residual_bias_kernel<<<oblocks, threads, 0, stream>>>(out.data_ptr<float>(), x.data_ptr<float>(),\n pr_b.data_ptr<float>(), ototal, C, L);\n C10_CUDA_KERNEL_LAUNCH_CHECK();\n return out;\n}\n'''\n\n_ext = load_inline(name='dsconv_ext_v1', cpp_sources=_cpp, cuda_sources=_cuda,\n functions=['dsconv_forward'], verbose=False,\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n extra_cflags=['-O3'])\n\nclass ModelNew(nn.Module):\n def __init__(self, channels, expanded_channels, kernel_size):\n super(ModelNew, self).__init__()\n self.pointwise = nn.Conv1d(channels, expanded_channels, 1)\n self.depthwise = nn.Conv1d(expanded_channels, expanded_channels, kernel_size,\n padding=kernel_size // 2, groups=expanded_channels)\n self.activation = nn.GELU()\n self.project_back = nn.Conv1d(expanded_channels, channels, 1)\n def forward(self, x):\n return _ext.dsconv_forward(x.contiguous(),\n self.pointwise.weight.contiguous().view(self.pointwise.out_channels, self.pointwise.in_channels),\n self.pointwise.bias.contiguous(),\n self.depthwise.weight.contiguous(),\n self.depthwise.bias.contiguous(),\n self.project_back.weight.contiguous().view(self.project_back.out_channels, self.project_back.in_channels),\n self.project_back.bias.contiguous())\n"
}