FW-GLM-5-1 · popcorn · pop_l123_st_gpt
correct 25_virtual_reduce_scatter_masked_sum.py
model
FW-GLM-5-1
turns / max
1 / 1
tool calls
1
tokens (total)
10401
wall clock
411.7s
truncated
yes
backend
cuda fp32
variant
popcorn
runtime
0.01 μs
ref runtime
0.01 μs
speedup
1.46x
started
2026-05-11T08:55:36Z
timingkernelbench.timing
kernel runtime
0.01 μs
ref runtime
0.01 μs
speedup
1.46x
kernel mean / median / std
0.01 / — / 5.95e-04 μs
ref mean / median / std
0.01 / — / 2.25e-04 μs
numerical precisioneval_kernel_against_ref
max abs error
0.00
mean abs error
0.00
max rel error
0.00
mean rel error
0.00
gpu memoryextended_metrics.measure_memory
kernel peak
0.00 MB
ref peak
0.00 MB
kernel / ref
0.67x
kernel launches / fusiontorch.profiler
kernel launches
4
ref launches
7
fusion ratio (ref / kernel)
1.75x
total cuda time
315 μs
SOL (speed-of-light)nsight_hardware_counters
SOL score (0–1)
9.000e-04
dram util %
0.1%
compute util %
0.0%
bottleneck
unknown
dominant pipe
None
arithmetic intensity
—
ridge point
20.00
roofline / occupancynsight_hardware_counters
dram bandwidth
2.86 GB/s
dram util %
0.1%
fp32 tflops
—
fp32 util %
—
fp16 tflops
—
occupancy %
7.6%
bottleneck
unknown
dominant pipe %
—
arithmetic intensity
—
ridge point
20.00
L1 hit %
—
L2 hit %
199.0%
ld sectors / req
2.00
st sectors / req
—
regs / thread
32
smem / block
2048 B
block size
160
peak bw
3350.00 GB/s
peak fp32 tflops
67.00
peak fp16 tflops
1979.00
warp stalls (top 5)nsight
long_scoreboard
2484.4%
short_scoreboard
285.2%
reference PyTorch source (the prompt the agent sees)
"""
Unequal virtual shard lengths: x is (R, S_MAX) with a fixed boolean mask marking valid cells.
Output (S_MAX,) is sum_r x[r, j] * mask[r, j] (masked sum along the virtual rank dimension).

Padding positions are masked out so they do not contribute.
"""

import torch
import torch.nn as nn

from kernelbench.distributed_collectives import default_device

R = 4
S_MAX = 20

