call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_source = r'''\n#include <torch/extension.h>\n\ntorch::Tensor csr_attn_forward(torch::Tensor row_ptr, torch::Tensor col_idx, torch::Tensor edge_scores, torch::Tensor node_value);\n'''\n\n_cuda_source = 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\ntemplate<int KIND>\n__device__ __forceinline__ int read_idx_t(const void* p, int i) {\n if constexpr (KIND == 0) return ((const int*)p)[i];\n else if constexpr (KIND == 1) return (int)((const long long*)p)[i];\n else return (int)((const float*)p)[i];\n}\n\n__device__ __forceinline__ float warp_reduce_sum0(float v) {\n v += __shfl_down_sync(0xffffffff, v, 16);\n v += __shfl_down_sync(0xffffffff, v, 8);\n v += __shfl_down_sync(0xffffffff, v, 4);\n v += __shfl_down_sync(0xffffffff, v, 2);\n v += __shfl_down_sync(0xffffffff, v, 1);\n return v;\n}\n__device__ __forceinline__ float warp_reduce_max0(float v) {\n v = fmaxf(v, __shfl_down_sync(0xffffffff, v, 16));\n v = fmaxf(v, __shfl_down_sync(0xffffffff, v, 8));\n v = fmaxf(v, __shfl_down_sync(0xffffffff, v, 4));\n v = fmaxf(v, __shfl_down_sync(0xffffffff, v, 2));\n v = fmaxf(v, __shfl_down_sync(0xffffffff, v, 1));\n return v;\n}\n\ntemplate<int ROWK, int COLK>\n__global__ void csr_attn_kernel_t(const void* __restrict__ row_ptr,\n const void* __restrict__ col_idx,\n const float* __restrict__ edge_scores,\n const float* __restrict__ node_value,\n float* __restrict__ out,\n int num_nodes,\n int feat_dim) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n int lane = tid & 31;\n int start = read_idx_t<ROWK>(row_ptr, row);\n int end = read_idx_t<ROWK>(row_ptr, row + 1);\n int deg = end - start;\n __shared__ float weights[1024];\n __shared__ float inv_sum_s;\n if (deg <= 0) {\n for (int f = tid; f < feat_dim; f += blockDim.x) out[row * feat_dim + f] = 0.0f;\n return;\n }\n if (deg <= 32) {\n if (tid < 32) {\n float s = (lane < deg) ? edge_scores[start + lane] : -3.402823466e+38F;\n float m = warp_reduce_max0(s);\n m = __shfl_sync(0xffffffff, m, 0);\n float w = (lane < deg) ? expf(s - m) : 0.0f;\n float denom = warp_reduce_sum0(w);\n denom = __shfl_sync(0xffffffff, denom, 0);\n if (lane < deg) weights[lane] = w;\n if (lane == 0) inv_sum_s = 1.0f / denom;\n }\n } else {\n if (tid == 0) {\n float m = -3.402823466e+38F;\n for (int e = 0; e < deg; ++e) m = fmaxf(m, edge_scores[start + e]);\n float denom = 0.0f;\n for (int e = 0; e < deg; ++e) { float w = expf(edge_scores[start + e] - m); weights[e] = w; denom += w; }\n inv_sum_s = 1.0f / denom;\n }\n }\n __syncthreads();\n float inv_sum = inv_sum_s;\n for (int f = tid; f < feat_dim; f += blockDim.x) {\n float acc = 0.0f;\n #pragma unroll\n for (int e = 0; e < 32; ++e) {\n if (e >= deg) break;\n int src = read_idx_t<COLK>(col_idx, start + e);\n acc = fmaf(node_value[src * feat_dim + f], weights[e] * inv_sum, acc);\n }\n if (deg > 32) {\n for (int e = 32; e < deg; ++e) {\n int src = read_idx_t<COLK>(col_idx, start + e);\n acc = fmaf(node_value[src * feat_dim + f], weights[e] * inv_sum, acc);\n }\n }\n out[row * feat_dim + f] = acc;\n }\n}\n\ntemplate<int RK>\nvoid launch_col(int ck, const void* rp, const void* ci, const float* es, const float* nv, float* out, int n, int fd, cudaStream_t stream) {\n if (ck == 0) csr_attn_kernel_t<RK,0><<<dim3(n), dim3(64), 0, stream>>>(rp, ci, es, nv, out, n, fd);\n else if (ck == 1) csr_attn_kernel_t<RK,1><<<dim3(n), dim3(64), 0, stream>>>(rp, ci, es, nv, out, n, fd);\n else csr_attn_kernel_t<RK,2><<<dim3(n), dim3(64), 0, stream>>>(rp, ci, es, nv, out, n, fd);\n}\n\ntorch::Tensor csr_attn_forward(torch::Tensor row_ptr, torch::Tensor col_idx, torch::Tensor edge_scores, torch::Tensor node_value) {\n int num_nodes = (int)row_ptr.numel() - 1;\n int feat_dim = (int)node_value.size(1);\n auto out = torch::empty({num_nodes, feat_dim}, node_value.options());\n int rk = row_ptr.scalar_type() == at::kInt ? 0 : (row_ptr.scalar_type() == at::kLong ? 1 : 2);\n int ck = col_idx.scalar_type() == at::kInt ? 0 : (col_idx.scalar_type() == at::kLong ? 1 : 2);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n if (rk == 0) launch_col<0>(ck, row_ptr.data_ptr(), col_idx.data_ptr(), edge_scores.data_ptr<float>(), node_value.data_ptr<float>(), out.data_ptr<float>(), num_nodes, feat_dim, stream);\n else if (rk == 1) launch_col<1>(ck, row_ptr.data_ptr(), col_idx.data_ptr(), edge_scores.data_ptr<float>(), node_value.data_ptr<float>(), out.data_ptr<float>(), num_nodes, feat_dim, stream);\n else launch_col<2>(ck, row_ptr.data_ptr(), col_idx.data_ptr(), edge_scores.data_ptr<float>(), node_value.data_ptr<float>(), out.data_ptr<float>(), num_nodes, feat_dim, stream);\n return out;\n}\n'''\n\n_ext = load_inline(name='csr_attn_ext_v6', cpp_sources=_cpp_source, cuda_sources=_cuda_source,\n functions=['csr_attn_forward'], extra_cuda_cflags=['-O3', '--use_fast_math'], extra_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n def forward(self, row_ptr: torch.Tensor, col_idx: torch.Tensor, edge_scores: torch.Tensor, node_value: torch.Tensor) -> torch.Tensor:\n return _ext.csr_attn_forward(row_ptr, col_idx, edge_scores, node_value)\n"
}