call → submit_kernel
callsubmit_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>\n\ntorch::Tensor forward_cuda(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_src = r\"\"\"\n#include <torch/types.h>\n#include <ATen/ATen.h>\n#include <ATen/Context.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAGuard.h>\n#include <c10/cuda/CUDAException.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cublas_v2.h>\n#include <math.h>\n\n#define CHECK_CUBLAS(expr) do { cublasStatus_t _s = (expr); TORCH_CHECK(_s == CUBLAS_STATUS_SUCCESS, \"cuBLAS error: \", (int)_s); } while (0)\n\n__global__ void depthwise_gelu_kernel(const float* __restrict__ p,\n const float* __restrict__ pw_b,\n const float* __restrict__ dw_w,\n const float* __restrict__ dw_b,\n float* __restrict__ g,\n int B, int E, int L, int K) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)B * E * L;\n if (idx >= total) return;\n\n int l = (int)(idx % L);\n long long t = idx / L;\n int e = (int)(t % E);\n int b = (int)(t / E);\n int pad = K >> 1;\n\n const float* pbe = p + ((long long)b * E + e) * L;\n const float* dwe = dw_w + (long long)e * K;\n float pb = pw_b[e];\n float acc = dw_b[e];\n\n #pragma unroll\n for (int j = 0; j < 16; ++j) {\n if (j >= K) break;\n int src = l + j - pad;\n if ((unsigned)src < (unsigned)L) {\n acc += dwe[j] * (pbe[src] + pb);\n }\n }\n\n const float inv_sqrt2 = 0.70710678118654752440f;\n float gelu = 0.5f * acc * (1.0f + erff(acc * inv_sqrt2));\n g[idx] = gelu;\n}\n\n__global__ void add_residual_bias_kernel(float* __restrict__ y,\n const float* __restrict__ x,\n const float* __restrict__ bias,\n int B, int C, int L) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)B * C * L;\n if (idx >= total) return;\n int l = (int)(idx % L);\n long long t = idx / L;\n int c = (int)(t % C);\n (void)l;\n y[idx] = y[idx] + x[idx] + bias[c];\n}\n\ntorch::Tensor forward_cuda(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 TORCH_CHECK(x.is_cuda(), \"x must be CUDA\");\n TORCH_CHECK(x.scalar_type() == at::kFloat, \"only float32 is supported\");\n TORCH_CHECK(x.is_contiguous(), \"x must be contiguous\");\n TORCH_CHECK(pw_w.is_contiguous() && pw_b.is_contiguous() && dw_w.is_contiguous() && dw_b.is_contiguous() && pr_w.is_contiguous() && pr_b.is_contiguous(), \"weights must be contiguous\");\n\n const c10::cuda::CUDAGuard device_guard(x.device());\n\n int B = (int)x.size(0);\n int C = (int)x.size(1);\n int L = (int)x.size(2);\n int E = (int)pw_w.size(0);\n int K = (int)dw_w.size(2);\n\n auto p = at::empty({B, E, L}, x.options());\n auto g = at::empty({B, E, L}, x.options());\n auto y = at::empty({B, C, L}, x.options());\n\n cublasHandle_t handle = at::cuda::getCurrentCUDABlasHandle();\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n CHECK_CUBLAS(cublasSetStream(handle, stream));\n#if defined(CUBLAS_PEDANTIC_MATH)\n if (at::globalContext().allowTF32CuDNN() || at::globalContext().allowTF32CuBLAS()) {\n CHECK_CUBLAS(cublasSetMathMode(handle, CUBLAS_DEFAULT_MATH));\n } else {\n CHECK_CUBLAS(cublasSetMathMode(handle, CUBLAS_PEDANTIC_MATH));\n }\n#endif\n\n const float alpha = 1.0f;\n const float beta0 = 0.0f;\n\n // Pointwise 1x1 conv as B independent row-major GEMMs:\n // p[b](E x L) = pw_w(E x C) * x[b](C x L), stored contiguous row-major.\n CHECK_CUBLAS(cublasSgemmStridedBatched(\n 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, 0LL,\n &beta0,\n p.data_ptr<float>(), L, (long long)E * L,\n B));\n\n int threads = 256;\n long long total_ge = (long long)B * E * L;\n int blocks_ge = (int)((total_ge + threads - 1) / threads);\n depthwise_gelu_kernel<<<blocks_ge, threads, 0, stream>>>(\n p.data_ptr<float>(), pw_b.data_ptr<float>(), dw_w.data_ptr<float>(), dw_b.data_ptr<float>(),\n g.data_ptr<float>(), B, E, L, K);\n C10_CUDA_KERNEL_LAUNCH_CHECK();\n\n // Project back: y[b](C x L) = pr_w(C x E) * g[b](E x L).\n CHECK_CUBLAS(cublasSgemmStridedBatched(\n handle, CUBLAS_OP_N, CUBLAS_OP_N,\n L, C, E,\n &alpha,\n g.data_ptr<float>(), L, (long long)E * L,\n pr_w.data_ptr<float>(), E, 0LL,\n &beta0,\n y.data_ptr<float>(), L, (long long)C * L,\n B));\n\n long long total_y = (long long)B * C * L;\n int blocks_y = (int)((total_y + threads - 1) / threads);\n add_residual_bias_kernel<<<blocks_y, threads, 0, stream>>>(\n y.data_ptr<float>(), x.data_ptr<float>(), pr_b.data_ptr<float>(), B, C, L);\n C10_CUDA_KERNEL_LAUNCH_CHECK();\n\n return y;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"dsconv1d_fused_cublas_ext\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"forward_cuda\"],\n extra_cuda_cflags=[\"-O3\"],\n extra_ldflags=[\"-lcublas\"],\n with_cuda=True,\n verbose=False,\n)\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\n def forward(self, x):\n return _ext.forward_cuda(x,\n self.pointwise.weight, self.pointwise.bias,\n self.depthwise.weight, self.depthwise.bias,\n self.project_back.weight, self.project_back.bias)\n"
}