call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n\ntorch::Tensor causal_conv_silu_forward(torch::Tensor x, torch::Tensor w, torch::Tensor bias);\ntorch::Tensor selective_scan_forward(torch::Tensor x, torch::Tensor delta, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\n__global__ void causal_conv_silu_kernel(\n const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ out,\n long sB, long sL, long sI,\n int B, int L, int I, int K)\n{\n long total = (long)B * L * I;\n long idx = (long)blockIdx.x * blockDim.x + threadIdx.x;\n long stride = (long)blockDim.x * gridDim.x;\n for (; idx < total; idx += stride) {\n int i = (int)(idx % I);\n long tmp = idx / I;\n int t = (int)(tmp % L);\n int b = (int)(tmp / L);\n float acc = bias[i];\n // PyTorch Conv1d with padding K-1, returning the first L positions:\n // input index = t + k - (K-1).\n #pragma unroll\n for (int k = 0; k < 8; ++k) {\n if (k < K) {\n int ti = t + k - (K - 1);\n if (ti >= 0) {\n acc += x[(long)b * sB + (long)ti * sL + (long)i * sI] * w[(long)i * K + k];\n }\n }\n }\n float sig = 1.0f / (1.0f + expf(-acc));\n out[idx] = acc * sig;\n }\n}\n\n__global__ void selective_scan_kernel(\n const float* __restrict__ x,\n const float* __restrict__ delta,\n const float* __restrict__ Bt,\n const float* __restrict__ Ct,\n const float* __restrict__ A_log,\n const float* __restrict__ D,\n float* __restrict__ y,\n int B, int L, int I, int N)\n{\n int lane = threadIdx.x & 31;\n int warp_in_block = threadIdx.x >> 5;\n int warps_per_block = blockDim.x >> 5;\n int wi = blockIdx.x * warps_per_block + warp_in_block;\n int total_warps = B * I;\n if (wi >= total_warps) return;\n\n int b = wi / I;\n int i = wi - b * I;\n int n = lane;\n\n float h = 0.0f;\n float aval = 0.0f;\n if (n < N) {\n aval = -expf(A_log[(long)i * N + n]);\n }\n float dskip = D[i];\n\n for (int t = 0; t < L; ++t) {\n long xi = ((long)b * L + t) * I + i;\n float xv = x[xi];\n float del = delta[xi];\n float prod = 0.0f;\n if (n < N) {\n long bcn = ((long)b * L + t) * N + n;\n float da = expf(del * aval);\n h = da * h + (xv * del) * Bt[bcn];\n prod = h * Ct[bcn];\n }\n // warp reduction over the N=16 active lanes (remaining lanes hold zero)\n prod += __shfl_down_sync(0xffffffff, prod, 16);\n prod += __shfl_down_sync(0xffffffff, prod, 8);\n prod += __shfl_down_sync(0xffffffff, prod, 4);\n prod += __shfl_down_sync(0xffffffff, prod, 2);\n prod += __shfl_down_sync(0xffffffff, prod, 1);\n if (lane == 0) {\n y[xi] = prod + xv * dskip;\n }\n }\n}\n\ntorch::Tensor causal_conv_silu_forward(torch::Tensor x, torch::Tensor w, torch::Tensor bias) {\n TORCH_CHECK(x.is_cuda() && w.is_cuda() && bias.is_cuda(), \"tensors must be CUDA\");\n TORCH_CHECK(x.scalar_type() == at::kFloat, \"only float32 is supported\");\n TORCH_CHECK(w.scalar_type() == at::kFloat && bias.scalar_type() == at::kFloat, \"only float32 is supported\");\n int B = (int)x.size(0);\n int L = (int)x.size(1);\n int I = (int)x.size(2);\n int K = (int)w.size(2);\n auto out = torch::empty({B, L, I}, x.options());\n long total = (long)B * L * I;\n int threads = 256;\n int blocks = (int)((total + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n causal_conv_silu_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(\n x.data_ptr<float>(), w.data_ptr<float>(), bias.data_ptr<float>(), out.data_ptr<float>(),\n x.stride(0), x.stride(1), x.stride(2), B, L, I, K);\n return out;\n}\n\ntorch::Tensor selective_scan_forward(torch::Tensor x, torch::Tensor delta, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) {\n TORCH_CHECK(x.is_cuda() && delta.is_cuda() && Bt.is_cuda() && Ct.is_cuda() && A_log.is_cuda() && D.is_cuda(), \"tensors must be CUDA\");\n TORCH_CHECK(x.scalar_type() == at::kFloat, \"only float32 is supported\");\n int B = (int)x.size(0);\n int L = (int)x.size(1);\n int I = (int)x.size(2);\n int N = (int)Bt.size(2);\n auto y = torch::empty_like(x);\n int threads = 128; // 4 warps; each warp scans one (batch, channel)\n int warps_per_block = threads / 32;\n int blocks = (B * I + warps_per_block - 1) / warps_per_block;\n selective_scan_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(\n x.data_ptr<float>(), delta.data_ptr<float>(), Bt.data_ptr<float>(), Ct.data_ptr<float>(),\n A_log.data_ptr<float>(), D.data_ptr<float>(), y.data_ptr<float>(), B, L, I, N);\n return y;\n}\n\"\"\"\n\n_mamba_ext = load_inline(\n name=\"mamba_block_custom_ext_v1\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"causal_conv_silu_forward\", \"selective_scan_forward\"],\n extra_cflags=[\"-O3\"],\n extra_cuda_cflags=[\"-O3\"],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, d_model: int, d_state: int, d_conv: int, expand: int):\n super(ModelNew, self).__init__()\n self.d_model = d_model\n self.d_inner = d_model * expand\n self.d_state = d_state\n self.d_conv = d_conv\n\n self.norm = nn.RMSNorm(d_model)\n self.in_proj = nn.Linear(d_model, self.d_inner * 2, bias=False)\n self.conv1d = nn.Conv1d(self.d_inner, self.d_inner, d_conv,\n padding=d_conv - 1, groups=self.d_inner, bias=True)\n self.activation = nn.SiLU()\n\n self.A_log = nn.Parameter(torch.randn(self.d_inner, d_state))\n self.proj_B = nn.Linear(self.d_inner, d_state, bias=False)\n self.proj_C = nn.Linear(self.d_inner, d_state, bias=False)\n self.proj_delta = nn.Linear(self.d_inner, self.d_inner, bias=True)\n self.D = nn.Parameter(torch.ones(self.d_inner))\n\n self.out_proj = nn.Linear(self.d_inner, d_model, bias=False)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n residual = x\n x_norm = self.norm(x)\n xz = F.linear(x_norm, self.in_proj.weight, None)\n I = self.d_inner\n x_branch = xz[..., :I]\n z = xz[..., I:]\n\n # Fused causal depthwise convolution over the x branch and SiLU activation.\n x_branch = _mamba_ext.causal_conv_silu_forward(x_branch, self.conv1d.weight, self.conv1d.bias)\n\n delta = F.softplus(F.linear(x_branch, self.proj_delta.weight, self.proj_delta.bias))\n B_t = F.linear(x_branch, self.proj_B.weight, None)\n C_t = F.linear(x_branch, self.proj_C.weight, None)\n\n y = _mamba_ext.selective_scan_forward(x_branch, delta, B_t, C_t, self.A_log, self.D)\n z = F.silu(z)\n y = y * z\n y = F.linear(y, self.out_proj.weight, None)\n return y + residual\n"
}