gpt-5.5-priority · popcorn · l123_single_gpt
incorrect 2_GraphEdgeSoftmaxCSR.py
model
gpt-5.5-priority
turns / max
1 / 1
tool calls
1
tokens (total)
0
wall clock
—
truncated
no
backend
cuda fp32
variant
popcorn
runtime
—
ref runtime
19.50 μs
speedup
—
started
2026-05-05T00:07:51Z
correctness issue:
timingkernelbench.timing
kernel runtime
—
ref runtime
19.50 μs
speedup
—
kernel mean / median / std
—
ref mean / median / std
19.50 / — / 0.38 μs
roofline / occupancynsight_hardware_counters
dram bandwidth
—
dram util %
—
fp32 tflops
—
fp32 util %
—
fp16 tflops
—
occupancy %
—
bottleneck
unknown
dominant pipe %
—
arithmetic intensity
—
ridge point
20.00
L1 hit %
—
L2 hit %
—
ld sectors / req
—
st sectors / req
—
regs / thread
—
smem / block
—
block size
—
peak bw
3350.00 GB/s
peak fp32 tflops
67.00
peak fp16 tflops
1979.00
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn


class Model(nn.Module):
    """
    Row-wise softmax over edge scores stored in CSR format.

    This is a core primitive in graph attention networks and sparse attention on
    irregular neighborhoods. Each node owns a contiguous edge segment in
    `edge_scores[row_ptr[i]:row_ptr[i + 1]]`, and the kernel normalizes scores
    independently within each segment.
    """

    def __init__(self):
        super().__init__()

    def forward(
        self,
        row_ptr: torch.Tensor,
        edge_scores: torch.Tensor,
    ) -> torch.Tensor:
        """
        Args:
            row_ptr:      (num_nodes + 1,) CSR row offsets
            edge_scores:  (num_edges,) unnormalized attention logits
        Returns:
            (num_edges,) softmax-normalized edge weights per source node
        """
        num_nodes = row_ptr.numel() - 1
        out = torch.empty_like(edge_scores)

        for node in range(num_nodes):
            start = int(row_ptr[node].item())
            end = int(row_ptr[node + 1].item())
            if end > start:
                out[start:end] = torch.softmax(edge_scores[start:end], dim=0)

        return out


num_nodes = 512
avg_degree = 24
batchless_num_edges = num_nodes * avg_degree


def _make_row_ptr(num_nodes: int, avg_degree: int) -> torch.Tensor:
    base = torch.full((num_nodes,), avg_degree, dtype=torch.int32)
    return row_ptr


def get_inputs():
    return list(popcorn_pri.make_csr_scalar_edge_scores(num_nodes, avg_degree))



def get_init_inputs():
    return []
