correct
14_GaussianProcessRBFKernel.py
started
2026-05-02T19:48:47Z
timingkernelbench.timing
kernel mean / median / std
0.01 / — / 2.00e-04 μs
ref mean / median / std
0.12 / — / 0.02 μs
numerical precisioneval_kernel_against_ref
gpu memoryextended_metrics.measure_memory
kernel launches / fusiontorch.profiler
fusion ratio (ref / kernel)
37.00x
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):
"""
RBF (Squared Exponential) covariance matrix computation for Gaussian
Processes. Given two sets of input points, computes the full
kernel matrix K[i,j] = sigma^2 * exp(-||x_i - x_j||^2 / (2 * l^2)).
The dominant cost in GP inference and a natural target for fusion.
"""
def __init__(self, input_dim, lengthscale=1.0, variance=1.0):
super().__init__()
self.log_lengthscale = nn.Parameter(torch.tensor(lengthscale).log())
self.log_variance = nn.Parameter(torch.tensor(variance).log())
def forward(self, X1: torch.Tensor, X2: torch.Tensor) -> torch.Tensor:
"""
Args:
X1: (B, N, D) – first set of inputs
X2: (B, M, D) – second set of inputs
Returns:
K: (B, N, M) – covariance matrix
"""
l2 = self.log_lengthscale.exp() ** 2
var = self.log_variance.exp()
# Squared distances via expansion
X1_sq = (X1 ** 2).sum(-1, keepdim=True) # (B, N, 1)
X2_sq = (X2 ** 2).sum(-1, keepdim=True) # (B, M, 1)
dist_sq = X1_sq - 2.0 * X1 @ X2.transpose(-1, -2) + X2_sq.transpose(-1, -2)
dist_sq = dist_sq.clamp(min=0.0)
return var * torch.exp(-0.5 * dist_sq / l2)
input_dim = 8
num_train = 512
num_test = 128
batch_size = 16
def get_inputs():
X1 = torch.randn(popcorn_pri.jitter_int(batch_size), popcorn_pri.jitter_int(num_train), input_dim)
X2 = torch.randn(popcorn_pri.jitter_int(batch_size), popcorn_pri.jitter_int(num_test), input_dim)
return [X1, X2]
def get_init_inputs():
return [input_dim]
turn 02.6s turn · 2.6s LLM · 0.0s tools
reasoning
**Crafting code optimization**
I need to optimize the code for RBF with parameters B16, N512, M128, D8, and fp32. First, I'm thinking about crafting it carefully. I should use load_inline to help manage everything more efficiently. Getting the specifications might be necessary too, so I’ll keep that in mind. It's a bit of a process, but I’m excited to see how I can improve it! Let's get to work on this!
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 1 · 1 tool call(s) · 39.9s turn · 39.9s LLM · 10,379 chars (click to expand)
turn 139.9s turn · 39.9s LLM · 0.0s tools
reasoning
**Implementing optimized kernels**
I need to implement something that uses matrix multiplication (matmul), which can be fast but creates intermediates. This involves a total of 1,048,576 elements with a small D8 size. The direct kernel seems to perform around 8 sub-multiplications per element plus exponential calculations. I'm considering whether a custom implementation might be faster if I approximate the exponential function. I’m also checking ways to configure the model parameters and ensure efficient computations with tensors for optimal performance.
**Considering CUDA optimizations**
I’m looking into using `torch::empty_like` for output shapes and setting up a CUDA kernel with 256 threads. While this setup is straightforward, it could have some latency issues. The H100 may manage special function throughput decently, and I could vectorize computations. I'm considering using 2D tiling and shared memory for better efficiency. The exponential function dominates computations, and I might use `__expf` for a fast approximation, making sure its accuracy is within my desired tolerances. Clamping negative values will also be necessary for correctness.
**Clarifying compute approach**
It seems the key issue here is calculating the squared distance between two vectors, represented as ||x-y||^2. This can be expanded as the sum of (x-y)^2. I'm considering using a reference expansion approach with `X1_sq - 2*dot(X1, X2) + X2_sq`. I wonder if I should utilize matrix multiplication with Tensor Float 32 (TF32) for this calculation. I need to ensure I'm accurately reflecting the computation for optimal performance.
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define TILE_N 16\n#define TILE_M 16\n#define D_FIXED 8\n\n__global__ void rbf_d8_tiled_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int B, int N, int M) {\n __shared__ float sx1[TILE_N][D_FIXED];\n __shared__ float sx2[TILE_M][D_FIXED];\n __shared__ float scale;\n __shared__ float var;\n\n const int tx = threadIdx.x; // 0..15, M dimension\n const int ty = threadIdx.y; // 0..15, N dimension\n const int tid = ty * TILE_M + tx;\n\n if (tid == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n\n const int b = blockIdx.z;\n const int n0 = blockIdx.y * TILE_N;\n const int m0 = blockIdx.x * TILE_M;\n\n if (tid < 128) {\n int row = tid >> 3;\n int d = tid & 7;\n int n = n0 + row;\n sx1[row][d] = (n < N) ? X1[((b * N + n) * D_FIXED + d)] : 0.0f;\n } else {\n int t = tid - 128;\n int row = t >> 3;\n int d = t & 7;\n int m = m0 + row;\n sx2[row][d] = (m < M) ? X2[((b * M + m) * D_FIXED + d)] : 0.0f;\n }\n __syncthreads();\n\n const int n = n0 + ty;\n const int m = m0 + tx;\n if (n < N && m < M) {\n float s = 0.0f;\n #pragma unroll\n for (int d = 0; d < D_FIXED; ++d) {\n float diff = sx1[ty][d] - sx2[tx][d];\n s = fmaf(diff, diff, s);\n }\n O[(b * N + n) * M + m] = var * __expf(scale * s);\n }\n}\n\n__global__ void rbf_generic_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int total, int N, int M, int D) {\n __shared__ float scale;\n __shared__ float var;\n if (threadIdx.x == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n __syncthreads();\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int m = idx % M;\n int t = idx / M;\n int n = t % N;\n int b = t / N;\n const float* p1 = X1 + ((b * N + n) * D);\n const float* p2 = X2 + ((b * M + m) * D);\n float s = 0.0f;\n for (int d = 0; d < D; ++d) {\n float diff = p1[d] - p2[d];\n s = fmaf(diff, diff, s);\n }\n O[idx] = var * __expf(scale * s);\n}\n\ntorch::Tensor rbf_forward(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v) {\n const int B = (int)X1.size(0);\n const int N = (int)X1.size(1);\n const int D = (int)X1.size(2);\n const int M = (int)X2.size(1);\n auto O = torch::empty({B, N, M}, X1.options());\n if (D == 8 && X1.is_cuda() && X2.is_cuda()) {\n dim3 block(TILE_M, TILE_N, 1);\n dim3 grid((M + TILE_M - 1) / TILE_M, (N + TILE_N - 1) / TILE_N, B);\n rbf_d8_tiled_kernel<<<grid, block>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), B, N, M);\n } else {\n int total = B * N * M;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n rbf_generic_kernel<<<blocks, threads>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), total, N, M, D);\n }\n return O;\n}\n'''\n\n_ext = load_inline(name='rbf_cov_ext_v1', cpp_sources='', cuda_sources=_cuda_src,\n functions=['rbf_forward'], verbose=False,\n extra_cuda_cflags=['-O3', '--use_fast_math'])\n\nclass ModelNew(nn.Module):\n def __init__(self, input_dim, lengthscale=1.0, variance=1.0):\n super().__init__()\n self.log_lengthscale = nn.Parameter(torch.tensor(lengthscale).log())\n self.log_variance = nn.Parameter(torch.tensor(variance).log())\n def forward(self, X1: torch.Tensor, X2: torch.Tensor) -> torch.Tensor:\n return _ext.rbf_forward(X1, X2, self.log_lengthscale, self.log_variance)\n"
}
result ← compile_kernel (fail)
failcompile_kernel
compile_kernel FAILED: RuntimeError.
RuntimeError: Error building extension 'rbf_cov_ext_v1': [1/3] /opt/conda/bin/x86_64-conda-linux-gnu-c++ -MMD -MF main.o.d -DTORCH_EXTENSION_NAME=rbf_cov_ext_v1 -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /home/prabhune/.local/share/uv/python/cpython-3.10-linux-x86_64-gnu/include/python3.10 -fPIC -std=c++17 -c /scratch/tejas/PopcornBench/runs/l12_default/popcorn/gpt-5.5-priority/level_1_problem_14_cache/k_273ae0195c58/rbf_cov_ext_v1/main.cpp -o main.o
FAILED: [code=1] main.o
/opt/conda/bin/x86_64-conda-linux-gnu-c++ -MMD -MF main.o.d -DTORCH_EXTENSION_NAME=rbf_cov_ext_v1 -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /home/prabhune/.local/share/uv/python/cpython-3.10-linux-x86_64-gnu/include/python3.10 -fPIC -std=c++17 -c /scratch/tejas/PopcornBench/runs/l12_default/popcorn/gpt-5.5-priority/level_1_problem_14_cache/k_273ae0195c58/rbf_cov_ext_v1/main.cpp -o main.o
/scratch/tejas/PopcornBench/runs/l12_default/popcorn/gpt-5.5-priority/level_1_problem_14_cache/k_273ae0195c58/rbf_cov_ext_v1/main.cpp: In function 'void pybind11_init_rbf_cov_ext_v1(pybind11::module_&)':
/scratch/tejas/PopcornBench/runs/l12_default/popcorn/gpt-5.5-priority/level_1_problem_14_cache/k_273ae0195c58/rbf_cov_ext_v1/main.cpp:4:50: error: 'rbf_forward' was not declared in this scope
4 | m.def("rbf_forward", torch::wrap_pybind_function(rbf_forward), "rbf_forward");
| ^~~~~~~~~~~
[2/3] /usr/local/cuda/bin/nvcc -MD -MF cuda.cuda.o.d -ccbin /opt/conda/bin/x86_64-conda-linux-gnu-cc -DTORCH_EXTENSION_NAME=rbf_cov_ext_v1 -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /home/prabhune/.local/share/uv/python/cpython-3.10-linux-x86_64-gnu/include/python3.10 -D__CUDA_NO_HALF_OPERATORS__ -D__CUDA_NO_HALF_CONVERSIONS__ -D__CUDA_NO_BFLOAT16_CONVERSIONS__ -D__CUDA_NO_HALF2_OPERATORS__ --expt-relaxed-constexpr -gencode=arch=compute_90,code=compute_90 -gencode=arch=compute_90,code=sm_90 --compiler-options '-fPIC' -O3 --use_fast_math -std=c++17 -c /scratch/tejas/PopcornBench/runs/l12_default/popcorn/gpt-5.5-priority/level_1_problem_14_cache/k_273ae0195c58/rbf_cov_ext_v1/cuda.cu -o cuda.cuda.o
nvcc warning : incompatible redefinition for option 'compiler-bindir', the last value of this option was used
ninja: build stopped: subcommand failed.
turn 2 · 1 tool call(s) · 10.2s turn · 10.2s LLM · 6,277 chars (click to expand)
turn 210.2s turn · 10.2s LLM · 0.0s tools
reasoning
**Clarifying function visibility**
I need to declare a function in `cpp_sources` if it's not visible to the main CUDA code. The instructions mention there's no `pybind` block, so I can include the declaration directly in `cpp_sources`. For instance, I might write `cpp_sources = "torch::Tensor rbf_forward(...);"` and include the necessary header, like `torch/extension`. I want to ensure everything is set up correctly for proper visibility and functionality!
call → compile_kernel
callcompile_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>\ntorch::Tensor rbf_forward(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define TILE_N 16\n#define TILE_M 16\n#define D_FIXED 8\n\n__global__ void rbf_d8_tiled_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int B, int N, int M) {\n __shared__ float sx1[TILE_N][D_FIXED];\n __shared__ float sx2[TILE_M][D_FIXED];\n __shared__ float scale;\n __shared__ float var;\n\n const int tx = threadIdx.x;\n const int ty = threadIdx.y;\n const int tid = ty * TILE_M + tx;\n\n if (tid == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n\n const int b = blockIdx.z;\n const int n0 = blockIdx.y * TILE_N;\n const int m0 = blockIdx.x * TILE_M;\n\n if (tid < 128) {\n int row = tid >> 3;\n int d = tid & 7;\n int n = n0 + row;\n sx1[row][d] = (n < N) ? X1[((b * N + n) * D_FIXED + d)] : 0.0f;\n } else {\n int t = tid - 128;\n int row = t >> 3;\n int d = t & 7;\n int m = m0 + row;\n sx2[row][d] = (m < M) ? X2[((b * M + m) * D_FIXED + d)] : 0.0f;\n }\n __syncthreads();\n\n const int n = n0 + ty;\n const int m = m0 + tx;\n if (n < N && m < M) {\n float s = 0.0f;\n #pragma unroll\n for (int d = 0; d < D_FIXED; ++d) {\n float diff = sx1[ty][d] - sx2[tx][d];\n s = fmaf(diff, diff, s);\n }\n O[(b * N + n) * M + m] = var * __expf(scale * s);\n }\n}\n\n__global__ void rbf_generic_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int total, int N, int M, int D) {\n __shared__ float scale;\n __shared__ float var;\n if (threadIdx.x == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n __syncthreads();\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int m = idx % M;\n int t = idx / M;\n int n = t % N;\n int b = t / N;\n const float* p1 = X1 + ((b * N + n) * D);\n const float* p2 = X2 + ((b * M + m) * D);\n float s = 0.0f;\n for (int d = 0; d < D; ++d) {\n float diff = p1[d] - p2[d];\n s = fmaf(diff, diff, s);\n }\n O[idx] = var * __expf(scale * s);\n}\n\ntorch::Tensor rbf_forward(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v) {\n const int B = (int)X1.size(0);\n const int N = (int)X1.size(1);\n const int D = (int)X1.size(2);\n const int M = (int)X2.size(1);\n auto O = torch::empty({B, N, M}, X1.options());\n if (D == 8) {\n dim3 block(TILE_M, TILE_N, 1);\n dim3 grid((M + TILE_M - 1) / TILE_M, (N + TILE_N - 1) / TILE_N, B);\n rbf_d8_tiled_kernel<<<grid, block>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), B, N, M);\n } else {\n int total = B * N * M;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n rbf_generic_kernel<<<blocks, threads>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), total, N, M, D);\n }\n return O;\n}\n'''\n\n_ext = load_inline(name='rbf_cov_ext_v2', cpp_sources=_cpp_src, cuda_sources=_cuda_src,\n functions=['rbf_forward'], verbose=False,\n extra_cuda_cflags=['-O3', '--use_fast_math'])\n\nclass ModelNew(nn.Module):\n def __init__(self, input_dim, lengthscale=1.0, variance=1.0):\n super().__init__()\n self.log_lengthscale = nn.Parameter(torch.tensor(lengthscale).log())\n self.log_variance = nn.Parameter(torch.tensor(variance).log())\n def forward(self, X1: torch.Tensor, X2: torch.Tensor) -> torch.Tensor:\n return _ext.rbf_forward(X1, X2, self.log_lengthscale, self.log_variance)\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 39.8s turn · 9.8s LLM · 0.0s tools
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(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define TILE_N 16\n#define TILE_M 16\n#define D_FIXED 8\n\n__global__ void rbf_d8_tiled_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int B, int N, int M) {\n __shared__ float sx1[TILE_N][D_FIXED];\n __shared__ float sx2[TILE_M][D_FIXED];\n __shared__ float scale;\n __shared__ float var;\n\n const int tx = threadIdx.x;\n const int ty = threadIdx.y;\n const int tid = ty * TILE_M + tx;\n\n if (tid == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n\n const int b = blockIdx.z;\n const int n0 = blockIdx.y * TILE_N;\n const int m0 = blockIdx.x * TILE_M;\n\n if (tid < 128) {\n int row = tid >> 3;\n int d = tid & 7;\n int n = n0 + row;\n sx1[row][d] = (n < N) ? X1[((b * N + n) * D_FIXED + d)] : 0.0f;\n } else {\n int t = tid - 128;\n int row = t >> 3;\n int d = t & 7;\n int m = m0 + row;\n sx2[row][d] = (m < M) ? X2[((b * M + m) * D_FIXED + d)] : 0.0f;\n }\n __syncthreads();\n\n const int n = n0 + ty;\n const int m = m0 + tx;\n if (n < N && m < M) {\n float s = 0.0f;\n #pragma unroll\n for (int d = 0; d < D_FIXED; ++d) {\n float diff = sx1[ty][d] - sx2[tx][d];\n s = fmaf(diff, diff, s);\n }\n O[(b * N + n) * M + m] = var * __expf(scale * s);\n }\n}\n\n__global__ void rbf_generic_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int total, int N, int M, int D) {\n __shared__ float scale;\n __shared__ float var;\n if (threadIdx.x == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n __syncthreads();\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int m = idx % M;\n int t = idx / M;\n int n = t % N;\n int b = t / N;\n const float* p1 = X1 + ((b * N + n) * D);\n const float* p2 = X2 + ((b * M + m) * D);\n float s = 0.0f;\n for (int d = 0; d < D; ++d) {\n float diff = p1[d] - p2[d];\n s = fmaf(diff, diff, s);\n }\n O[idx] = var * __expf(scale * s);\n}\n\ntorch::Tensor rbf_forward(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v) {\n const int B = (int)X1.size(0);\n const int N = (int)X1.size(1);\n const int D = (int)X1.size(2);\n const int M = (int)X2.size(1);\n auto O = torch::empty({B, N, M}, X1.options());\n if (D == 8) {\n dim3 block(TILE_M, TILE_N, 1);\n dim3 grid((M + TILE_M - 1) / TILE_M, (N + TILE_N - 1) / TILE_N, B);\n rbf_d8_tiled_kernel<<<grid, block>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), B, N, M);\n } else {\n int total = B * N * M;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n rbf_generic_kernel<<<blocks, threads>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), total, N, M, D);\n }\n return O;\n}\n'''\n\n_ext = load_inline(name='rbf_cov_ext_v2c', cpp_sources=_cpp_src, cuda_sources=_cuda_src,\n functions=['rbf_forward'], verbose=False,\n extra_cuda_cflags=['-O3', '--use_fast_math'])\n\nclass ModelNew(nn.Module):\n def __init__(self, input_dim, lengthscale=1.0, variance=1.0):\n super().__init__()\n self.log_lengthscale = nn.Parameter(torch.tensor(lengthscale).log())\n self.log_variance = nn.Parameter(torch.tensor(variance).log())\n def forward(self, X1: torch.Tensor, X2: torch.Tensor) -> torch.Tensor:\n return _ext.rbf_forward(X1, X2, self.log_lengthscale, self.log_variance)\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=7.75e-07 mean_abs_err=2.87e-09 max_rel_err=7.26e-06
turn 4 · 1 tool call(s) · 25.0s turn · 25.0s LLM · 6,271 chars (click to expand)
turn 425.0s turn · 25.0s LLM · 0.0s tools
reasoning
**Considering sync costs**
I'm thinking about how shared elements might improve things, but sync costs could be a concern. The 4096 blocks for sync don't seem too large. Perhaps I should compute using an expansion formula or precomputed norms, but that could require separate kernels and norm arrays, which isn't ideal. Maybe I can leverage tensor cores for dot products, but the output complexity might dominate. Custom fusions could help streamline this process.
call → static_check
callstatic_check
{
"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(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define TILE_N 16\n#define TILE_M 16\n#define D_FIXED 8\n\n__global__ void rbf_d8_tiled_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int B, int N, int M) {\n __shared__ float sx1[TILE_N][D_FIXED];\n __shared__ float sx2[TILE_M][D_FIXED];\n __shared__ float scale;\n __shared__ float var;\n\n const int tx = threadIdx.x;\n const int ty = threadIdx.y;\n const int tid = ty * TILE_M + tx;\n\n if (tid == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n\n const int b = blockIdx.z;\n const int n0 = blockIdx.y * TILE_N;\n const int m0 = blockIdx.x * TILE_M;\n\n if (tid < 128) {\n int row = tid >> 3;\n int d = tid & 7;\n int n = n0 + row;\n sx1[row][d] = (n < N) ? X1[((b * N + n) * D_FIXED + d)] : 0.0f;\n } else {\n int t = tid - 128;\n int row = t >> 3;\n int d = t & 7;\n int m = m0 + row;\n sx2[row][d] = (m < M) ? X2[((b * M + m) * D_FIXED + d)] : 0.0f;\n }\n __syncthreads();\n\n const int n = n0 + ty;\n const int m = m0 + tx;\n if (n < N && m < M) {\n float s = 0.0f;\n #pragma unroll\n for (int d = 0; d < D_FIXED; ++d) {\n float diff = sx1[ty][d] - sx2[tx][d];\n s = fmaf(diff, diff, s);\n }\n O[(b * N + n) * M + m] = var * __expf(scale * s);\n }\n}\n\n__global__ void rbf_generic_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int total, int N, int M, int D) {\n __shared__ float scale;\n __shared__ float var;\n if (threadIdx.x == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n __syncthreads();\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int m = idx % M;\n int t = idx / M;\n int n = t % N;\n int b = t / N;\n const float* p1 = X1 + ((b * N + n) * D);\n const float* p2 = X2 + ((b * M + m) * D);\n float s = 0.0f;\n for (int d = 0; d < D; ++d) {\n float diff = p1[d] - p2[d];\n s = fmaf(diff, diff, s);\n }\n O[idx] = var * __expf(scale * s);\n}\n\ntorch::Tensor rbf_forward(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v) {\n const int B = (int)X1.size(0);\n const int N = (int)X1.size(1);\n const int D = (int)X1.size(2);\n const int M = (int)X2.size(1);\n auto O = torch::empty({B, N, M}, X1.options());\n if (D == 8) {\n dim3 block(TILE_M, TILE_N, 1);\n dim3 grid((M + TILE_M - 1) / TILE_M, (N + TILE_N - 1) / TILE_N, B);\n rbf_d8_tiled_kernel<<<grid, block>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), B, N, M);\n } else {\n int total = B * N * M;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n rbf_generic_kernel<<<blocks, threads>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), total, N, M, D);\n }\n return O;\n}\n'''\n\n_ext = load_inline(name='rbf_cov_ext_v2s', cpp_sources=_cpp_src, cuda_sources=_cuda_src,\n functions=['rbf_forward'], verbose=False,\n extra_cuda_cflags=['-O3', '--use_fast_math'])\n\nclass ModelNew(nn.Module):\n def __init__(self, input_dim, lengthscale=1.0, variance=1.0):\n super().__init__()\n self.log_lengthscale = nn.Parameter(torch.tensor(lengthscale).log())\n self.log_variance = nn.Parameter(torch.tensor(variance).log())\n def forward(self, X1: torch.Tensor, X2: torch.Tensor) -> torch.Tensor:\n return _ext.rbf_forward(X1, X2, self.log_lengthscale, self.log_variance)\n"
}
result ← static_check (ok)
okstatic_check
static_check PASSED: no violations or warnings detected.
turn 520.7s turn · 20.7s LLM · 0.0s tools
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(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define TILE_N 8\n#define TILE_M 32\n#define D_FIXED 8\n#define DPAD 9\n\n__global__ void rbf_d8_tiled_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int B, int N, int M) {\n __shared__ float sx1[TILE_N][DPAD];\n __shared__ float sx2[TILE_M][DPAD];\n __shared__ float scale;\n __shared__ float var;\n\n const int tx = threadIdx.x; // 0..31, contiguous M\n const int ty = threadIdx.y; // 0..7, N\n const int tid = ty * TILE_M + tx;\n\n if (tid == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n\n const int b = blockIdx.z;\n const int n0 = blockIdx.y * TILE_N;\n const int m0 = blockIdx.x * TILE_M;\n\n if (tid < TILE_N * D_FIXED) {\n int row = tid >> 3;\n int d = tid & 7;\n int n = n0 + row;\n sx1[row][d] = (n < N) ? X1[((b * N + n) * D_FIXED + d)] : 0.0f;\n }\n if (tid < TILE_M * D_FIXED) {\n int row = tid >> 3;\n int d = tid & 7;\n int m = m0 + row;\n sx2[row][d] = (m < M) ? X2[((b * M + m) * D_FIXED + d)] : 0.0f;\n }\n __syncthreads();\n\n const int n = n0 + ty;\n const int m = m0 + tx;\n if (n < N && m < M) {\n float s = 0.0f;\n #pragma unroll\n for (int d = 0; d < D_FIXED; ++d) {\n float diff = sx1[ty][d] - sx2[tx][d];\n s = fmaf(diff, diff, s);\n }\n O[(b * N + n) * M + m] = var * __expf(scale * s);\n }\n}\n\n__global__ void rbf_generic_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int total, int N, int M, int D) {\n __shared__ float scale;\n __shared__ float var;\n if (threadIdx.x == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n __syncthreads();\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int m = idx % M;\n int t = idx / M;\n int n = t % N;\n int b = t / N;\n const float* p1 = X1 + ((b * N + n) * D);\n const float* p2 = X2 + ((b * M + m) * D);\n float s = 0.0f;\n for (int d = 0; d < D; ++d) {\n float diff = p1[d] - p2[d];\n s = fmaf(diff, diff, s);\n }\n O[idx] = var * __expf(scale * s);\n}\n\ntorch::Tensor rbf_forward(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v) {\n const int B = (int)X1.size(0);\n const int N = (int)X1.size(1);\n const int D = (int)X1.size(2);\n const int M = (int)X2.size(1);\n auto O = torch::empty({B, N, M}, X1.options());\n if (D == 8) {\n dim3 block(TILE_M, TILE_N, 1);\n dim3 grid((M + TILE_M - 1) / TILE_M, (N + TILE_N - 1) / TILE_N, B);\n rbf_d8_tiled_kernel<<<grid, block>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), B, N, M);\n } else {\n int total = B * N * M;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n rbf_generic_kernel<<<blocks, threads>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), total, N, M, D);\n }\n return O;\n}\n'''\n\n_ext = load_inline(name='rbf_cov_ext_v3', cpp_sources=_cpp_src, cuda_sources=_cuda_src,\n functions=['rbf_forward'], verbose=False,\n extra_cuda_cflags=['-O3', '--use_fast_math'])\n\nclass ModelNew(nn.Module):\n def __init__(self, input_dim, lengthscale=1.0, variance=1.0):\n super().__init__()\n self.log_lengthscale = nn.Parameter(torch.tensor(lengthscale).log())\n self.log_variance = nn.Parameter(torch.tensor(variance).log())\n def forward(self, X1: torch.Tensor, X2: torch.Tensor) -> torch.Tensor:\n return _ext.rbf_forward(X1, X2, self.log_lengthscale, self.log_variance)\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=7.75e-07 mean_abs_err=2.87e-09 max_rel_err=7.26e-06
turn 69.9s turn · 9.9s LLM · 0.0s tools
call → static_check
callstatic_check
{
"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(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define TILE_N 8\n#define TILE_M 32\n#define D_FIXED 8\n#define DPAD 9\n\n__global__ void rbf_d8_tiled_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int B, int N, int M) {\n __shared__ float sx1[TILE_N][DPAD];\n __shared__ float sx2[TILE_M][DPAD];\n __shared__ float scale;\n __shared__ float var;\n\n const int tx = threadIdx.x;\n const int ty = threadIdx.y;\n const int tid = ty * TILE_M + tx;\n\n if (tid == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n\n const int b = blockIdx.z;\n const int n0 = blockIdx.y * TILE_N;\n const int m0 = blockIdx.x * TILE_M;\n\n if (tid < TILE_N * D_FIXED) {\n int row = tid >> 3;\n int d = tid & 7;\n int n = n0 + row;\n sx1[row][d] = (n < N) ? X1[((b * N + n) * D_FIXED + d)] : 0.0f;\n }\n if (tid < TILE_M * D_FIXED) {\n int row = tid >> 3;\n int d = tid & 7;\n int m = m0 + row;\n sx2[row][d] = (m < M) ? X2[((b * M + m) * D_FIXED + d)] : 0.0f;\n }\n __syncthreads();\n\n const int n = n0 + ty;\n const int m = m0 + tx;\n if (n < N && m < M) {\n float s = 0.0f;\n #pragma unroll\n for (int d = 0; d < D_FIXED; ++d) {\n float diff = sx1[ty][d] - sx2[tx][d];\n s = fmaf(diff, diff, s);\n }\n O[(b * N + n) * M + m] = var * __expf(scale * s);\n }\n}\n\n__global__ void rbf_generic_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int total, int N, int M, int D) {\n __shared__ float scale;\n __shared__ float var;\n if (threadIdx.x == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n __syncthreads();\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int m = idx % M;\n int t = idx / M;\n int n = t % N;\n int b = t / N;\n const float* p1 = X1 + ((b * N + n) * D);\n const float* p2 = X2 + ((b * M + m) * D);\n float s = 0.0f;\n for (int d = 0; d < D; ++d) {\n float diff = p1[d] - p2[d];\n s = fmaf(diff, diff, s);\n }\n O[idx] = var * __expf(scale * s);\n}\n\ntorch::Tensor rbf_forward(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v) {\n const int B = (int)X1.size(0);\n const int N = (int)X1.size(1);\n const int D = (int)X1.size(2);\n const int M = (int)X2.size(1);\n auto O = torch::empty({B, N, M}, X1.options());\n if (D == 8) {\n dim3 block(TILE_M, TILE_N, 1);\n dim3 grid((M + TILE_M - 1) / TILE_M, (N + TILE_N - 1) / TILE_N, B);\n rbf_d8_tiled_kernel<<<grid, block>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), B, N, M);\n } else {\n int total = B * N * M;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n rbf_generic_kernel<<<blocks, threads>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), total, N, M, D);\n }\n return O;\n}\n'''\n\n_ext = load_inline(name='rbf_cov_ext_v3s', cpp_sources=_cpp_src, cuda_sources=_cuda_src,\n functions=['rbf_forward'], verbose=False,\n extra_cuda_cflags=['-O3', '--use_fast_math'])\n\nclass ModelNew(nn.Module):\n def __init__(self, input_dim, lengthscale=1.0, variance=1.0):\n super().__init__()\n self.log_lengthscale = nn.Parameter(torch.tensor(lengthscale).log())\n self.log_variance = nn.Parameter(torch.tensor(variance).log())\n def forward(self, X1: torch.Tensor, X2: torch.Tensor) -> torch.Tensor:\n return _ext.rbf_forward(X1, X2, self.log_lengthscale, self.log_variance)\n"
}
result ← static_check (ok)
okstatic_check
static_check PASSED: no violations or warnings detected.
turn 7 · FINAL · 1 tool call(s) · 11.7s turn · 11.7s LLM · 6,040 chars (click to expand)
turn 711.7s turn · 11.7s LLM · 0.0s tools · FINAL
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>\ntorch::Tensor rbf_forward(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define TILE_N 8\n#define TILE_M 32\n#define D_FIXED 8\n#define DPAD 9\n\n__global__ void rbf_d8_tiled_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int B, int N, int M) {\n __shared__ float sx1[TILE_N][DPAD];\n __shared__ float sx2[TILE_M][DPAD];\n __shared__ float scale;\n __shared__ float var;\n\n const int tx = threadIdx.x;\n const int ty = threadIdx.y;\n const int tid = ty * TILE_M + tx;\n\n if (tid == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n\n const int b = blockIdx.z;\n const int n0 = blockIdx.y * TILE_N;\n const int m0 = blockIdx.x * TILE_M;\n\n if (tid < TILE_N * D_FIXED) {\n int row = tid >> 3;\n int d = tid & 7;\n int n = n0 + row;\n sx1[row][d] = (n < N) ? X1[((b * N + n) * D_FIXED + d)] : 0.0f;\n }\n if (tid < TILE_M * D_FIXED) {\n int row = tid >> 3;\n int d = tid & 7;\n int m = m0 + row;\n sx2[row][d] = (m < M) ? X2[((b * M + m) * D_FIXED + d)] : 0.0f;\n }\n __syncthreads();\n\n const int n = n0 + ty;\n const int m = m0 + tx;\n if (n < N && m < M) {\n float s = 0.0f;\n #pragma unroll\n for (int d = 0; d < D_FIXED; ++d) {\n float diff = sx1[ty][d] - sx2[tx][d];\n s = fmaf(diff, diff, s);\n }\n O[(b * N + n) * M + m] = var * __expf(scale * s);\n }\n}\n\n__global__ void rbf_generic_kernel(const float* __restrict__ X1,\n const float* __restrict__ X2,\n const float* __restrict__ log_l,\n const float* __restrict__ log_v,\n float* __restrict__ O,\n int total, int N, int M, int D) {\n __shared__ float scale;\n __shared__ float var;\n if (threadIdx.x == 0) {\n float l = __expf(log_l[0]);\n scale = -0.5f / (l * l);\n var = __expf(log_v[0]);\n }\n __syncthreads();\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int m = idx % M;\n int t = idx / M;\n int n = t % N;\n int b = t / N;\n const float* p1 = X1 + ((b * N + n) * D);\n const float* p2 = X2 + ((b * M + m) * D);\n float s = 0.0f;\n for (int d = 0; d < D; ++d) {\n float diff = p1[d] - p2[d];\n s = fmaf(diff, diff, s);\n }\n O[idx] = var * __expf(scale * s);\n}\n\ntorch::Tensor rbf_forward(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v) {\n const int B = (int)X1.size(0);\n const int N = (int)X1.size(1);\n const int D = (int)X1.size(2);\n const int M = (int)X2.size(1);\n auto O = torch::empty({B, N, M}, X1.options());\n if (D == 8) {\n dim3 block(TILE_M, TILE_N, 1);\n dim3 grid((M + TILE_M - 1) / TILE_M, (N + TILE_N - 1) / TILE_N, B);\n rbf_d8_tiled_kernel<<<grid, block>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), B, N, M);\n } else {\n int total = B * N * M;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n rbf_generic_kernel<<<blocks, threads>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),\n log_l.data_ptr<float>(), log_v.data_ptr<float>(),\n O.data_ptr<float>(), total, N, M, D);\n }\n return O;\n}\n'''\n\n_ext = load_inline(name='rbf_cov_ext_final', cpp_sources=_cpp_src, cuda_sources=_cuda_src,\n functions=['rbf_forward'], verbose=False,\n extra_cuda_cflags=['-O3', '--use_fast_math'])\n\nclass ModelNew(nn.Module):\n def __init__(self, input_dim, lengthscale=1.0, variance=1.0):\n super().__init__()\n self.log_lengthscale = nn.Parameter(torch.tensor(lengthscale).log())\n self.log_variance = nn.Parameter(torch.tensor(variance).log())\n def forward(self, X1: torch.Tensor, X2: torch.Tensor) -> torch.Tensor:\n return _ext.rbf_forward(X1, X2, self.log_lengthscale, self.log_variance)\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=7.75e-07 mean_abs_err=2.87e-09 max_rel_err=7.26e-06
Memory: 37.31 MB peak (ref: 45.35 MB, ratio: 0.8227x)
Kernel launches: 1 (ref: 37, fusion ratio: 37.0)
SOL score: 0.1603
final submitted kernel (137 lines, 4,789 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline
_cpp_src = r'''
#include <torch/extension.h>
torch::Tensor rbf_forward(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v);
'''
_cuda_src = r'''
#include <torch/extension.h>
#include <cuda.h>
#include <cuda_runtime.h>
#define TILE_N 8
#define TILE_M 32
#define D_FIXED 8
#define DPAD 9
__global__ void rbf_d8_tiled_kernel(const float* __restrict__ X1,
const float* __restrict__ X2,
const float* __restrict__ log_l,
const float* __restrict__ log_v,
float* __restrict__ O,
int B, int N, int M) {
__shared__ float sx1[TILE_N][DPAD];
__shared__ float sx2[TILE_M][DPAD];
__shared__ float scale;
__shared__ float var;
const int tx = threadIdx.x;
const int ty = threadIdx.y;
const int tid = ty * TILE_M + tx;
if (tid == 0) {
float l = __expf(log_l[0]);
scale = -0.5f / (l * l);
var = __expf(log_v[0]);
}
const int b = blockIdx.z;
const int n0 = blockIdx.y * TILE_N;
const int m0 = blockIdx.x * TILE_M;
if (tid < TILE_N * D_FIXED) {
int row = tid >> 3;
int d = tid & 7;
int n = n0 + row;
sx1[row][d] = (n < N) ? X1[((b * N + n) * D_FIXED + d)] : 0.0f;
}
if (tid < TILE_M * D_FIXED) {
int row = tid >> 3;
int d = tid & 7;
int m = m0 + row;
sx2[row][d] = (m < M) ? X2[((b * M + m) * D_FIXED + d)] : 0.0f;
}
__syncthreads();
const int n = n0 + ty;
const int m = m0 + tx;
if (n < N && m < M) {
float s = 0.0f;
#pragma unroll
for (int d = 0; d < D_FIXED; ++d) {
float diff = sx1[ty][d] - sx2[tx][d];
s = fmaf(diff, diff, s);
}
O[(b * N + n) * M + m] = var * __expf(scale * s);
}
}
__global__ void rbf_generic_kernel(const float* __restrict__ X1,
const float* __restrict__ X2,
const float* __restrict__ log_l,
const float* __restrict__ log_v,
float* __restrict__ O,
int total, int N, int M, int D) {
__shared__ float scale;
__shared__ float var;
if (threadIdx.x == 0) {
float l = __expf(log_l[0]);
scale = -0.5f / (l * l);
var = __expf(log_v[0]);
}
__syncthreads();
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx >= total) return;
int m = idx % M;
int t = idx / M;
int n = t % N;
int b = t / N;
const float* p1 = X1 + ((b * N + n) * D);
const float* p2 = X2 + ((b * M + m) * D);
float s = 0.0f;
for (int d = 0; d < D; ++d) {
float diff = p1[d] - p2[d];
s = fmaf(diff, diff, s);
}
O[idx] = var * __expf(scale * s);
}
torch::Tensor rbf_forward(torch::Tensor X1, torch::Tensor X2, torch::Tensor log_l, torch::Tensor log_v) {
const int B = (int)X1.size(0);
const int N = (int)X1.size(1);
const int D = (int)X1.size(2);
const int M = (int)X2.size(1);
auto O = torch::empty({B, N, M}, X1.options());
if (D == 8) {
dim3 block(TILE_M, TILE_N, 1);
dim3 grid((M + TILE_M - 1) / TILE_M, (N + TILE_N - 1) / TILE_N, B);
rbf_d8_tiled_kernel<<<grid, block>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),
log_l.data_ptr<float>(), log_v.data_ptr<float>(),
O.data_ptr<float>(), B, N, M);
} else {
int total = B * N * M;
int threads = 256;
int blocks = (total + threads - 1) / threads;
rbf_generic_kernel<<<blocks, threads>>>(X1.data_ptr<float>(), X2.data_ptr<float>(),
log_l.data_ptr<float>(), log_v.data_ptr<float>(),
O.data_ptr<float>(), total, N, M, D);
}
return O;
}
'''
_ext = load_inline(name='rbf_cov_ext_final', cpp_sources=_cpp_src, cuda_sources=_cuda_src,
functions=['rbf_forward'], verbose=False,
extra_cuda_cflags=['-O3', '--use_fast_math'])
class ModelNew(nn.Module):
def __init__(self, input_dim, lengthscale=1.0, variance=1.0):
super().__init__()
self.log_lengthscale = nn.Parameter(torch.tensor(lengthscale).log())
self.log_variance = nn.Parameter(torch.tensor(variance).log())
def forward(self, X1: torch.Tensor, X2: torch.Tensor) -> torch.Tensor:
return _ext.rbf_forward(X1, X2, self.log_lengthscale, self.log_variance)