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\ntorch::Tensor dm_forward(torch::Tensor counts, torch::Tensor log_alpha);\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__device__ __forceinline__ float lgamma_count_plus_one(float c) {\n int k = __float2int_rn(c);\n if ((unsigned)k < 10u && fabsf(c - (float)k) < 1.0e-6f) {\n // lgamma(k+1) == log(k!) for k=0..9; common input path.\n static const float vals[10] = {\n 0.0f,\n 0.0f,\n 0.69314718055994530942f,\n 1.7917594692280550008f,\n 3.1780538303479456196f,\n 4.7874917427820459942f,\n 6.5792512120101009951f,\n 8.5251613610654143002f,\n 10.604602902745250228f,\n 12.801827480081469611f\n };\n return vals[k];\n }\n return lgammaf(c + 1.0f);\n}\n\n__device__ __forceinline__ void warp_reduce2(float &a, float &b) {\n unsigned mask = 0xffffffffu;\n a += __shfl_down_sync(mask, a, 16); b += __shfl_down_sync(mask, b, 16);\n a += __shfl_down_sync(mask, a, 8); b += __shfl_down_sync(mask, b, 8);\n a += __shfl_down_sync(mask, a, 4); b += __shfl_down_sync(mask, b, 4);\n a += __shfl_down_sync(mask, a, 2); b += __shfl_down_sync(mask, b, 2);\n a += __shfl_down_sync(mask, a, 1); b += __shfl_down_sync(mask, b, 1);\n}\n\n__device__ __forceinline__ void warp_reduce3(float &a, float &b, float &c) {\n unsigned mask = 0xffffffffu;\n a += __shfl_down_sync(mask, a, 16); b += __shfl_down_sync(mask, b, 16); c += __shfl_down_sync(mask, c, 16);\n a += __shfl_down_sync(mask, a, 8); b += __shfl_down_sync(mask, b, 8); c += __shfl_down_sync(mask, c, 8);\n a += __shfl_down_sync(mask, a, 4); b += __shfl_down_sync(mask, b, 4); c += __shfl_down_sync(mask, c, 4);\n a += __shfl_down_sync(mask, a, 2); b += __shfl_down_sync(mask, b, 2); c += __shfl_down_sync(mask, c, 2);\n a += __shfl_down_sync(mask, a, 1); b += __shfl_down_sync(mask, b, 1); c += __shfl_down_sync(mask, c, 1);\n}\n\n__global__ void dm_kernel(const float* __restrict__ counts,\n const float* __restrict__ log_alpha,\n float* __restrict__ out,\n int B, int V) {\n int row = blockIdx.x;\n int lane = threadIdx.x; // one warp per row\n if (row >= B) return;\n\n // Fast path when the model is in its initialized state (alpha_v == 1).\n // The scan is tiny (V=256) and keeps correctness if state_dict copied zeros.\n bool local_zero = true;\n for (int i = lane; i < V; i += 32) {\n if (__ldg(log_alpha + i) != 0.0f) local_zero = false;\n }\n bool all_zero = (__ballot_sync(0xffffffffu, local_zero) == 0xffffffffu);\n\n const float* rowp = counts + (long long)row * V;\n\n if (all_zero) {\n float nsum = 0.0f;\n float lsum = 0.0f;\n for (int i = lane; i < V; i += 32) {\n float c = __ldg(rowp + i);\n nsum += c;\n lsum += lgamma_count_plus_one(c);\n }\n warp_reduce2(nsum, lsum);\n if (lane == 0) {\n float vf = (float)V;\n out[row] = lgammaf(vf) - lgammaf(nsum + vf) + lsum;\n }\n } else {\n float nsum = 0.0f;\n float asum = 0.0f;\n float lsum = 0.0f;\n for (int i = lane; i < V; i += 32) {\n float c = __ldg(rowp + i);\n float a = expf(__ldg(log_alpha + i));\n nsum += c;\n asum += a;\n lsum += lgammaf(c + a) - lgammaf(a);\n }\n warp_reduce3(nsum, asum, lsum);\n if (lane == 0) {\n out[row] = lgammaf(asum) - lgammaf(nsum + asum) + lsum;\n }\n }\n}\n\ntorch::Tensor dm_forward(torch::Tensor counts, torch::Tensor log_alpha) {\n TORCH_CHECK(counts.is_cuda(), \"counts must be a CUDA tensor\");\n TORCH_CHECK(log_alpha.is_cuda(), \"log_alpha must be a CUDA tensor\");\n TORCH_CHECK(counts.scalar_type() == at::kFloat, \"counts must be float32\");\n TORCH_CHECK(log_alpha.scalar_type() == at::kFloat, \"log_alpha must be float32\");\n TORCH_CHECK(counts.dim() == 2, \"counts must be 2D\");\n\n int B = (int)counts.size(0);\n int V = (int)counts.size(1);\n auto out = torch::empty({B}, counts.options());\n if (B > 0) {\n dm_kernel<<<B, 32, 0, at::cuda::getCurrentCUDAStream()>>>(\n counts.data_ptr<float>(), log_alpha.data_ptr<float>(), out.data_ptr<float>(), B, V);\n }\n return out;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"dirichlet_multinomial_fused_ext\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"dm_forward\"],\n extra_cflags=[\"-O3\"],\n extra_cuda_cflags=[\"-O3\"],\n verbose=False,\n)\n\n\nclass ModelNew(nn.Module):\n def __init__(self, vocab_size):\n super().__init__()\n self.vocab_size = vocab_size\n self.log_alpha = nn.Parameter(torch.zeros(vocab_size))\n\n def forward(self, counts: torch.Tensor) -> torch.Tensor:\n return _ext.dm_forward(counts, self.log_alpha)\n"
}