call → compile_kernel
callcompile_kernel
{
"kernel_code": "\"\"\"\nUnequal virtual shard lengths: x is (R, S_MAX) with a fixed boolean mask marking valid cells.\nOutput (S_MAX,) is sum_r x[r, j] * mask[r, j] (masked sum along the virtual rank dimension).\n\"\"\"\n\nimport torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\nfrom kernelbench.distributed_collectives import default_device\n\nR = 4\nS_MAX = 20\n\n# mask[r, j] == True iff rank r contributes a real value at column j\n_MASK_DATA = [\n [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],\n]\n\n\ncuda_source = \"\"\"\n#include <torch/extension.h>\n\n// Constant memory for mask - cached and broadcast to all threads\n// Layout: mask[j * 4 + r] for column-major access (better coalescing)\n// But for row-major: mask[r * 20 + j]\n__constant__ float d_mask[80]; // 4 rows * 20 cols\n\n// Optimized kernel: no shared memory, use constant memory for mask\n__global__ void masked_sum_kernel(const float* __restrict__ x, float* __restrict__ out) {\n int j = threadIdx.x;\n \n if (j < 20) {\n float sum = 0.0f;\n // Access x in column-major-friendly way: x[r * 20 + j]\n // But constant mask is also row-major\n sum += x[0 * 20 + j] * d_mask[0 * 20 + j];\n sum += x[1 * 20 + j] * d_mask[1 * 20 + j];\n sum += x[2 * 20 + j] * d_mask[2 * 20 + j];\n sum += x[3 * 20 + j] * d_mask[3 * 20 + j];\n out[j] = sum;\n }\n}\n\n// Host-side mask data\nstatic const float h_mask[80] = {\n // Row 0: first 8 are 1\n 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n // Row 1: first 12 are 1\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,\n // Row 2: first 10 are 1\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n // Row 3: first 18 are 1\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,\n};\n\ntorch::Tensor masked_sum_cuda(torch::Tensor x) {\n TORCH_CHECK(x.dim() == 2, \"Input must be 2D\");\n TORCH_CHECK(x.size(0) == 4, \"First dimension must be 4\");\n TORCH_CHECK(x.size(1) == 20, \"Second dimension must be 20\");\n TORCH_CHECK(x.is_contiguous(), \"Input must be contiguous\");\n TORCH_CHECK(x.dtype() == torch::kFloat32, \"Input must be float32\");\n \n // Copy mask to constant memory (only needs to be done once, but safe to repeat)\n cudaMemcpyToSymbol(d_mask, h_mask, 80 * sizeof(float));\n \n auto out = torch::empty({20}, x.options());\n \n masked_sum_kernel<<<1, 32>>>(\n x.data_ptr<float>(),\n out.data_ptr<float>()\n );\n \n return out;\n}\n\"\"\"\n\ncpp_source = \"torch::Tensor masked_sum_cuda(torch::Tensor x);\"\n\n# Load the CUDA extension\nmasked_sum_ext = load_inline(\n name=\"masked_sum_ext\",\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=[\"masked_sum_cuda\"],\n extra_cuda_cflags=[\"-O3\"],\n verbose=False,\n)\n\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.register_buffer(\n \"shard_mask\",\n torch.tensor(_MASK_DATA, dtype=torch.bool),\n persistent=False,\n )\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return masked_sum_ext.masked_sum_cuda(x)\n\n\ndef get_inputs():\n dev = default_device()\n g = torch.Generator(device=dev)\n g.manual_seed(8)\n return [torch.randn(R, S_MAX, device=dev, generator=g)]\n\n\ndef get_init_inputs():\n return []"
}