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_src = r'''\n#include <torch/extension.h>\ntorch::Tensor rbf_forward_cuda(torch::Tensor distances, int64_t num_rbf, double cutoff);\ntorch::Tensor rbf_forward(torch::Tensor distances, int64_t num_rbf, double cutoff) { return rbf_forward_cuda(distances, num_rbf, cutoff); }\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 <vector>\n\n__global__ void rbf64_fill_kernel(const float* __restrict__ dists, float* __restrict__ out, int64_t M, float cutoff) {\n constexpr int WARPS_PER_BLOCK = 8;\n int tid = threadIdx.x;\n int warp = tid >> 5;\n int lane = tid & 31;\n int64_t m = (int64_t)blockIdx.x * WARPS_PER_BLOCK + warp;\n if (m >= M) return;\n float d = 0.0f;\n if (lane == 0) d = dists[m];\n d = __shfl_sync(0xffffffff, d, 0);\n if (d >= cutoff) return;\n float q = d * (63.0f / cutoff);\n float env = 0.0f;\n if (lane == 0) env = 0.5f * (__cosf(3.14159265358979323846f * d / cutoff) + 1.0f);\n env = __shfl_sync(0xffffffff, env, 0);\n int start = (int)ceilf(q - 4.472135955f);\n int end = (int)floorf(q + 4.472135955f);\n if (start < 0) start = 0;\n if (end > 63) end = 63;\n int r = start + lane;\n if (r <= end) {\n float t = q - (float)r;\n float val = __expf(-0.5f * t * t) * env;\n out[m * 64 + r] = val;\n }\n}\n\n__global__ void rbf_generic_kernel(const float* __restrict__ dists, float* __restrict__ out, int64_t M, int R, float cutoff, float inv_step) {\n int64_t idx = (int64_t)blockIdx.x * blockDim.x + threadIdx.x;\n int64_t total = M * (int64_t)R;\n if (idx >= total) return;\n int r = (int)(idx % R);\n int64_t m = idx / R;\n float d = dists[m];\n float val = 0.0f;\n if (d < cutoff) {\n float q = d * inv_step;\n float t = q - (float)r;\n float tt = t * t;\n if (tt <= 20.0f) {\n float env = 0.5f * (__cosf(3.14159265358979323846f * d / cutoff) + 1.0f);\n val = __expf(-0.5f * tt) * env;\n }\n }\n out[idx] = val;\n}\n\ntorch::Tensor rbf_forward_cuda(torch::Tensor distances, int64_t num_rbf, double cutoff_d) {\n TORCH_CHECK(distances.is_cuda(), \"distances must be CUDA\");\n TORCH_CHECK(distances.scalar_type() == torch::kFloat32, \"distances must be float32\");\n auto dist = distances.contiguous();\n std::vector<int64_t> sizes = dist.sizes().vec(); sizes.push_back(num_rbf);\n auto out = torch::empty(sizes, dist.options());\n int64_t M = dist.numel(); if (M == 0) return out;\n float cutoff = (float)cutoff_d;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n if (num_rbf == 64) {\n cudaMemsetAsync(out.data_ptr<float>(), 0, (size_t)(M * 64) * sizeof(float), stream);\n rbf64_fill_kernel<<<(unsigned int)((M + 7) / 8), 256, 0, stream>>>(dist.data_ptr<float>(), out.data_ptr<float>(), M, cutoff);\n } else {\n int threads=256; int64_t total=M*num_rbf; int blocks=(int)((total+threads-1)/threads);\n float inv_step=(float)(num_rbf-1)/cutoff;\n rbf_generic_kernel<<<blocks,threads,0,stream>>>(dist.data_ptr<float>(), out.data_ptr<float>(), M, (int)num_rbf, cutoff, inv_step);\n }\n return out;\n}\n'''\n\n_rbf_ext = load_inline(name='rbf_ext_v4', cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=['rbf_forward'], extra_cuda_cflags=['-O3','--use_fast_math'], extra_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, num_rbf=64, cutoff=5.0):\n super().__init__(); self.num_rbf=num_rbf; self.cutoff=cutoff\n offsets=torch.linspace(0.0, cutoff, num_rbf); self.register_buffer('offsets', offsets)\n self.coeff=-0.5/(offsets[1]-offsets[0]).item()**2\n def forward(self, distances: torch.Tensor) -> torch.Tensor:\n return _rbf_ext.rbf_forward(distances, self.num_rbf, float(self.cutoff))\n"
}