call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n\n_cpp_src = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAGuard.h>\n\nvoid causal_conv1d_fwd_launcher(const float* x, const float* w, const float* bias, float* y,\n int B, int Cin, int L, int Cout, int K, int dilation, bool has_bias,\n cudaStream_t stream);\n\ntorch::Tensor causal_conv_forward(torch::Tensor x, torch::Tensor w, torch::Tensor bias,\n bool has_bias, int64_t dilation) {\n TORCH_CHECK(x.is_cuda(), \"x must be CUDA\");\n TORCH_CHECK(w.is_cuda(), \"weight must be CUDA\");\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"only float32 is supported\");\n TORCH_CHECK(w.scalar_type() == torch::kFloat32, \"only float32 weight is supported\");\n TORCH_CHECK(x.is_contiguous(), \"x must be contiguous\");\n TORCH_CHECK(w.is_contiguous(), \"weight must be contiguous\");\n if (has_bias) {\n TORCH_CHECK(bias.is_cuda(), \"bias must be CUDA\");\n TORCH_CHECK(bias.scalar_type() == torch::kFloat32, \"only float32 bias is supported\");\n TORCH_CHECK(bias.is_contiguous(), \"bias must be contiguous\");\n }\n const c10::cuda::CUDAGuard device_guard(x.device());\n int B = (int)x.size(0);\n int Cin = (int)x.size(1);\n int L = (int)x.size(2);\n int Cout = (int)w.size(0);\n int K = (int)w.size(2);\n auto y = torch::empty({B, Cout, L}, x.options());\n const float* bptr = has_bias ? bias.data_ptr<float>() : nullptr;\n causal_conv1d_fwd_launcher(x.data_ptr<float>(), w.data_ptr<float>(), bptr, y.data_ptr<float>(),\n B, Cin, L, Cout, K, (int)dilation, has_bias,\n at::cuda::getCurrentCUDAStream());\n return y;\n}\n'''\n\n_cuda_src = r'''\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n\n#define BM 32\n#define BN 128\n#define BK 32\n\n__global__ __launch_bounds__(256, 2)\nvoid causal_conv1d_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int B, int Cin, int L, int Cout, int K, int dilation, int has_bias) {\n __shared__ float As[BM][BK];\n __shared__ float Bs[BK][BN];\n\n const int tid = threadIdx.x;\n const int tx = tid & 15; // 0..15\n const int ty = tid >> 4; // 0..15\n\n const int n_block = blockIdx.x * BN;\n const int m_block = blockIdx.y * BM;\n const int row0 = m_block + ty;\n const int row1 = row0 + 16;\n const int totalK = Cin * K;\n const int pad = (K - 1) * dilation;\n\n float acc00=0.f, acc01=0.f, acc02=0.f, acc03=0.f, acc04=0.f, acc05=0.f, acc06=0.f, acc07=0.f;\n float acc10=0.f, acc11=0.f, acc12=0.f, acc13=0.f, acc14=0.f, acc15=0.f, acc16=0.f, acc17=0.f;\n\n for (int kb = 0; kb < totalK; kb += BK) {\n // Load A tile: weights [Cout, Cin, K] viewed as [Cout, Cin*K]\n #pragma unroll\n for (int idx = tid; idx < BM * BK; idx += 256) {\n int r = idx / BK;\n int kk = idx - r * BK;\n int p = kb + kk;\n int oc = m_block + r;\n float v = 0.f;\n if (oc < Cout && p < totalK) {\n int ic = p / K;\n int k = p - ic * K;\n v = w[(oc * Cin + ic) * K + k];\n }\n As[r][kk] = v;\n }\n\n // Load B tile: on-the-fly causal im2col, columns are flattened (batch,time)\n for (int idx = tid; idx < BK * BN; idx += 256) {\n int kk = idx / BN;\n int c = idx - kk * BN;\n int p = kb + kk;\n int n = n_block + c;\n float v = 0.f;\n if (p < totalK && n < B * L) {\n int ic = p / K;\n int k = p - ic * K;\n int b = n / L;\n int t = n - b * L;\n int xt = t + k * dilation - pad;\n if ((unsigned)xt < (unsigned)L) {\n v = x[(b * Cin + ic) * L + xt];\n }\n }\n Bs[kk][c] = v;\n }\n __syncthreads();\n\n #pragma unroll\n for (int kk = 0; kk < BK; ++kk) {\n float a0 = As[ty][kk];\n float a1 = As[ty + 16][kk];\n float b0 = Bs[kk][tx + 0];\n float b1 = Bs[kk][tx + 16];\n float b2 = Bs[kk][tx + 32];\n float b3 = Bs[kk][tx + 48];\n float b4 = Bs[kk][tx + 64];\n float b5 = Bs[kk][tx + 80];\n float b6 = Bs[kk][tx + 96];\n float b7 = Bs[kk][tx + 112];\n acc00 = fmaf(a0, b0, acc00); acc01 = fmaf(a0, b1, acc01);\n acc02 = fmaf(a0, b2, acc02); acc03 = fmaf(a0, b3, acc03);\n acc04 = fmaf(a0, b4, acc04); acc05 = fmaf(a0, b5, acc05);\n acc06 = fmaf(a0, b6, acc06); acc07 = fmaf(a0, b7, acc07);\n acc10 = fmaf(a1, b0, acc10); acc11 = fmaf(a1, b1, acc11);\n acc12 = fmaf(a1, b2, acc12); acc13 = fmaf(a1, b3, acc13);\n acc14 = fmaf(a1, b4, acc14); acc15 = fmaf(a1, b5, acc15);\n acc16 = fmaf(a1, b6, acc16); acc17 = fmaf(a1, b7, acc17);\n }\n __syncthreads();\n }\n\n if (has_bias) {\n if (row0 < Cout) {\n float bv = bias[row0];\n acc00 += bv; acc01 += bv; acc02 += bv; acc03 += bv; acc04 += bv; acc05 += bv; acc06 += bv; acc07 += bv;\n }\n if (row1 < Cout) {\n float bv = bias[row1];\n acc10 += bv; acc11 += bv; acc12 += bv; acc13 += bv; acc14 += bv; acc15 += bv; acc16 += bv; acc17 += bv;\n }\n }\n\n const int offs[8] = {0,16,32,48,64,80,96,112};\n float vals0[8] = {acc00,acc01,acc02,acc03,acc04,acc05,acc06,acc07};\n float vals1[8] = {acc10,acc11,acc12,acc13,acc14,acc15,acc16,acc17};\n\n #pragma unroll\n for (int j = 0; j < 8; ++j) {\n int n = n_block + tx + offs[j];\n if (n < B * L) {\n int b = n / L;\n int t = n - b * L;\n if (row0 < Cout) y[(b * Cout + row0) * L + t] = vals0[j];\n if (row1 < Cout) y[(b * Cout + row1) * L + t] = vals1[j];\n }\n }\n}\n\nvoid causal_conv1d_fwd_launcher(const float* x, const float* w, const float* bias, float* y,\n int B, int Cin, int L, int Cout, int K, int dilation, bool has_bias,\n cudaStream_t stream) {\n dim3 block(256);\n dim3 grid((B * L + BN - 1) / BN, (Cout + BM - 1) / BM);\n causal_conv1d_kernel<<<grid, block, 0, stream>>>(x, w, bias, y, B, Cin, L, Cout, K, dilation, has_bias ? 1 : 0);\n C10_CUDA_KERNEL_LAUNCH_CHECK();\n}\n'''\n\n_ext = load_inline(\n name=\"causal_conv1d_k4_fp32_ext\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"causal_conv_forward\"],\n extra_cflags=[\"-O3\"],\n extra_cuda_cflags=[\"-O3\"],\n with_cuda=True,\n verbose=False,\n)\n\n\nclass ModelNew(nn.Module):\n def __init__(self, in_channels: int, out_channels: int, kernel_size: int, dilation: int = 1, bias: bool = False):\n super(ModelNew, self).__init__()\n self.causal_padding = (kernel_size - 1) * dilation\n self.conv1d = nn.Conv1d(in_channels, out_channels, kernel_size, dilation=dilation, bias=bias)\n self.dilation = dilation\n self.register_buffer(\"_dummy_bias\", torch.empty(0), persistent=False)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n b = self.conv1d.bias\n if b is None:\n return _ext.causal_conv_forward(x, self.conv1d.weight, self._dummy_bias, False, self.dilation)\n else:\n return _ext.causal_conv_forward(x, self.conv1d.weight, b, True, self.dilation)\n"
}