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\ntorch::Tensor edge_dot_forward(torch::Tensor src_idx,\n torch::Tensor dst_idx,\n torch::Tensor src_feat,\n torch::Tensor dst_feat);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAException.h>\n#include <cstdint>\n\ntemplate <typename index_t>\n__global__ __launch_bounds__(256, 2)\nvoid edge_dot128_kernel(const index_t* __restrict__ src_idx,\n const index_t* __restrict__ dst_idx,\n const float* __restrict__ src_feat,\n const float* __restrict__ dst_feat,\n float* __restrict__ out,\n int E) {\n constexpr int WARPS_PER_BLOCK = 8;\n int tid = threadIdx.x;\n int lane = tid & 31;\n int warp = tid >> 5;\n int edge = blockIdx.x * WARPS_PER_BLOCK + warp;\n if (edge >= E) return;\n\n int s = static_cast<int>(src_idx[edge]);\n int d = static_cast<int>(dst_idx[edge]);\n const float* __restrict__ sp = src_feat + (static_cast<long long>(s) << 7); // *128\n const float* __restrict__ dp = dst_feat + (static_cast<long long>(d) << 7);\n\n float sum = 0.0f;\n float a0 = sp[lane]; float b0 = dp[lane];\n float a1 = sp[lane + 32]; float b1 = dp[lane + 32];\n float a2 = sp[lane + 64]; float b2 = dp[lane + 64];\n float a3 = sp[lane + 96]; float b3 = dp[lane + 96];\n sum = fmaf(a0, b0, sum);\n sum = fmaf(a1, b1, sum);\n sum = fmaf(a2, b2, sum);\n sum = fmaf(a3, b3, sum);\n\n sum += __shfl_down_sync(0xffffffff, sum, 16);\n sum += __shfl_down_sync(0xffffffff, sum, 8);\n sum += __shfl_down_sync(0xffffffff, sum, 4);\n sum += __shfl_down_sync(0xffffffff, sum, 2);\n sum += __shfl_down_sync(0xffffffff, sum, 1);\n if (lane == 0) out[edge] = sum;\n}\n\ntemplate <typename index_t>\n__global__ __launch_bounds__(256, 2)\nvoid edge_dot_generic_kernel(const index_t* __restrict__ src_idx,\n const index_t* __restrict__ dst_idx,\n const float* __restrict__ src_feat,\n const float* __restrict__ dst_feat,\n float* __restrict__ out,\n int E,\n int D) {\n constexpr int WARPS_PER_BLOCK = 8;\n int tid = threadIdx.x;\n int lane = tid & 31;\n int warp = tid >> 5;\n int edge = blockIdx.x * WARPS_PER_BLOCK + warp;\n if (edge >= E) return;\n\n int s = static_cast<int>(src_idx[edge]);\n int d = static_cast<int>(dst_idx[edge]);\n const float* __restrict__ sp = src_feat + static_cast<long long>(s) * D;\n const float* __restrict__ dp = dst_feat + static_cast<long long>(d) * D;\n\n float sum = 0.0f;\n for (int k = lane; k < D; k += 32) {\n sum = fmaf(sp[k], dp[k], sum);\n }\n\n sum += __shfl_down_sync(0xffffffff, sum, 16);\n sum += __shfl_down_sync(0xffffffff, sum, 8);\n sum += __shfl_down_sync(0xffffffff, sum, 4);\n sum += __shfl_down_sync(0xffffffff, sum, 2);\n sum += __shfl_down_sync(0xffffffff, sum, 1);\n if (lane == 0) out[edge] = sum;\n}\n\ntorch::Tensor edge_dot_forward(torch::Tensor src_idx,\n torch::Tensor dst_idx,\n torch::Tensor src_feat,\n torch::Tensor dst_feat) {\n const int E = static_cast<int>(src_idx.numel());\n const int D = static_cast<int>(src_feat.size(1));\n auto out = torch::empty({E}, src_feat.options());\n if (E == 0) return out;\n\n constexpr int THREADS = 256;\n constexpr int WARPS_PER_BLOCK = THREADS / 32;\n dim3 block(THREADS);\n dim3 grid((E + WARPS_PER_BLOCK - 1) / WARPS_PER_BLOCK);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n\n if (src_idx.scalar_type() == at::kInt) {\n const int* sidx = src_idx.data_ptr<int>();\n const int* didx = dst_idx.data_ptr<int>();\n if (D == 128) {\n edge_dot128_kernel<int><<<grid, block, 0, stream>>>(sidx, didx,\n src_feat.data_ptr<float>(), dst_feat.data_ptr<float>(), out.data_ptr<float>(), E);\n } else {\n edge_dot_generic_kernel<int><<<grid, block, 0, stream>>>(sidx, didx,\n src_feat.data_ptr<float>(), dst_feat.data_ptr<float>(), out.data_ptr<float>(), E, D);\n }\n } else { // int64 indices\n const int64_t* sidx = src_idx.data_ptr<int64_t>();\n const int64_t* didx = dst_idx.data_ptr<int64_t>();\n if (D == 128) {\n edge_dot128_kernel<int64_t><<<grid, block, 0, stream>>>(sidx, didx,\n src_feat.data_ptr<float>(), dst_feat.data_ptr<float>(), out.data_ptr<float>(), E);\n } else {\n edge_dot_generic_kernel<int64_t><<<grid, block, 0, stream>>>(sidx, didx,\n src_feat.data_ptr<float>(), dst_feat.data_ptr<float>(), out.data_ptr<float>(), E, D);\n }\n }\n C10_CUDA_KERNEL_LAUNCH_CHECK();\n return out;\n}\n'''\n\n_ext = load_inline(\n name=\"edge_sampled_dot_ext_v1\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"edge_dot_forward\"],\n extra_cflags=[\"-O3\"],\n extra_cuda_cflags=[\"-O3\"],\n with_cuda=True,\n verbose=False,\n)\n\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n\n def forward(self, src_idx: torch.Tensor, dst_idx: torch.Tensor,\n src_feat: torch.Tensor, dst_feat: torch.Tensor) -> torch.Tensor:\n return _ext.edge_dot_forward(src_idx, dst_idx, src_feat, dst_feat)\n"
}