correct
2_GraphEdgeSoftmaxCSR.py
started
2026-05-11T12:08:34Z
timingkernelbench.timing
kernel mean / median / std
0.01 / — / 5.29e-04 μs
ref mean / median / std
1230.00 / — / 0.15 μs
numerical precisioneval_kernel_against_ref
gpu memoryextended_metrics.measure_memory
kernel launches / fusiontorch.profiler
fusion ratio (ref / kernel)
1280.33x
SOL (speed-of-light)nsight_hardware_counters
roofline / occupancynsight_hardware_counters
warp stalls (top 5)nsight
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 0915.1s turn · 3.8s LLM · 911.3s tools · tokens in=1,694 · out=6 · total=2,139
reasoning
The task is to replace the forward computation of a PyTorch model with a custom CUDA kernel. The model performs row-wise softmax over edge scores in CSR format.
The task involves replacing the forward computation of a PyTorch model with a custom CUDA kernel. The model needs to accept the same inputs as the original, maintain the same forward signature, and produce identical numerical results. It operates on data in CSR format, performing a row-wise softmax on edge scores.
call → get_gpu_specs
callget_gpu_specs
{}
result ← get_gpu_specs (ok)
okget_gpu_specs
GPU specs for NVIDIA H100 80GB HBM3:
total memory (runtime): 79.1 GB
spec entry: H100
GPU Architecture: Hopper
GPU Memory: 80GB
Memory Bandwidth: 3.35 TB/s
FP64 TFLOPS: 34
FP64 Tensor Core TFLOPS: 67
FP32 TFLOPS: 67
TF32 Tensor Core TFLOPS: 989 with sparsity
BFLOAT16 Tensore Core TFLOPS: 1979 with sparsity
FP16 Tensor Core TFLOPS: 1979 with sparsity
FP8 Tensor Core TFLOPS: 3958 with sparsity
INT8 Tensor Core TOPS: 3958 with sparsity
Register File Size: 64K 32-bit registers per SM
Maximum number of registers per thread: 255
Maximum number of thread blocks per SM: 32
Shared memory capacity per SM: 228 KB
Maximum shared memory per thread block: 227 KB
turn 189.1s turn · 12.9s LLM · 76.2s tools · tokens in=2,372 · out=505 · total=2,967
reasoning
GPU is H100, lots of power, but for this small problem (512 rows, ~12k edges), it's tiny, so kernel launch overhead etc., but anyway, need faster than PyTorch loop which is slow because of .item() cal...
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = '''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cfloat>\n\n__global__ void csr_softmax_kernel(const int* __restrict__ row_ptr, const float* __restrict__ edge_scores, float* __restrict__ out, int num_nodes) {\n int node = blockIdx.x;\n if (node >= num_nodes) return;\n \n int start = row_ptr[node];\n int end = row_ptr[node + 1];\n int len = end - start;\n if (len <= 0) return;\n \n // Use one thread per row for simplicity, since rows are short\n float max_val = -FLT_MAX;\n for (int i = start; i < end; ++i) {\n max_val = fmaxf(max_val, edge_scores[i]);\n }\n \n float sum = 0.0f;\n for (int i = start; i < end; ++i) {\n sum += expf(edge_scores[i] - max_val);\n }\n \n for (int i = start; i < end; ++i) {\n out[i] = expf(edge_scores[i] - max_val) / sum;\n }\n}\n\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores) {\n int num_nodes = row_ptr.size(0) - 1;\n auto out = torch::empty_like(edge_scores);\n \n dim3 grid(num_nodes);\n dim3 block(1);\n \n csr_softmax_kernel<<<grid, block>>>(\n row_ptr.data_ptr<int>(),\n edge_scores.data_ptr<float>(),\n out.data_ptr<float>(),\n num_nodes\n );\n \n return out;\n}\n'''\n\ncpp_source = '''\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores);\n'''\n\nmodule = load_inline(\n name='csr_softmax',\n cpp_sources=[cpp_source],\n cuda_sources=[cuda_source],\n functions=['csr_softmax_cuda'],\n verbose=True\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.module = module\n \n def forward(self, row_ptr, edge_scores):\n return self.module.csr_softmax_cuda(row_ptr, edge_scores)\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 2416.5s turn · 7.2s LLM · 409.3s tools · tokens in=2,984 · out=506 · total=3,497
reasoning
Compiled successfully. Now check correctness.
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = '''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cfloat>\n\n__global__ void csr_softmax_kernel(const int* __restrict__ row_ptr, const float* __restrict__ edge_scores, float* __restrict__ out, int num_nodes) {\n int node = blockIdx.x;\n if (node >= num_nodes) return;\n \n int start = row_ptr[node];\n int end = row_ptr[node + 1];\n int len = end - start;\n if (len <= 0) return;\n \n // Use one thread per row for simplicity, since rows are short\n float max_val = -FLT_MAX;\n for (int i = start; i < end; ++i) {\n max_val = fmaxf(max_val, edge_scores[i]);\n }\n \n float sum = 0.0f;\n for (int i = start; i < end; ++i) {\n sum += expf(edge_scores[i] - max_val);\n }\n \n for (int i = start; i < end; ++i) {\n out[i] = expf(edge_scores[i] - max_val) / sum;\n }\n}\n\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores) {\n int num_nodes = row_ptr.size(0) - 1;\n auto out = torch::empty_like(edge_scores);\n \n dim3 grid(num_nodes);\n dim3 block(1);\n \n csr_softmax_kernel<<<grid, block>>>(\n row_ptr.data_ptr<int>(),\n edge_scores.data_ptr<float>(),\n out.data_ptr<float>(),\n num_nodes\n );\n \n return out;\n}\n'''\n\ncpp_source = '''\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores);\n'''\n\nmodule = load_inline(\n name='csr_softmax',\n cpp_sources=[cpp_source],\n cuda_sources=[cuda_source],\n functions=['csr_softmax_cuda'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.module = module\n \n def forward(self, row_ptr, edge_scores):\n return self.module.csr_softmax_cuda(row_ptr, edge_scores)\n"
}
result ← run_correctness (fail)
failrun_correctness
run_correctness FAILED: ? trials did not all match.
runtime_error: expected scalar type Int but found Float
turn 3387.9s turn · 6.9s LLM · 381.0s tools · tokens in=3,526 · out=539 · total=4,263
reasoning
Error: row_ptr is int32? Wait, expected Int but found Float? No, the error is probably in data_ptr, but row_ptr should be int.
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = '''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cfloat>\n#include <cstdint>\n\n__global__ void csr_softmax_kernel(const int32_t* __restrict__ row_ptr, const float* __restrict__ edge_scores, float* __restrict__ out, int num_nodes) {\n int node = blockIdx.x;\n if (node >= num_nodes) return;\n \n int start = row_ptr[node];\n int end = row_ptr[node + 1];\n int len = end - start;\n if (len <= 0) return;\n \n float max_val = -FLT_MAX;\n for (int i = start; i < end; ++i) {\n max_val = fmaxf(max_val, edge_scores[i]);\n }\n \n float sum = 0.0f;\n for (int i = start; i < end; ++i) {\n sum += expf(edge_scores[i] - max_val);\n }\n \n for (int i = start; i < end; ++i) {\n out[i] = expf(edge_scores[i] - max_val) / sum;\n }\n}\n\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores) {\n int num_nodes = row_ptr.size(0) - 1;\n auto out = torch::empty_like(edge_scores);\n \n dim3 grid(num_nodes);\n dim3 block(1);\n \n csr_softmax_kernel<<<grid, block>>>(\n row_ptr.data_ptr<int32_t>(),\n edge_scores.data_ptr<float>(),\n out.data_ptr<float>(),\n num_nodes\n );\n \n cudaError_t err = cudaGetLastError();\n if (err != cudaSuccess) {\n printf(\"CUDA error: %s\\\\n\", cudaGetErrorString(err));\n }\n \n return out;\n}\n'''\n\ncpp_source = '''\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores);\n'''\n\nmodule = load_inline(\n name='csr_softmax',\n cpp_sources=[cpp_source],\n cuda_sources=[cuda_source],\n functions=['csr_softmax_cuda'],\n verbose=True\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.module = module\n \n def forward(self, row_ptr, edge_scores):\n return self.module.csr_softmax_cuda(row_ptr, edge_scores)\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 4440.3s turn · 5.4s LLM · 435.0s tools · tokens in=4,280 · out=500 · total=4,792
reasoning
Still verbose true, but passed. Now run correctness again.
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = '''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cfloat>\n#include <cstdint>\n\n__global__ void csr_softmax_kernel(const int32_t* __restrict__ row_ptr, const float* __restrict__ edge_scores, float* __restrict__ out, int num_nodes) {\n int node = blockIdx.x;\n if (node >= num_nodes) return;\n \n int start = row_ptr[node];\n int end = row_ptr[node + 1];\n int len = end - start;\n if (len <= 0) return;\n \n float max_val = -FLT_MAX;\n for (int i = start; i < end; ++i) {\n max_val = fmaxf(max_val, edge_scores[i]);\n }\n \n float sum = 0.0f;\n for (int i = start; i < end; ++i) {\n sum += expf(edge_scores[i] - max_val);\n }\n \n for (int i = start; i < end; ++i) {\n out[i] = expf(edge_scores[i] - max_val) / sum;\n }\n}\n\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores) {\n int num_nodes = row_ptr.size(0) - 1;\n auto out = torch::empty_like(edge_scores);\n \n dim3 grid(num_nodes);\n dim3 block(1);\n \n csr_softmax_kernel<<<grid, block>>>(\n row_ptr.data_ptr<int32_t>(),\n edge_scores.data_ptr<float>(),\n out.data_ptr<float>(),\n num_nodes\n );\n \n return out;\n}\n'''\n\ncpp_source = '''\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores);\n'''\n\nmodule = load_inline(\n name='csr_softmax',\n cpp_sources=[cpp_source],\n cuda_sources=[cuda_source],\n functions=['csr_softmax_cuda'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.module = module\n \n def forward(self, row_ptr, edge_scores):\n return self.module.csr_softmax_cuda(row_ptr, edge_scores)\n"
}
result ← run_correctness (fail)
failrun_correctness
run_correctness FAILED: ? trials did not all match.
runtime_error: expected scalar type Int but found Float
turn 5410.2s turn · 11.6s LLM · 398.7s tools · tokens in=4,821 · out=511 · total=5,580
reasoning
Still same error. The error is likely because row_ptr is int32, but somewhere torch expects Int which is int64?
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = '''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cfloat>\n#include <cstdint>\n\n__global__ void csr_softmax_kernel(const int64_t* __restrict__ row_ptr, const float* __restrict__ edge_scores, float* __restrict__ out, int num_nodes) {\n int node = blockIdx.x;\n if (node >= num_nodes) return;\n \n int64_t start = row_ptr[node];\n int64_t end = row_ptr[node + 1];\n int64_t len = end - start;\n if (len <= 0) return;\n \n float max_val = -FLT_MAX;\n for (int64_t i = start; i < end; ++i) {\n max_val = fmaxf(max_val, edge_scores[i]);\n }\n \n float sum = 0.0f;\n for (int64_t i = start; i < end; ++i) {\n sum += expf(edge_scores[i] - max_val);\n }\n \n for (int64_t i = start; i < end; ++i) {\n out[i] = expf(edge_scores[i] - max_val) / sum;\n }\n}\n\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores) {\n int num_nodes = row_ptr.size(0) - 1;\n auto out = torch::empty_like(edge_scores);\n \n dim3 grid(num_nodes);\n dim3 block(1);\n \n csr_softmax_kernel<<<grid, block>>>(\n row_ptr.data_ptr<int64_t>(),\n edge_scores.data_ptr<float>(),\n out.data_ptr<float>(),\n num_nodes\n );\n \n return out;\n}\n'''\n\ncpp_source = '''\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores);\n'''\n\nmodule = load_inline(\n name='csr_softmax',\n cpp_sources=[cpp_source],\n cuda_sources=[cuda_source],\n functions=['csr_softmax_cuda'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.module = module\n \n def forward(self, row_ptr, edge_scores):\n return self.module.csr_softmax_cuda(row_ptr, edge_scores)\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 6213.6s turn · 4.6s LLM · 208.9s tools · tokens in=5,597 · out=512 · total=6,114
reasoning
Compiled. Now correctness.
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = '''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cfloat>\n#include <cstdint>\n\n__global__ void csr_softmax_kernel(const int64_t* __restrict__ row_ptr, const float* __restrict__ edge_scores, float* __restrict__ out, int num_nodes) {\n int node = blockIdx.x;\n if (node >= num_nodes) return;\n \n int64_t start = row_ptr[node];\n int64_t end = row_ptr[node + 1];\n int64_t len = end - start;\n if (len <= 0) return;\n \n float max_val = -FLT_MAX;\n for (int64_t i = start; i < end; ++i) {\n max_val = fmaxf(max_val, edge_scores[i]);\n }\n \n float sum = 0.0f;\n for (int64_t i = start; i < end; ++i) {\n sum += expf(edge_scores[i] - max_val);\n }\n \n for (int64_t i = start; i < end; ++i) {\n out[i] = expf(edge_scores[i] - max_val) / sum;\n }\n}\n\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores) {\n int num_nodes = row_ptr.size(0) - 1;\n auto out = torch::empty_like(edge_scores);\n \n dim3 grid(num_nodes);\n dim3 block(1);\n \n csr_softmax_kernel<<<grid, block>>>(\n row_ptr.data_ptr<int64_t>(),\n edge_scores.data_ptr<float>(),\n out.data_ptr<float>(),\n num_nodes\n );\n \n return out;\n}\n'''\n\ncpp_source = '''\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores);\n'''\n\nmodule = load_inline(\n name='csr_softmax',\n cpp_sources=[cpp_source],\n cuda_sources=[cuda_source],\n functions=['csr_softmax_cuda'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.module = module\n \n def forward(self, row_ptr, edge_scores):\n return self.module.csr_softmax_cuda(row_ptr, edge_scores)\n"
}
result ← run_correctness (fail)
failrun_correctness
run_correctness FAILED: ? trials did not all match.
runtime_error: expected scalar type Long but found Float
turn 7264.5s turn · 5.6s LLM · 258.8s tools · tokens in=6,143 · out=522 · total=6,738
reasoning
Still error. The error now is expected Long found Float. So probably the inputs in get_inputs have row_ptr as int32, not long.
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = '''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cfloat>\n#include <cstdint>\n\n__global__ void csr_softmax_kernel(const int64_t* __restrict__ row_ptr, const float* __restrict__ edge_scores, float* __restrict__ out, int num_nodes) {\n int node = blockIdx.x;\n if (node >= num_nodes) return;\n \n int64_t start = row_ptr[node];\n int64_t end = row_ptr[node + 1];\n int64_t len = end - start;\n if (len <= 0) return;\n \n float max_val = -FLT_MAX;\n for (int64_t i = start; i < end; ++i) {\n max_val = fmaxf(max_val, edge_scores[i]);\n }\n \n float sum = 0.0f;\n for (int64_t i = start; i < end; ++i) {\n sum += expf(edge_scores[i] - max_val);\n }\n \n for (int64_t i = start; i < end; ++i) {\n out[i] = expf(edge_scores[i] - max_val) / sum;\n }\n}\n\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores) {\n int num_nodes = row_ptr.size(0) - 1;\n auto out = torch::empty_like(edge_scores);\n \n dim3 grid(num_nodes);\n dim3 block(1);\n \n csr_softmax_kernel<<<grid, block>>>(\n row_ptr.data_ptr<int64_t>(),\n edge_scores.data_ptr<float>(),\n out.data_ptr<float>(),\n num_nodes\n );\n \n return out;\n}\n'''\n\ncpp_source = '''\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores);\n'''\n\nmodule = load_inline(\n name='csr_softmax',\n cpp_sources=[cpp_source],\n cuda_sources=[cuda_source],\n functions=['csr_softmax_cuda'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.module = module\n \n def forward(self, row_ptr, edge_scores):\n row_ptr = row_ptr.to(torch.int64)\n return self.module.csr_softmax_cuda(row_ptr, edge_scores)\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 8408.0s turn · 10.3s LLM · 397.7s tools · tokens in=6,755 · out=523 · total=7,282
reasoning
Now test correctness.
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = '''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cfloat>\n#include <cstdint>\n\n__global__ void csr_softmax_kernel(const int64_t* __restrict__ row_ptr, const float* __restrict__ edge_scores, float* __restrict__ out, int num_nodes) {\n int node = blockIdx.x;\n if (node >= num_nodes) return;\n \n int64_t start = row_ptr[node];\n int64_t end = row_ptr[node + 1];\n int64_t len = end - start;\n if (len <= 0) return;\n \n float max_val = -FLT_MAX;\n for (int64_t i = start; i < end; ++i) {\n max_val = fmaxf(max_val, edge_scores[i]);\n }\n \n float sum = 0.0f;\n for (int64_t i = start; i < end; ++i) {\n sum += expf(edge_scores[i] - max_val);\n }\n \n for (int64_t i = start; i < end; ++i) {\n out[i] = expf(edge_scores[i] - max_val) / sum;\n }\n}\n\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores) {\n int num_nodes = row_ptr.size(0) - 1;\n auto out = torch::empty_like(edge_scores);\n \n dim3 grid(num_nodes);\n dim3 block(1);\n \n csr_softmax_kernel<<<grid, block>>>(\n row_ptr.data_ptr<int64_t>(),\n edge_scores.data_ptr<float>(),\n out.data_ptr<float>(),\n num_nodes\n );\n \n return out;\n}\n'''\n\ncpp_source = '''\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores);\n'''\n\nmodule = load_inline(\n name='csr_softmax',\n cpp_sources=[cpp_source],\n cuda_sources=[cuda_source],\n functions=['csr_softmax_cuda'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.module = module\n \n def forward(self, row_ptr, edge_scores):\n row_ptr = row_ptr.to(torch.int64)\n return self.module.csr_softmax_cuda(row_ptr, edge_scores)\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=1.19e-07 mean_abs_err=2.47e-09 max_rel_err=3.62e-07
turn 9747.4s turn · 9.1s LLM · 738.2s tools · tokens in=7,376 · out=522 · total=7,961 · FINAL
reasoning
It passed correctness. Now, since it's correct, and should be faster (Python loop vs CUDA), I can submit.
call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = '''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cfloat>\n#include <cstdint>\n\n__global__ void csr_softmax_kernel(const int64_t* __restrict__ row_ptr, const float* __restrict__ edge_scores, float* __restrict__ out, int num_nodes) {\n int node = blockIdx.x;\n if (node >= num_nodes) return;\n \n int64_t start = row_ptr[node];\n int64_t end = row_ptr[node + 1];\n int64_t len = end - start;\n if (len <= 0) return;\n \n float max_val = -FLT_MAX;\n for (int64_t i = start; i < end; ++i) {\n max_val = fmaxf(max_val, edge_scores[i]);\n }\n \n float sum = 0.0f;\n for (int64_t i = start; i < end; ++i) {\n sum += expf(edge_scores[i] - max_val);\n }\n \n for (int64_t i = start; i < end; ++i) {\n out[i] = expf(edge_scores[i] - max_val) / sum;\n }\n}\n\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores) {\n int num_nodes = row_ptr.size(0) - 1;\n auto out = torch::empty_like(edge_scores);\n \n dim3 grid(num_nodes);\n dim3 block(1);\n \n csr_softmax_kernel<<<grid, block>>>(\n row_ptr.data_ptr<int64_t>(),\n edge_scores.data_ptr<float>(),\n out.data_ptr<float>(),\n num_nodes\n );\n \n return out;\n}\n'''\n\ncpp_source = '''\ntorch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores);\n'''\n\nmodule = load_inline(\n name='csr_softmax',\n cpp_sources=[cpp_source],\n cuda_sources=[cuda_source],\n functions=['csr_softmax_cuda'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.module = module\n \n def forward(self, row_ptr, edge_scores):\n row_ptr = row_ptr.to(torch.int64)\n return self.module.csr_softmax_cuda(row_ptr, edge_scores)\n"
}
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=1.19e-07 mean_abs_err=2.47e-09 max_rel_err=3.62e-07
Memory: 33.1 MB peak (ref: 33.1 MB, ratio: 1.0001x)
Kernel launches: 6 (ref: 7682, fusion ratio: 1280.3333)
SOL score: 0.0783
Flagged for excessive speedup — this submission may have been rejected by automated review.
final submitted kernel (74 lines, 1,897 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline
cuda_source = '''
#include <torch/extension.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <cfloat>
#include <cstdint>
__global__ void csr_softmax_kernel(const int64_t* __restrict__ row_ptr, const float* __restrict__ edge_scores, float* __restrict__ out, int num_nodes) {
int node = blockIdx.x;
if (node >= num_nodes) return;
int64_t start = row_ptr[node];
int64_t end = row_ptr[node + 1];
int64_t len = end - start;
if (len <= 0) return;
float max_val = -FLT_MAX;
for (int64_t i = start; i < end; ++i) {
max_val = fmaxf(max_val, edge_scores[i]);
}
float sum = 0.0f;
for (int64_t i = start; i < end; ++i) {
sum += expf(edge_scores[i] - max_val);
}
for (int64_t i = start; i < end; ++i) {
out[i] = expf(edge_scores[i] - max_val) / sum;
}
}
torch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores) {
int num_nodes = row_ptr.size(0) - 1;
auto out = torch::empty_like(edge_scores);
dim3 grid(num_nodes);
dim3 block(1);
csr_softmax_kernel<<<grid, block>>>(
row_ptr.data_ptr<int64_t>(),
edge_scores.data_ptr<float>(),
out.data_ptr<float>(),
num_nodes
);
return out;
}
'''
cpp_source = '''
torch::Tensor csr_softmax_cuda(torch::Tensor row_ptr, torch::Tensor edge_scores);
'''
module = load_inline(
name='csr_softmax',
cpp_sources=[cpp_source],
cuda_sources=[cuda_source],
functions=['csr_softmax_cuda'],
verbose=False
)
class ModelNew(nn.Module):
def __init__(self):
super().__init__()
self.module = module
def forward(self, row_ptr, edge_scores):
row_ptr = row_ptr.to(torch.int64)
return self.module.csr_softmax_cuda(row_ptr, edge_scores)