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_src = r'''\n#include <torch/extension.h>\n\ntorch::Tensor hmm_forward_cuda(torch::Tensor observations, torch::Tensor log_init, torch::Tensor log_trans, torch::Tensor log_emit);\n\ntorch::Tensor hmm_forward(torch::Tensor observations, torch::Tensor log_init, torch::Tensor log_trans, torch::Tensor log_emit) {\n return hmm_forward_cuda(observations, log_init, log_trans, log_emit);\n}\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#define S 16\n#define O 64\n\n__global__ void hmm_kernel(const long long* __restrict__ obs,\n const float* __restrict__ log_init,\n const float* __restrict__ log_trans,\n const float* __restrict__ log_emit,\n float* __restrict__ out,\n int B, int T) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n\n __shared__ float pi[S];\n __shared__ float A[S*S];\n __shared__ float E[S*O];\n __shared__ float alpha[S];\n __shared__ float next_alpha[S];\n\n if (tid == 0) {\n float m = log_init[0];\n #pragma unroll\n for (int i = 1; i < S; ++i) m = fmaxf(m, log_init[i]);\n float s = 0.0f;\n #pragma unroll\n for (int i = 0; i < S; ++i) s += expf(log_init[i] - m);\n float lse = m + logf(s);\n #pragma unroll\n for (int i = 0; i < S; ++i) pi[i] = log_init[i] - lse;\n }\n\n if (tid < S) {\n int r = tid;\n float mt = log_trans[r*S];\n #pragma unroll\n for (int j = 1; j < S; ++j) mt = fmaxf(mt, log_trans[r*S + j]);\n float st = 0.0f;\n #pragma unroll\n for (int j = 0; j < S; ++j) st += expf(log_trans[r*S + j] - mt);\n float lset = mt + logf(st);\n #pragma unroll\n for (int j = 0; j < S; ++j) A[r*S + j] = log_trans[r*S + j] - lset;\n\n float me = log_emit[r*O];\n #pragma unroll\n for (int k = 1; k < O; ++k) me = fmaxf(me, log_emit[r*O + k]);\n float se = 0.0f;\n #pragma unroll\n for (int k = 0; k < O; ++k) se += expf(log_emit[r*O + k] - me);\n float lsee = me + logf(se);\n #pragma unroll\n for (int k = 0; k < O; ++k) E[r*O + k] = log_emit[r*O + k] - lsee;\n }\n __syncthreads();\n\n int ob0 = (int)obs[b*T];\n if (tid < S) {\n alpha[tid] = pi[tid] + E[tid*O + ob0];\n }\n __syncthreads();\n\n for (int t = 1; t < T; ++t) {\n int ob = (int)obs[b*T + t];\n if (tid < S) {\n int j = tid;\n float m = alpha[0] + A[j]; // A[0*S+j]\n #pragma unroll\n for (int i = 1; i < S; ++i) {\n float v = alpha[i] + A[i*S + j];\n m = fmaxf(m, v);\n }\n float ss = 0.0f;\n #pragma unroll\n for (int i = 0; i < S; ++i) {\n ss += expf(alpha[i] + A[i*S + j] - m);\n }\n next_alpha[j] = m + logf(ss) + E[j*O + ob];\n }\n __syncthreads();\n if (tid < S) alpha[tid] = next_alpha[tid];\n __syncthreads();\n }\n\n if (tid == 0) {\n float m = alpha[0];\n #pragma unroll\n for (int i = 1; i < S; ++i) m = fmaxf(m, alpha[i]);\n float ss = 0.0f;\n #pragma unroll\n for (int i = 0; i < S; ++i) ss += expf(alpha[i] - m);\n out[b] = m + logf(ss);\n }\n}\n\ntorch::Tensor hmm_forward_cuda(torch::Tensor observations, torch::Tensor log_init, torch::Tensor log_trans, torch::Tensor log_emit) {\n TORCH_CHECK(observations.is_cuda(), \"observations must be CUDA\");\n TORCH_CHECK(log_init.is_cuda() && log_trans.is_cuda() && log_emit.is_cuda(), \"parameters must be CUDA\");\n TORCH_CHECK(log_init.scalar_type() == at::kFloat && log_trans.scalar_type() == at::kFloat && log_emit.scalar_type() == at::kFloat, \"parameters must be float\");\n TORCH_CHECK(observations.scalar_type() == at::kLong, \"observations must be int64\");\n TORCH_CHECK(log_init.size(0) == S && log_trans.size(0) == S && log_trans.size(1) == S && log_emit.size(0) == S && log_emit.size(1) == O, \"only S=16,O=64 supported\");\n int B = (int)observations.size(0);\n int T = (int)observations.size(1);\n auto out = torch::empty({B}, log_init.options());\n const int threads = 32;\n hmm_kernel<<<B, threads, 0, at::cuda::getCurrentCUDAStream()>>>(\n (const long long*)observations.data_ptr<int64_t>(),\n log_init.data_ptr<float>(), log_trans.data_ptr<float>(), log_emit.data_ptr<float>(),\n out.data_ptr<float>(), B, T);\n return out;\n}\n'''\n\n_hmm_ext = load_inline(\n name='hmm_forward_ext_v1',\n cpp_sources=[_cpp_src],\n cuda_sources=[_cuda_src],\n functions=['hmm_forward'],\n extra_cuda_cflags=['-O3'],\n extra_cflags=['-O3'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, num_states, num_obs):\n super().__init__()\n self.num_states = num_states\n self.num_obs = num_obs\n self.log_init = nn.Parameter(torch.zeros(num_states))\n self.log_trans = nn.Parameter(torch.zeros(num_states, num_states))\n self.log_emit = nn.Parameter(torch.zeros(num_states, num_obs))\n\n def forward(self, observations: torch.Tensor) -> torch.Tensor:\n return _hmm_ext.hmm_forward(observations, self.log_init, self.log_trans, self.log_emit)\n"
}