call → profile_kernel
callprofile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\ncpp_src=r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor csr_max_forward(torch::Tensor row_ptr, torch::Tensor col_idx, torch::Tensor node_feat);\n\"\"\"\ncuda_src=r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\ntemplate <typename index_t>\n__global__ __launch_bounds__(96, 8) void csr_max80_kernel(const index_t* __restrict__ row_ptr,\n const index_t* __restrict__ col_idx,\n const float* __restrict__ node_feat,\n float* __restrict__ out,\n int num_nodes) {\n int dst = blockIdx.x;\n int f = threadIdx.x;\n if (f < 80) {\n int start = (int)row_ptr[dst];\n int end = (int)row_ptr[dst + 1];\n float m = -INFINITY;\n #pragma unroll 1\n for (int e = start; e < end; ++e) {\n int src = (int)col_idx[e];\n float v = __ldg(node_feat + src * 80 + f);\n m = fmaxf(m, v);\n }\n out[dst * 80 + f] = m;\n }\n}\n\ntemplate <typename index_t>\n__global__ void csr_max_kernel(const index_t* __restrict__ row_ptr,\n const index_t* __restrict__ col_idx,\n const float* __restrict__ node_feat,\n float* __restrict__ out,\n int num_nodes,\n int feat_dim) {\n int dst = blockIdx.x;\n int tid = threadIdx.x;\n int start = (int)row_ptr[dst];\n int end = (int)row_ptr[dst + 1];\n for (int f = tid; f < feat_dim; f += blockDim.x) {\n float m = -INFINITY;\n for (int e = start; e < end; ++e) {\n int src = (int)col_idx[e];\n float v = __ldg(node_feat + (long long)src * feat_dim + f);\n m = fmaxf(m, v);\n }\n out[(long long)dst * feat_dim + f] = m;\n }\n}\n\ntorch::Tensor csr_max_forward(torch::Tensor row_ptr, torch::Tensor col_idx, torch::Tensor node_feat) {\n int num_nodes = row_ptr.numel()-1; int feat_dim = node_feat.size(1);\n auto out = torch::empty({num_nodes, feat_dim}, node_feat.options());\n if (feat_dim == 80 && row_ptr.scalar_type() == torch::kFloat32) {\n csr_max80_kernel<float><<<num_nodes, 96>>>(row_ptr.data_ptr<float>(), col_idx.data_ptr<float>(), node_feat.data_ptr<float>(), out.data_ptr<float>(), num_nodes);\n } else if (feat_dim == 80) {\n csr_max80_kernel<int><<<num_nodes, 96>>>(row_ptr.data_ptr<int>(), col_idx.data_ptr<int>(), node_feat.data_ptr<float>(), out.data_ptr<float>(), num_nodes);\n } else if (row_ptr.scalar_type() == torch::kFloat32) {\n csr_max_kernel<float><<<num_nodes,128>>>(row_ptr.data_ptr<float>(), col_idx.data_ptr<float>(), node_feat.data_ptr<float>(), out.data_ptr<float>(), num_nodes, feat_dim);\n } else {\n csr_max_kernel<int><<<num_nodes,128>>>(row_ptr.data_ptr<int>(), col_idx.data_ptr<int>(), node_feat.data_ptr<float>(), out.data_ptr<float>(), num_nodes, feat_dim);\n }\n return out;\n}\n\"\"\"\n_ext=load_inline(name=\"csr_max_ext_v4prof\", cpp_sources=cpp_src, cuda_sources=cuda_src, functions=[\"csr_max_forward\"], extra_cflags=[\"-O3\"], extra_cuda_cflags=[\"-O3\"], verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self): super().__init__()\n def forward(self,row_ptr,col_idx,node_feat):\n return _ext.csr_max_forward(row_ptr,col_idx,node_feat)\n"
}
result ← profile_kernel (ok)
okprofile_kernel
profile_kernel PASSED: profiling complete.
=== Kernel Profile Summary ===
--- Kernel Breakdown (by GPU time) ---
#1: aten::empty 768.0μs (100%) calls=1
--- Timing ---
GPU time: 8.10 μs [↑2.3μs REGRESSED]
--- Memory Bandwidth ---
DRAM BW: 31.1/3350 GB/s (0.9%) [↓0.4% REGRESSED]
read=31.1 write=0.0 GB/s
Hit rates: L2=91.4%
--- Compute Throughput ---
Pipe util: FMA=2.0%, Tensor=0.0%
--- Roofline Analysis ---
Ridge point (FP32): 20.00 FLOPs/byte
Classification: UNKNOWN
--- Occupancy ---
Achieved: 20.3% [↓0.7% REGRESSED]
Eligible warps/cycle: 0.11
WARNING: <1 eligible warp/cycle = latency-bound, needs more parallelism
Launch: regs/thread=16, smem/blk=1024B, block=96, grid=640
--- Memory Access Quality ---
Global ld coalescing: 2.10 sectors/req (2.1x wasted BW)
--- Warp Stall Reasons (% of issue cycles) ---
long_scoreboard 2468.5% ####################
short_scoreboard 121.3% ####################
mio_throttle 1.8%
--- Optimization Hints ---
-> 2468% stalls: global memory latency (waiting for DRAM/L2). + sectors/req=2.1 -> uncoalesced global loads, restructure access pattern or use __ldg Try shared-memory tiling, prefetching, or reducing working set.
-> Global load coalescing=2.1x (ideal=1.0) -> 2x wasted DRAM BW. Make per-warp accesses contiguous.
-> Low occupancy (20%) limited by small block (96). Consider __launch_bounds__ or reducing register pressure.
-> Low eligible warps + low BW% + low compute% = LATENCY-BOUND. Need more parallelism (larger grid, more ILP, prefetching).
--- Delta vs Previous Iteration ---
GPU time: 5.76→8.10μs (↑2.34) REGRESSED
DRAM BW%: 1.34→0.93% (↓0.41) REGRESSED
Occupancy: 20.99→20.25% (↓0.74) REGRESSED
Eligible warps/cyc: 0.16→0.11 (↓0.05) REGRESSED
L2 hit%: 91.18→91.40% (↑0.22) ok