turn 017.0s turn · 17.0s LLM · 0.0s tools · FINAL
call → submit_kernel
callsubmit_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\n// CUDA launcher implemented in cuda source\ntorch::Tensor csr_softmax_forward_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores);\n\ntorch::Tensor csr_softmax_forward(torch::Tensor row_ptr, torch::Tensor edge_scores) {\n return csr_softmax_forward_cuda(row_ptr, edge_scores);\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 <cfloat>\n\n__device__ __forceinline__ float warp_reduce_max(float v) {\n unsigned mask = 0xffffffffu;\n v = fmaxf(v, __shfl_down_sync(mask, v, 16));\n v = fmaxf(v, __shfl_down_sync(mask, v, 8));\n v = fmaxf(v, __shfl_down_sync(mask, v, 4));\n v = fmaxf(v, __shfl_down_sync(mask, v, 2));\n v = fmaxf(v, __shfl_down_sync(mask, v, 1));\n return v;\n}\n\n__device__ __forceinline__ float warp_reduce_sum(float v) {\n unsigned mask = 0xffffffffu;\n v += __shfl_down_sync(mask, v, 16);\n v += __shfl_down_sync(mask, v, 8);\n v += __shfl_down_sync(mask, v, 4);\n v += __shfl_down_sync(mask, v, 2);\n v += __shfl_down_sync(mask, v, 1);\n return v;\n}\n\ntemplate<int WARPS_PER_BLOCK>\n__global__ void csr_softmax_warp_kernel(const int* __restrict__ row_ptr,\n const float* __restrict__ scores,\n float* __restrict__ out,\n int num_nodes) {\n int tid = threadIdx.x;\n int lane = tid & 31;\n int warp = tid >> 5;\n int row = blockIdx.x * WARPS_PER_BLOCK + warp;\n if (row >= num_nodes) return;\n\n int start = row_ptr[row];\n int end = row_ptr[row + 1];\n int n = end - start;\n if (n <= 0) return;\n\n float m = -FLT_MAX;\n for (int i = lane; i < n; i += 32) {\n m = fmaxf(m, scores[start + i]);\n }\n m = warp_reduce_max(m);\n\n float s = 0.0f;\n for (int i = lane; i < n; i += 32) {\n s += __expf(scores[start + i] - m);\n }\n s = warp_reduce_sum(s);\n float inv_s = 1.0f / s;\n\n for (int i = lane; i < n; i += 32) {\n out[start + i] = __expf(scores[start + i] - m) * inv_s;\n }\n}\n\ntorch::Tensor csr_softmax_forward_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores) {\n auto out = torch::empty_like(edge_scores);\n int num_nodes = (int)row_ptr.numel() - 1;\n if (num_nodes <= 0 || edge_scores.numel() == 0) return out;\n\n const int warps = 4;\n dim3 block(32 * warps);\n dim3 grid((num_nodes + warps - 1) / warps);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n csr_softmax_warp_kernel<warps><<<grid, block, 0, stream>>>(\n row_ptr.data_ptr<int>(), edge_scores.data_ptr<float>(), out.data_ptr<float>(), num_nodes);\n return out;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"csr_row_softmax_ext_v1\",\n cpp_sources=[_cpp_src],\n cuda_sources=[_cuda_src],\n functions=[\"csr_softmax_forward\"],\n extra_cflags=[\"-O3\"],\n extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"],\n verbose=False,\n)\n\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n\n def forward(self, row_ptr: torch.Tensor, edge_scores: torch.Tensor) -> torch.Tensor:\n return _ext.csr_softmax_forward(row_ptr, edge_scores)\n" }
result ← submit_kernel (fail)
failsubmit_kernel submit_kernel FAILED: correctness check did not pass (? trials). runtime_error: expected scalar type Int but found Float
final submitted kernel (109 lines, 3,294 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline

_cpp_src = r"""
#include <torch/extension.h>

// CUDA launcher implemented in cuda source
torch::Tensor csr_softmax_forward_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores);

torch::Tensor csr_softmax_forward(torch::Tensor row_ptr, torch::Tensor edge_scores) {
    return csr_softmax_forward_cuda(row_ptr, edge_scores);
}
"""

_cuda_src = r"""
#include <torch/extension.h>
#include <ATen/cuda/CUDAContext.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <cfloat>

__device__ __forceinline__ float warp_reduce_max(float v) {
    unsigned mask = 0xffffffffu;
    v = fmaxf(v, __shfl_down_sync(mask, v, 16));
    v = fmaxf(v, __shfl_down_sync(mask, v, 8));
    v = fmaxf(v, __shfl_down_sync(mask, v, 4));
    v = fmaxf(v, __shfl_down_sync(mask, v, 2));
    v = fmaxf(v, __shfl_down_sync(mask, v, 1));
    return v;
}

__device__ __forceinline__ float warp_reduce_sum(float v) {
    unsigned mask = 0xffffffffu;
    v += __shfl_down_sync(mask, v, 16);
    v += __shfl_down_sync(mask, v, 8);
    v += __shfl_down_sync(mask, v, 4);
    v += __shfl_down_sync(mask, v, 2);
    v += __shfl_down_sync(mask, v, 1);
    return v;
}

template<int WARPS_PER_BLOCK>
__global__ void csr_softmax_warp_kernel(const int* __restrict__ row_ptr,
                                        const float* __restrict__ scores,
                                        float* __restrict__ out,
                                        int num_nodes) {
    int tid = threadIdx.x;
    int lane = tid & 31;
    int warp = tid >> 5;
    int row = blockIdx.x * WARPS_PER_BLOCK + warp;
    if (row >= num_nodes) return;

    int start = row_ptr[row];
    int end = row_ptr[row + 1];
    int n = end - start;
    if (n <= 0) return;

    float m = -FLT_MAX;
    for (int i = lane; i < n; i += 32) {
        m = fmaxf(m, scores[start + i]);
    }
    m = warp_reduce_max(m);

    float s = 0.0f;
    for (int i = lane; i < n; i += 32) {
        s += __expf(scores[start + i] - m);
    }
    s = warp_reduce_sum(s);
    float inv_s = 1.0f / s;

    for (int i = lane; i < n; i += 32) {
        out[start + i] = __expf(scores[start + i] - m) * inv_s;
    }
}

torch::Tensor csr_softmax_forward_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores) {
    auto out = torch::empty_like(edge_scores);
    int num_nodes = (int)row_ptr.numel() - 1;
    if (num_nodes <= 0 || edge_scores.numel() == 0) return out;

    const int warps = 4;
    dim3 block(32 * warps);
    dim3 grid((num_nodes + warps - 1) / warps);
    cudaStream_t stream = at::cuda::getCurrentCUDAStream();
    csr_softmax_warp_kernel<warps><<<grid, block, 0, stream>>>(
        row_ptr.data_ptr<int>(), edge_scores.data_ptr<float>(), out.data_ptr<float>(), num_nodes);
    return out;
}
"""

_ext = load_inline(
    name="csr_row_softmax_ext_v1",
    cpp_sources=[_cpp_src],
    cuda_sources=[_cuda_src],
    functions=["csr_softmax_forward"],
    extra_cflags=["-O3"],
    extra_cuda_cflags=["-O3", "--use_fast_math"],
    verbose=False,
)


class ModelNew(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, row_ptr: torch.Tensor, edge_scores: torch.Tensor) -> torch.Tensor:
        return _ext.csr_softmax_forward(row_ptr, edge_scores)