# mask[r, j] == True iff rank r contributes a real value at column j
_MASK_DATA = [
    [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
]


class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.register_buffer(
            "shard_mask",
            torch.tensor(_MASK_DATA, dtype=torch.bool),
            persistent=False,
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        m = self.shard_mask.to(dtype=x.dtype, device=x.device)
        return (x * m).sum(dim=0)


def get_inputs():
    dev = default_device()
    p = popcorn_pri
    return [torch.randn(p.jitter_int(R), p.jitter_int(S_MAX), device=dev)]


def get_init_inputs():
    return []
turn 0 · FINAL · 1 tool call(s) · 411.7s turn · 84.2s LLM · tokens in=1,319 · out=9,082 · total=10,401 · 19,927 chars (click to expand)
turn 0411.7s turn · 84.2s LLM · 327.5s tools · tokens in=1,319 · out=9,082 · total=10,401 · FINAL · reasoning clipped
reasoning
reasoning (truncated 8670 chars): Let me analyze this task: 1. We have a simple operation: multiply a tensor `x` of shape (R, S_MAX) = (4, 20) by a boolean mask, then sum along dimension 0. 2. The mask is fixed and known at compile time: ```python _MASK_DATA = [ [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], # row 0: 8 valid [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], # row 1: 12 valid [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], # row 2: 10 valid [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], # row 3: 18 valid ] ``` 3. The output is (S_MAX,) = (20,) where each element j is sum_r x[r,j] * mask[r,j]. Since the mask is small and fixed, we can hardcode it in the kernel or pass it as a constant buffer. The operation is simple: masked sum reduction along dimension 0. For a simple kernel approach: - Each thread could handle one output element (one column j) - Or we could use shared memory reduction Given that S_MAX = 20 and R = 4, this is a very small problem. A simple kernel with each thread handling one column would work well. Let me write a CUDA kernel: ```cpp __global__ void masked_sum_kernel(const float* __restrict__ x, float* __restrict__ out, const bool* mask, int R, int S_MAX) { int j = blockIdx.x * blockDim.x + threadIdx.x; if (j < S_MAX) { float sum = 0.0f; for (int r = 0; r < R; r++) { if (mask[r * S_MAX + j]) { sum += x[r * S_MAX + j]; } } out[j] = sum; } } ``` But since the mask is known at compile time, we could hardcode it: ```cpp __global__ void masked_sum_kernel_fixed(const float* __restrict__ x, float* __restrict__ out) { int j = blockIdx.x * blockDim.x + threadIdx.x; const int R = 4; const int S_MAX = 20; if (j < S_MAX) { float sum = 0.0f; // Hardcoded mask if (j < 8) sum += x[0 * S_MAX + j]; // row 0 if (j < 12) sum += x[1 * S_MAX + j]; // row 1 if (j < 10) sum += x[2 * S_MAX + j]; // row 2 if (j < 18) sum += x[3 * S_MAX + j]; // row 3 out[j] = sum; } } ``` Wait, let me check the mask more carefully: - Row 0: columns 0-7 are valid (8 columns) - Row 1: columns 0-11 are valid (12 columns) - Row 2: columns 0-9 are valid (10 columns) - Row 3: columns 0-17 are valid (18 columns) So for each column j: - j < 8: sum x[0,j] + x[1,j] + x[2,j] + x[3,j] (all 4 rows contribute) - 8 <= j < 10: sum x[1,j] + x[2,j] + x[3,j] (rows 1, 2, 3) - 10 <= j < 12: sum x[1,j] + x[3,j] (rows 1, 3) - 12 <= j < 18: sum x[3,j] (only row 3) - j >= 18: sum = 0 (no valid rows) Let me verify: ``` Mask: [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], # row 0: valid at j=0-7 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], # row 1: valid at j=0-11 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], # row 2: valid at j=0-9 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], # row 3: valid at j=0-17 ``` So: - j=0-7: all 4 rows have mask=1 → sum all 4 - j=8-9: rows 1,2,3 have mask=1 (row 0 is 0) → sum 3 rows - j=10-11: rows 1,3 have mask=1 (rows 0,2 are 0) → sum 2 rows - j=12-17: only row 3 has mask=1 → sum 1 row - j=18-19: no rows have mask=1 → sum=0 Now, for optimization: 1. Since the problem is small (20 outputs), we can use a single warp 2. We can hardcode the mask since it's fixed 3. Use coalesced memory access by having consecutive threads access consecutive columns Let me write the complete solution: ```python import torch import torch.nn as nn from torch.utils.cpp_extension import load_inline # Compile the CUDA kernel cuda_source = """ __global__ void masked_sum_kernel(const float* __restrict__ x, float* __restrict__ out, int R, int S_MAX) { int j = blockIdx.x * blockDim.x + threadIdx.x; if (j < S_MAX) { float sum = 0.0f; // Hardcoded mask based on _MASK_DATA // Row 0: valid for j < 8 if (j < 8) sum += x[0 * S_MAX + j]; // Row 1: valid for j < 12 if (j < 12) sum += x[1 * S_MAX + j]; // Row 2: valid for j < 10 if (j < 10) sum += x[2 * S_MAX + j]; // Row 3: valid for j < 18 if (j < 18) sum += x[3 * S_MAX + j]; out[j] = sum; } } torch::Tensor masked_sum_cuda(torch::Tensor x) { const int R = 4; const int S_MAX = 20; auto out = torch::zeros({S_MAX}, x.options()); int threads_per_block = 32; // Single warp is enough for 20 elements int blocks = (S_MAX + threads_per_block - 1) / threads_per_block; masked_sum_kernel<<<blocks, threads_per_block>>>( x.data_ptr<float>(), out.data_ptr<float>(), R, S_MAX ); return out; } """ cpp_source = "torch::Tensor masked_sum_cuda(torch::Tensor x);" masked_sum_module = load_inline( name='masked_sum_module', cpp_sources=cpp_source, cuda_sources=cuda_source, functions=['masked_sum_cuda'], verbose=True ) class ModelNew(nn.Module): def __init__(self): super().__init__() self.register_buffer( "shard_mask", torch.tensor(_MASK_DATA, dtype=torch.bool), persistent=False, ) def forward(self, x: torch.Tensor) -> torch.Tensor: return masked_sum_module.masked_sum_cuda(x) ``` Wait, I need to be careful about the mask data. The reference implementation has `_MASK_DATA` defined at module level. Let me include that. Actually, looking more carefully at the structure, I should: 1. Define _MASK_DATA at the module level 2. Use hardcoded values in the kernel (since the mask is fixed) Let me also think about if we need to handle different devices. The reference moves the mask to the device of x. But since we're hardcoding, we don't need to do that. Let me also think about correctness: - The kernel iterates over columns j, and for each column, sums the masked values from each row - The indices for x are [r * S_MAX + j] = [r * 20 + j] which is correct for row-major layout Let me refine the solution: ```python import torch import torch.nn as nn from torch.utils.cpp_extension import load_inline _MASK_DATA = [ [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], ] # Compile the CUDA kernel cuda_source = """ __global__ void masked_sum_kernel(const float* __restrict__ x, float* __restrict__ out) { const int R = 4; const int S_MAX = 20; int j = blockIdx.x * blockDim.x + threadIdx.x; if (j < S_MAX) { float sum = 0.0f; // Hardcoded mask based on _MASK_DATA // Row 0: valid for j < 8 if (j < 8) sum += x[0 * S_MAX + j]; // Row 1: valid for j < 12 if (j < 12) sum += x[1 * S_MAX + j]; // Row 2: valid for j < 10 if (j < 10) sum += x[2 * S_MAX + j]; // Row 3: valid for j < 18 if (j < 18) sum += x[3 * S_MAX + j]; out[j] = sum; } } torch::Tensor masked_sum_cuda(torch::Tensor x) { const int S_MAX = 20; auto out = torch::zeros({S_MAX}, x.options()); int threads_per_block = 32; int blocks = (S_MAX + threads_per_block - 1) / threads_per_block; masked_sum_kernel<<<blocks, threads_per_block>>>( x.data_ptr<float>(), out.data_ptr<float>() ); return out; } """ cpp_source = "torch::Tensor masked_sum_cuda(torch::Tensor x);" masked_sum_module = load_inline( name='masked_sum_module', cpp_sources=cpp_source, cuda_sources=cuda_source, functions=['masked_sum_cuda'], verbose=True ) class ModelNew(nn.Module): def __init__(self): super().__init__() self.register_buffer( "shard_mask", torch.tensor(_MASK_DATA, dtype=torch.bool), persi ...[ omitted 8670 characters ]... ch.tensor(_MASK_DATA, dtype=torch.bool), persistent=False, ) def forward(self, x: torch.Tensor) -> torch.Tensor: return _masked_sum_module.masked_sum_cuda(x) ``` Actually, let me think about whether there's a better way to optimize this. The problem is very small, so: 1. Kernel launch overhead might be significant 2. We could potentially fuse multiple operations But since the reference is just doing `(x * m).sum(dim=0)`, and we're implementing the same logic, I think a simple kernel is the best approach. One more thing: I should ensure the output is on the same device as the input. The `x.options()` in the kernel should handle this, but let me double-check. Actually, looking at the torch API: - `torch::zeros({20}, x.options())` creates a tensor with the same dtype, device, and other options as x. So this should be correct. Let me also think about potential issues: 1. What if the input has a different shape? The reference doesn't check this, so I assume it's always (4, 20). 2. What if the input is on CPU? The kernel will fail. But the reference uses `default_device()` which returns a CUDA device, so this shouldn't happen. I think the solution is complete. Let me finalize it. Actually, I just realized I should also handle the case where the module might already be loaded (if the script is run multiple times). Let me use a unique name for the module. Also, I should consider using `torch::Tensor` properly in C++. Let me make sure the code is correct. One more optimization: I could use `__restrict__` for the pointers to help the compiler optimize memory access. I already have that. Let me also consider using `__ldg()` for read-only cache on the input data. For such a small problem, this might not matter, but it could help with memory access patterns. Actually, let me keep it simple for now. The kernel is already quite optimized with hardcoded values. Final solution: ```python import torch import torch.nn as nn from torch.utils.cpp_extension import load_inline _MASK_DATA = [ [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], ] R = 4 S_MAX = 20 # Compile the CUDA kernel at module load time cuda_source = """ __global__ void masked_sum_kernel(const float* __restrict__ x, float* __restrict__ out) { int j = blockIdx.x * blockDim.x + threadIdx.x; if (j < 20) { float sum = 0.0f; // Hardcoded mask - each row has a specific valid range based on _MASK_DATA if (j < 8) sum += x[j]; // Row 0: valid for j in [0, 8) if (j < 12) sum += x[20 + j]; // Row 1: valid for j in [0, 12) if (j < 10) sum += x[40 + j]; // Row 2: valid for j in [0, 10) if (j < 18) sum += x[60 + j]; // Row 3: valid for j in [0, 18) out[j] = sum; } } torch::Tensor masked_sum_cuda(torch::Tensor x) { if (!x.is_contiguous()) { x = x.contiguous(); } auto out = torch::zeros({20}, x.options()); // Single warp (32 threads) is sufficient for 20 elements masked_sum_kernel<<<1, 32>>>( x.data_ptr<float>(), out.data_ptr<float>() ); return out; } """ cpp_source = "torch::Tensor masked_sum_cuda(torch::Tensor x);" _masked_sum_module = load_inline( name='masked_sum_ext_v1', cpp_sources=cpp_source, cuda_sources=cuda_source, functions=['masked_sum_cuda'], verbose=False, extra_cuda_cflags=['-O3'] ) class ModelNew(nn.Module): def __init__(self): super().__init__() self.register_buffer( "shard_mask", torch.tensor(_MASK_DATA, dtype=torch.bool), persistent=False, ) def forward(self, x: torch.Tensor) -> torch.Tensor: return _masked_sum_module.masked_sum_cuda(x) ``` Wait, I changed the indexing to use direct offsets (j, 20+j, 40+j, 60+j) instead of (0*20+j, 1*20+j, 2*20+j, 3*20+j). Both are equivalent, but the direct offsets might be slightly faster due to simpler arithmetic. Let me double-check: - x is shape (4, 20) = (R, S_MAX) - x[0] is row 0, elements 0-19 - x[1] is row 1, elements 0-19 - etc. In memory (row-major): - x[0][0] = x[0] - x[0][1] = x[1] - ... - x[0][19] = x[19] - x[1][0] = x[20] - ... - x[3][19] = x[79] So for row r and column j, the index is r*20 + j. - Row 0: indices 0-19 - Row 1: indices 20-39 - Row 2: indices 40-59 - Row 3: indices 60-79 My offsets are correct: - x[j] for row 0, column j - x[20+j] for row 1, column j - x[40+j] for row 2, column j - x[60+j] for row 3, column j Great, the solution is correct! Actually, I want to consider one more optimization: we could unroll the loop and use shared memory to reduce global memory access. But since each thread only accesses 4 elements (at most), this might not be worth the overhead. Let me also think about whether we could use warp-level primitives. Since we only have 20 elements to compute, and each element is independent, we don't need any inter-thread communication. I think the current solution is good. Let me finalize it. One last thing: I should make sure the imports are correct. The reference uses: ```python from kernelbench.distributed_collectives import default_device ``` But since I'm not using `default_device()` in my code, I don't need this import. However, I should include it if needed for compatibility. Actually, looking at the code, `get_inputs()` uses `default_device()`, but that's in the reference implementation, not in my `ModelNew` class. So I don't need to import it. Let me also add a check for CUDA availability, just in case: Actually, no - the problem states that the evaluation will run on CUDA, so I don't need to check for that. Final solution: ```python import torch import torch.nn as nn from torch.utils.cpp_extension import load_inline _MASK_DATA = [ [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], ] R = 4 S_MAX = 20 # Compile the CUDA kernel at module load time cuda_source = """ __global__ void masked_sum_kernel(const float* __restrict__ x, float* __restrict__ out) { int j = blockIdx.x * blockDim.x + threadIdx.x; if (j < 20) { float sum = 0.0f; // Hardcoded mask based on _MASK_DATA if (j < 8) sum += x[j]; // Row 0: valid for j in [0, 8) if (j < 12) sum += x[20 + j]; // Row 1: valid for j in [0, 12) if (j < 10) sum += x[40 + j]; // Row 2: valid for j in [0, 10) if (j < 18) sum += x[60 + j]; // Row 3: valid for j in [0, 18) out[j] = sum; } } torch::Tensor masked_sum_cuda(torch::Tensor x) { if (!x.is_contiguous()) { x = x.contiguous(); } auto out = torch::zeros({20}, x.options()); // Single warp (32 threads) is sufficient for 20 elements masked_sum_kernel<<<1, 32>>>( x.data_ptr<float>(), out.data_ptr<float>() ); return out; } """ cpp_source = "torch::Tensor masked_sum_cuda(torch::Tensor x);" _masked_sum_module = load_inline( name='masked_sum_ext_v1', cpp_sources=cpp_source, cuda_sources=cuda_source, functions=['masked_sum_cuda'], verbose=False, extra_cuda_cflags=['-O3'] ) class ModelNew(nn.Module): def __init__(self): super().__init__() self.register_buffer( "shard_mask", torch.tensor(_MASK_DATA, dtype=torch.bool), persistent=False, ) def forward(self, x: torch.Tensor) -> torch.Tensor: return _masked_sum_module.masked_sum_cuda(x) ``` This should be the complete solution. Let me submit it.
call → submit_kernel
callsubmit_kernel { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\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\nR = 4\nS_MAX = 20\n\n# Compile the CUDA kernel at module load time\ncuda_source = \"\"\"\n__global__ void masked_sum_kernel(const float* __restrict__ x, float* __restrict__ out) {\n int j = blockIdx.x * blockDim.x + threadIdx.x;\n \n if (j < 20) {\n float sum = 0.0f;\n \n // Hardcoded mask based on _MASK_DATA\n // Row 0: valid for j in [0, 8)\n if (j < 8) sum += x[j];\n // Row 1: valid for j in [0, 12)\n if (j < 12) sum += x[20 + j];\n // Row 2: valid for j in [0, 10)\n if (j < 10) sum += x[40 + j];\n // Row 3: valid for j in [0, 18)\n if (j < 18) sum += x[60 + j];\n \n out[j] = sum;\n }\n}\n\ntorch::Tensor masked_sum_cuda(torch::Tensor x) {\n if (!x.is_contiguous()) {\n x = x.contiguous();\n }\n \n auto out = torch::zeros({20}, x.options());\n \n // Single warp (32 threads) is sufficient for 20 elements\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_masked_sum_module = load_inline(\n name='masked_sum_ext_v1',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['masked_sum_cuda'],\n verbose=False,\n extra_cuda_cflags=['-O3']\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_module.masked_sum_cuda(x)" }
result ← submit_kernel (ok)
oksubmit_kernel submit_kernel PASSED: (5 / 5) correctness trials all passed. Kernel runtime: 0.01 μs Runtime stats: mean=0.01μs median=?μs std=0.00μs Numerical precision: max_abs_err=0.00e+00 mean_abs_err=0.00e+00 max_rel_err=0.00e+00 Kernel launches: 4 (ref: 7, fusion ratio: 1.75) SOL score: 0.0009
final submitted kernel (75 lines, 2,017 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline

_MASK_DATA = [
    [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
]

R = 4
S_MAX = 20

# Compile the CUDA kernel at module load time
cuda_source = """
__global__ void masked_sum_kernel(const float* __restrict__ x, float* __restrict__ out) {
    int j = blockIdx.x * blockDim.x + threadIdx.x;
    
    if (j < 20) {
        float sum = 0.0f;
        
        // Hardcoded mask based on _MASK_DATA
        // Row 0: valid for j in [0, 8)
        if (j < 8) sum += x[j];
        // Row 1: valid for j in [0, 12)
        if (j < 12) sum += x[20 + j];
        // Row 2: valid for j in [0, 10)
        if (j < 10) sum += x[40 + j];
        // Row 3: valid for j in [0, 18)
        if (j < 18) sum += x[60 + j];
        
        out[j] = sum;
    }
}

torch::Tensor masked_sum_cuda(torch::Tensor x) {
    if (!x.is_contiguous()) {
        x = x.contiguous();
    }
    
    auto out = torch::zeros({20}, x.options());
    
    // Single warp (32 threads) is sufficient for 20 elements
    masked_sum_kernel<<<1, 32>>>(
        x.data_ptr<float>(),
        out.data_ptr<float>()
    );
    
    return out;
}
"""

cpp_source = "torch::Tensor masked_sum_cuda(torch::Tensor x);"

_masked_sum_module = load_inline(
    name='masked_sum_ext_v1',
    cpp_sources=cpp_source,
    cuda_sources=cuda_source,
    functions=['masked_sum_cuda'],
    verbose=False,
    extra_cuda_cflags=['-O3']
)

class ModelNew(nn.Module):
    def __init__(self):
        super().__init__()
        self.register_buffer(
            "shard_mask",
            torch.tensor(_MASK_DATA, dtype=torch.bool),
            persistent=False,
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return _masked_sum_module.masked_sum_cuda(x)