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\ncpp_src = r'''\n#include <torch/extension.h>\n#include <vector>\nstd::vector<torch::Tensor> prepare_v_gate(torch::Tensor projected, torch::Tensor w0, torch::Tensor b0, torch::Tensor w1, torch::Tensor b1, int64_t seq_len);\ntorch::Tensor prepare_h(torch::Tensor fw1, torch::Tensor fb1, torch::Tensor fw2, torch::Tensor fb2, int64_t seq_len);\nvoid mul_freq_inplace(torch::Tensor vf, torch::Tensor hf);\ntorch::Tensor apply_gate_transpose(torch::Tensor y, torch::Tensor gate, int64_t L);\n'''\n\ncuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <vector>\n#include <cmath>\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_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x)\n\n__global__ void prep_v_gate_kernel(const float* __restrict__ proj,\n const float* __restrict__ cw0, const float* __restrict__ cb0,\n const float* __restrict__ cw1, const float* __restrict__ cb1,\n float* __restrict__ vpad, float* __restrict__ gate,\n int B, int L, int D, int K, int N) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)B * L * D;\n if (idx >= total) return;\n int d = idx % D;\n long long q = idx / D;\n int t = q % L;\n int b = q / L;\n int threeD = 3 * D;\n const float* base = proj + ((long long)b * L + t) * threeD;\n vpad[((long long)b * D + d) * N + t] = base[d];\n int pad = K >> 1;\n float g0 = cb0[d];\n float g1 = cb1[d];\n #pragma unroll\n for (int r = 0; r < 8; ++r) {\n if (r < K) {\n int tt = t + r - pad;\n if ((unsigned)tt < (unsigned)L) {\n const float* p = proj + ((long long)b * L + tt) * threeD;\n g0 += cw0[d * K + r] * p[D + d];\n g1 += cw1[d * K + r] * p[2 * D + d];\n }\n }\n }\n gate[((long long)b * L + t) * D + d] = g0 * g1;\n}\n\n__global__ void zero_second_half_kernel(float* __restrict__ vpad, int B, int D, int L, int N) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)B * D * L;\n if (idx >= total) return;\n int t = idx % L;\n long long bd = idx / L;\n vpad[bd * N + L + t] = 0.0f;\n}\n\n__global__ void prep_h_kernel(const float* __restrict__ fw1, const float* __restrict__ fb1,\n const float* __restrict__ fw2, const float* __restrict__ fb2,\n float* __restrict__ hpad, int D, int L, int N) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)D * N;\n if (idx >= total) return;\n int t = idx % N;\n int d = idx / N;\n if (t >= L) { hpad[(long long)d * N + t] = 0.0f; return; }\n float x = (L > 1) ? ((float)t / (float)(L - 1)) : 0.0f;\n float acc = fb2[d];\n #pragma unroll\n for (int j = 0; j < 64; ++j) {\n float z = x * fw1[j] + fb1[j];\n float a = z / (1.0f + expf(-z));\n acc += a * fw2[d * 64 + j];\n }\n hpad[(long long)d * N + t] = acc;\n}\n\n__global__ void cmul_broadcast_inplace_kernel(float2* __restrict__ vf, const float2* __restrict__ hf, int B, int D, int F) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)B * D * F;\n if (idx >= total) return;\n int f = idx % F;\n int d = (idx / F) % D;\n float2 a = vf[idx];\n float2 b = hf[(long long)d * F + f];\n vf[idx] = make_float2(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);\n}\n\n__global__ void apply_gate_transpose_kernel(const float* __restrict__ y, const float* __restrict__ gate,\n float* __restrict__ out, int B, int L, int D, int N) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)B * L * D;\n if (idx >= total) return;\n int d = idx % D;\n long long q = idx / D;\n int t = q % L;\n int b = q / L;\n out[idx] = y[((long long)b * D + d) * N + t] * gate[((long long)b * L + t) * D + d];\n}\n\nstd::vector<torch::Tensor> prepare_v_gate(torch::Tensor projected, torch::Tensor w0, torch::Tensor b0, torch::Tensor w1, torch::Tensor b1, int64_t seq_len) {\n CHECK_INPUT(projected); CHECK_INPUT(w0); CHECK_INPUT(b0); CHECK_INPUT(w1); CHECK_INPUT(b1);\n int B = projected.size(0), L = projected.size(1), D = projected.size(2) / 3, K = w0.size(2), N = (int)(2 * seq_len);\n auto vpad = torch::empty({B, D, N}, projected.options());\n auto gate = torch::empty({B, L, D}, projected.options());\n const int threads = 256;\n long long total = (long long)B * L * D;\n prep_v_gate_kernel<<<(total + threads - 1) / threads, threads>>>(projected.data_ptr<float>(), w0.data_ptr<float>(), b0.data_ptr<float>(), w1.data_ptr<float>(), b1.data_ptr<float>(), vpad.data_ptr<float>(), gate.data_ptr<float>(), B, L, D, K, N);\n long long ztotal = (long long)B * D * (N - L);\n zero_second_half_kernel<<<(ztotal + threads - 1) / threads, threads>>>(vpad.data_ptr<float>(), B, D, L, N);\n return {vpad, gate};\n}\n\ntorch::Tensor prepare_h(torch::Tensor fw1, torch::Tensor fb1, torch::Tensor fw2, torch::Tensor fb2, int64_t seq_len) {\n CHECK_INPUT(fw1); CHECK_INPUT(fb1); CHECK_INPUT(fw2); CHECK_INPUT(fb2);\n int D = fw2.size(0), L = (int)seq_len, N = 2 * L;\n auto hpad = torch::empty({D, N}, fw2.options());\n const int threads = 256;\n long long total = (long long)D * N;\n prep_h_kernel<<<(total + threads - 1) / threads, threads>>>(fw1.data_ptr<float>(), fb1.data_ptr<float>(), fw2.data_ptr<float>(), fb2.data_ptr<float>(), hpad.data_ptr<float>(), D, L, N);\n return hpad;\n}\n\nvoid mul_freq_inplace(torch::Tensor vf, torch::Tensor hf) {\n CHECK_CUDA(vf); CHECK_CUDA(hf); CHECK_CONTIGUOUS(vf); CHECK_CONTIGUOUS(hf);\n int B = vf.size(0), D = vf.size(1), F = vf.size(2);\n const int threads = 256;\n long long total = (long long)B * D * F;\n cmul_broadcast_inplace_kernel<<<(total + threads - 1) / threads, threads>>>(reinterpret_cast<float2*>(vf.data_ptr<c10::complex<float>>()), reinterpret_cast<const float2*>(hf.data_ptr<c10::complex<float>>()), B, D, F);\n}\n\ntorch::Tensor apply_gate_transpose(torch::Tensor y, torch::Tensor gate, int64_t Larg) {\n CHECK_INPUT(y); CHECK_INPUT(gate);\n int B = y.size(0), D = y.size(1), N = y.size(2), L = (int)Larg;\n auto out = torch::empty({B, L, D}, y.options());\n const int threads = 256;\n long long total = (long long)B * L * D;\n apply_gate_transpose_kernel<<<(total + threads - 1) / threads, threads>>>(y.data_ptr<float>(), gate.data_ptr<float>(), out.data_ptr<float>(), B, L, D, N);\n return out;\n}\n'''\n\n_ext = load_inline(name='hyena_order2_ext_final', cpp_sources=cpp_src, cuda_sources=cuda_src,\n functions=['prepare_v_gate', 'prepare_h', 'mul_freq_inplace', 'apply_gate_transpose'],\n extra_cuda_cflags=['-O3'], extra_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, d_model: int, seq_len: int, order: int, short_filter_size: int):\n super(ModelNew, self).__init__()\n self.d_model = d_model\n self.seq_len = seq_len\n self.order = order\n self.fft_size = 2 * seq_len\n self.in_proj = nn.Linear(d_model, d_model * (order + 1), bias=True)\n self.short_convs = nn.ModuleList([\n nn.Conv1d(d_model, d_model, short_filter_size,\n padding=short_filter_size // 2, groups=d_model)\n for _ in range(order)\n ])\n self.filter_mlp = nn.Sequential(nn.Linear(1, 64), nn.SiLU(), nn.Linear(64, d_model))\n self.register_buffer('filter_positions', torch.linspace(0, 1, seq_len).unsqueeze(-1))\n self.out_proj = nn.Linear(d_model, d_model, bias=True)\n self._hf_cache = None\n self._hf_cache_key = None\n\n def _get_hf(self):\n key = (self.filter_mlp[0].weight._version, self.filter_mlp[0].bias._version,\n self.filter_mlp[2].weight._version, self.filter_mlp[2].bias._version,\n self.filter_mlp[0].weight.data_ptr(), self.filter_mlp[0].bias.data_ptr(),\n self.filter_mlp[2].weight.data_ptr(), self.filter_mlp[2].bias.data_ptr(),\n self.filter_mlp[2].weight.device.index)\n if self._hf_cache is None or self._hf_cache_key != key:\n hpad = _ext.prepare_h(self.filter_mlp[0].weight.contiguous(), self.filter_mlp[0].bias.contiguous(),\n self.filter_mlp[2].weight.contiguous(), self.filter_mlp[2].bias.contiguous(),\n self.seq_len)\n self._hf_cache = torch.fft.rfft(hpad, dim=-1)\n self._hf_cache_key = key\n return self._hf_cache\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n projected = F.linear(x, self.in_proj.weight, self.in_proj.bias)\n vpad, gate = _ext.prepare_v_gate(projected.contiguous(),\n self.short_convs[0].weight.contiguous(), self.short_convs[0].bias.contiguous(),\n self.short_convs[1].weight.contiguous(), self.short_convs[1].bias.contiguous(),\n self.seq_len)\n vf = torch.fft.rfft(vpad, dim=-1)\n _ext.mul_freq_inplace(vf, self._get_hf())\n y = torch.fft.irfft(vf, n=self.fft_size, dim=-1)\n yt = _ext.apply_gate_transpose(y, gate, x.shape[1])\n return F.linear(yt, self.out_proj.weight, self.out_proj.bias)\n"
}