incorrect
9_BayesianLinearRegression.py
started
2026-05-11T12:42:10Z
correctness issue: Output mismatch
timingkernelbench.timing
kernel mean / median / std
—
ref mean / median / std
0.45 / — / 0.03 μs
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):
"""
Bayesian linear regression with a conjugate Gaussian prior.
Given features X and targets y, computes the posterior distribution
over weights: p(w | X, y) = N(mu_post, Sigma_post) in closed form
via the matrix inversion lemma / Cholesky decomposition.
"""
def __init__(self, input_dim, prior_precision=1.0, noise_precision=1.0):
super().__init__()
self.input_dim = input_dim
self.prior_precision = prior_precision
self.noise_precision = noise_precision
def forward(
self, X: torch.Tensor, y: torch.Tensor, X_test: torch.Tensor
) -> tuple:
"""
Args:
X: (B, N, D) – training features
y: (B, N, 1) – training targets
X_test: (B, M, D) – test features
Returns:
(pred_mean, pred_var):
pred_mean: (B, M, 1)
pred_var: (B, M)
"""
D = X.shape[-1]
eye = torch.eye(D, device=X.device, dtype=X.dtype).unsqueeze(0)
# Posterior precision: Lambda_post = alpha * I + beta * X^T X
Lambda_post = self.prior_precision * eye + self.noise_precision * (X.transpose(-1, -2) @ X)
L = torch.linalg.cholesky(Lambda_post)
# Posterior mean: mu_post = Lambda_post^{-1} * beta * X^T y
rhs = self.noise_precision * (X.transpose(-1, -2) @ y)
mu_post = torch.cholesky_solve(rhs, L)
# Predictive distribution
pred_mean = X_test @ mu_post
Sigma_post = torch.cholesky_inverse(L)
pred_var = (X_test @ Sigma_post * X_test).sum(-1) + 1.0 / self.noise_precision
return pred_mean, pred_var
input_dim = 16
num_train = 256
num_test = 64
batch_size = 16
def get_inputs():
p = popcorn_pri
X = torch.randn(p.jitter_int(batch_size), p.jitter_int(num_train), input_dim)
y = torch.randn(p.jitter_int(batch_size), p.jitter_int(num_train), 1)
X_test = torch.randn(p.jitter_int(batch_size), p.jitter_int(num_test), input_dim)
return [X, y, X_test]
def get_init_inputs():
return [input_dim]
turn 0 · 0 tool call(s) · 11.6s turn · 11.6s LLM · tokens in=1,770 · out=1,834 · total=3,948 · 6,567 chars (click to expand)
turn 011.6s turn · 11.6s LLM · 0.0s tools · tokens in=1,770 · out=1,834 · total=3,948
reasoning
The task is to replace the forward computation of this Bayesian linear regression model with a custom CUDA kernel that's faster than PyTorch.
assistant```python
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline
cuda_source = r'''
#include <torch/extension.h>
#include <cuda.h>
#include <cuda_runtime.h>
#define BLOCK_SIZE 16
__global__ void bayesian_linear_kernel(
const float* __restrict__ X,
const float* __restrict__ y,
const float* __restrict__ X_test,
float* __restrict__ pred_mean,
float* __restrict__ pred_var,
int B, int N, int D, int M,
float prior_precision, float noise_precision
) {
int b = blockIdx.x;
if (b >= B) return;
extern __shared__ float smem[];
const float* Xb = X + b * N * D;
const float* yb = y + b * N;
const float* Xt = X_test + b * M * D;
float* Lambda = smem; // D*D
float* Lchol = smem + D*D; // D*D
float* rhs = smem + 2*D*D; // D
float* mu = smem + 2*D*D + D; // D
float* Sigma = smem + 2*D*D + 2*D; // D*D
float* temp = smem + 3*D*D + 2*D; // D*D or scratch
// Compute X^T X and X^T y
for (int i = threadIdx.x; i < D*D; i += blockDim.x) {
int row = i / D;
int col = i % D;
float sum = 0.0f;
for (int k = 0; k < N; k++) {
sum += Xb[k*D + row] * Xb[k*D + col];
}
Lambda[i] = prior_precision * (row == col ? 1.0f : 0.0f) + noise_precision * sum;
}
__syncthreads();
// Cholesky decomposition (naive, for D=16)
for (int i = 0; i < D; i++) {
for (int j = threadIdx.x; j <= i; j += blockDim.x) {
float sum = 0.0f;
for (int k = 0; k < j; k++) {
sum += Lchol[i*D + k] * Lchol[j*D + k];
}
if (i == j) {
Lchol[i*D + i] = sqrtf(Lambda[i*D + i] - sum);
} else {
Lchol[i*D + j] = (Lambda[i*D + j] - sum) / Lchol[j*D + j];
}
}
__syncthreads();
}
// rhs = noise * X^T y
for (int i = threadIdx.x; i < D; i += blockDim.x) {
float sum = 0.0f;
for (int k = 0; k < N; k++) {
sum += Xb[k*D + i] * yb[k];
}
rhs[i] = noise_precision * sum;
}
__syncthreads();
// cholesky_solve: forward then back sub
// Forward: L z = rhs
for (int i = 0; i < D; i++) {
if (threadIdx.x == 0) {
float sum = 0.0f;
for (int k = 0; k < i; k++) sum += Lchol[i*D + k] * mu[k];
mu[i] = (rhs[i] - sum) / Lchol[i*D + i];
}
__syncthreads();
}
// Back: L^T mu = z
for (int i = D-1; i >= 0; i--) {
if (threadIdx.x == 0) {
float sum = 0.0f;
for (int k = i+1; k < D; k++) sum += Lchol[k*D + i] * mu[k];
mu[i] = (mu[i] - sum) / Lchol[i*D + i];
}
__syncthreads();
}
// pred_mean = X_test @ mu
for (int m = threadIdx.x; m < M; m += blockDim.x) {
float sum = 0.0f;
for (int d = 0; d < D; d++) {
sum += Xt[m*D + d] * mu[d];
}
pred_mean[b*M + m] = sum;
}
// cholesky_inverse: solve L L^T Sigma = I
for (int col = 0; col < D; col++) {
// forward sub for each column
for (int i = 0; i < D; i++) {
if (threadIdx.x == 0) {
float sum = (i == col ? 1.0f : 0.0f);
for (int k = 0; k < i; k++) sum -= Lchol[i*D + k] * temp[k*D + col];
temp[i*D + col] = sum / Lchol[i*D + i];
}
__syncthreads();
}
// back sub
for (int i = D-1; i >= 0; i--) {
if (threadIdx.x == 0) {
float sum = temp[i*D + col];
for (int k = i+1; k < D; k++) sum -= Lchol[k*D + i] * Sigma[k*D + col];
Sigma[i*D + col] = sum / Lchol[i*D + i];
}
__syncthreads();
}
}
// pred_var
for (int m = threadIdx.x; m < M; m += blockDim.x) {
float sum = 0.0f;
for (int d = 0; d < D; d++) {
float tmp = 0.0f;
for (int e = 0; e < D; e++) {
tmp += Xt[m*D + e] * Sigma[e*D + d];
}
sum += tmp * Xt[m*D + d];
}
pred_var[b*M + m] = sum + 1.0f / noise_precision;
}
}
std::vector<torch::Tensor> bayesian_linear_cuda(
torch::Tensor X, torch::Tensor y, torch::Tensor X_test,
float prior_precision, float noise_precision
) {
int B = X.size(0);
int N = X.size(1);
int D = X.size(2);
int M = X_test.size(1);
auto options = torch::TensorOptions().dtype(X.dtype()).device(X.device());
auto pred_mean = torch::zeros({B, M, 1}, options);
auto pred_var = torch::zeros({B, M}, options);
dim3 grid(B);
dim3 block(256);
int smem_size = (3*D*D + 2*D + D*D) * sizeof(float); // rough
bayesian_linear_kernel<<<grid, block, smem_size>>>(
X.data_ptr<float>(), y.data_ptr<float>(), X_test.data_ptr<float>(),
pred_mean.data_ptr<float>(), pred_var.data_ptr<float>(),
B, N, D, M, prior_precision, noise_precision
);
return {pred_mean, pred_var};
}
'''
cpp_source = '''
std::vector<torch::Tensor> bayesian_linear_cuda(
torch::Tensor X, torch::Tensor y, torch::Tensor X_test,
float prior_precision, float noise_precision
);
'''
module = load_inline(
name='bayesian_linear',
cpp_sources=cpp_source,
cuda_sources=cuda_source,
functions=['bayesian_linear_cuda'],
verbose=False
)
class ModelNew(nn.Module):
def __init__(self, input_dim, prior_precision=1.0, noise_precision=1.0):
super().__init__()
self.input_dim = input_dim
self.prior_precision = prior_precision
self.noise_precision = noise_precision
def forward(self, X, y, X_test):
res = module.bayesian_linear_cuda(X, y, X_test, self.prior_precision, self.noise_precision)
return res[0], res[1]
```
turn 1 · 1 tool call(s) · 119.0s turn · 9.2s LLM · tokens in=4,016 · out=1,841 · total=5,983 · 7,134 chars (click to expand)
turn 1119.0s turn · 9.2s LLM · 109.8s tools · tokens in=4,016 · out=1,841 · total=5,983
reasoning
The instruction says: "You must call at least one tool this turn: use `compile_kernel` / `run_correctness` to iterate, or call `submit_kernel` with your best `ModelNew` implementation to finalize the ...
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define BLOCK_SIZE 16\n\n__global__ void bayesian_linear_kernel(\n const float* __restrict__ X,\n const float* __restrict__ y,\n const float* __restrict__ X_test,\n float* __restrict__ pred_mean,\n float* __restrict__ pred_var,\n int B, int N, int D, int M,\n float prior_precision, float noise_precision\n) {\n int b = blockIdx.x;\n if (b >= B) return;\n\n extern __shared__ float smem[];\n\n const float* Xb = X + b * N * D;\n const float* yb = y + b * N;\n const float* Xt = X_test + b * M * D;\n\n float* Lambda = smem; // D*D\n float* Lchol = smem + D*D; // D*D\n float* rhs = smem + 2*D*D; // D\n float* mu = smem + 2*D*D + D; // D\n float* Sigma = smem + 2*D*D + 2*D; // D*D\n float* temp = smem + 3*D*D + 2*D; // D*D or scratch\n\n // Compute X^T X and X^T y\n for (int i = threadIdx.x; i < D*D; i += blockDim.x) {\n int row = i / D;\n int col = i % D;\n float sum = 0.0f;\n for (int k = 0; k < N; k++) {\n sum += Xb[k*D + row] * Xb[k*D + col];\n }\n Lambda[i] = prior_precision * (row == col ? 1.0f : 0.0f) + noise_precision * sum;\n }\n __syncthreads();\n\n // Cholesky decomposition (naive, for D=16)\n for (int i = 0; i < D; i++) {\n for (int j = threadIdx.x; j <= i; j += blockDim.x) {\n float sum = 0.0f;\n for (int k = 0; k < j; k++) {\n sum += Lchol[i*D + k] * Lchol[j*D + k];\n }\n if (i == j) {\n Lchol[i*D + i] = sqrtf(Lambda[i*D + i] - sum);\n } else {\n Lchol[i*D + j] = (Lambda[i*D + j] - sum) / Lchol[j*D + j];\n }\n }\n __syncthreads();\n }\n\n // rhs = noise * X^T y\n for (int i = threadIdx.x; i < D; i += blockDim.x) {\n float sum = 0.0f;\n for (int k = 0; k < N; k++) {\n sum += Xb[k*D + i] * yb[k];\n }\n rhs[i] = noise_precision * sum;\n }\n __syncthreads();\n\n // cholesky_solve: forward then back sub\n // Forward: L z = rhs\n for (int i = 0; i < D; i++) {\n if (threadIdx.x == 0) {\n float sum = 0.0f;\n for (int k = 0; k < i; k++) sum += Lchol[i*D + k] * mu[k];\n mu[i] = (rhs[i] - sum) / Lchol[i*D + i];\n }\n __syncthreads();\n }\n // Back: L^T mu = z\n for (int i = D-1; i >= 0; i--) {\n if (threadIdx.x == 0) {\n float sum = 0.0f;\n for (int k = i+1; k < D; k++) sum += Lchol[k*D + i] * mu[k];\n mu[i] = (mu[i] - sum) / Lchol[i*D + i];\n }\n __syncthreads();\n }\n\n // pred_mean = X_test @ mu\n for (int m = threadIdx.x; m < M; m += blockDim.x) {\n float sum = 0.0f;\n for (int d = 0; d < D; d++) {\n sum += Xt[m*D + d] * mu[d];\n }\n pred_mean[b*M + m] = sum;\n }\n\n // cholesky_inverse: solve L L^T Sigma = I\n for (int col = 0; col < D; col++) {\n // forward sub for each column\n for (int i = 0; i < D; i++) {\n if (threadIdx.x == 0) {\n float sum = (i == col ? 1.0f : 0.0f);\n for (int k = 0; k < i; k++) sum -= Lchol[i*D + k] * temp[k*D + col];\n temp[i*D + col] = sum / Lchol[i*D + i];\n }\n __syncthreads();\n }\n // back sub\n for (int i = D-1; i >= 0; i--) {\n if (threadIdx.x == 0) {\n float sum = temp[i*D + col];\n for (int k = i+1; k < D; k++) sum -= Lchol[k*D + i] * Sigma[k*D + col];\n Sigma[i*D + col] = sum / Lchol[i*D + i];\n }\n __syncthreads();\n }\n }\n\n // pred_var\n for (int m = threadIdx.x; m < M; m += blockDim.x) {\n float sum = 0.0f;\n for (int d = 0; d < D; d++) {\n float tmp = 0.0f;\n for (int e = 0; e < D; e++) {\n tmp += Xt[m*D + e] * Sigma[e*D + d];\n }\n sum += tmp * Xt[m*D + d];\n }\n pred_var[b*M + m] = sum + 1.0f / noise_precision;\n }\n}\n\nstd::vector<torch::Tensor> bayesian_linear_cuda(\n torch::Tensor X, torch::Tensor y, torch::Tensor X_test,\n float prior_precision, float noise_precision\n) {\n int B = X.size(0);\n int N = X.size(1);\n int D = X.size(2);\n int M = X_test.size(1);\n\n auto options = torch::TensorOptions().dtype(X.dtype()).device(X.device());\n auto pred_mean = torch::zeros({B, M, 1}, options);\n auto pred_var = torch::zeros({B, M}, options);\n\n dim3 grid(B);\n dim3 block(256);\n int smem_size = (3*D*D + 2*D + D*D) * sizeof(float); // rough\n\n bayesian_linear_kernel<<<grid, block, smem_size>>>(\n X.data_ptr<float>(), y.data_ptr<float>(), X_test.data_ptr<float>(),\n pred_mean.data_ptr<float>(), pred_var.data_ptr<float>(),\n B, N, D, M, prior_precision, noise_precision\n );\n\n return {pred_mean, pred_var};\n}\n'''\n\ncpp_source = '''\nstd::vector<torch::Tensor> bayesian_linear_cuda(\n torch::Tensor X, torch::Tensor y, torch::Tensor X_test,\n float prior_precision, float noise_precision\n);\n'''\n\nmodule = load_inline(\n name='bayesian_linear',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['bayesian_linear_cuda'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, input_dim, prior_precision=1.0, noise_precision=1.0):\n super().__init__()\n self.input_dim = input_dim\n self.prior_precision = prior_precision\n self.noise_precision = noise_precision\n\n def forward(self, X, y, X_test):\n res = module.bayesian_linear_cuda(X, y, X_test, self.prior_precision, self.noise_precision)\n return res[0], res[1]\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 2 · 1 tool call(s) · 137.0s turn · 12.2s LLM · tokens in=6,000 · out=1,842 · total=7,856 · 7,535 chars (click to expand)
turn 2137.0s turn · 12.2s LLM · 124.8s tools · tokens in=6,000 · out=1,842 · total=7,856
reasoning
It compiled successfully. Now I should check correctness with run_correctness.
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define BLOCK_SIZE 16\n\n__global__ void bayesian_linear_kernel(\n const float* __restrict__ X,\n const float* __restrict__ y,\n const float* __restrict__ X_test,\n float* __restrict__ pred_mean,\n float* __restrict__ pred_var,\n int B, int N, int D, int M,\n float prior_precision, float noise_precision\n) {\n int b = blockIdx.x;\n if (b >= B) return;\n\n extern __shared__ float smem[];\n\n const float* Xb = X + b * N * D;\n const float* yb = y + b * N;\n const float* Xt = X_test + b * M * D;\n\n float* Lambda = smem; // D*D\n float* Lchol = smem + D*D; // D*D\n float* rhs = smem + 2*D*D; // D\n float* mu = smem + 2*D*D + D; // D\n float* Sigma = smem + 2*D*D + 2*D; // D*D\n float* temp = smem + 3*D*D + 2*D; // D*D or scratch\n\n // Compute X^T X and X^T y\n for (int i = threadIdx.x; i < D*D; i += blockDim.x) {\n int row = i / D;\n int col = i % D;\n float sum = 0.0f;\n for (int k = 0; k < N; k++) {\n sum += Xb[k*D + row] * Xb[k*D + col];\n }\n Lambda[i] = prior_precision * (row == col ? 1.0f : 0.0f) + noise_precision * sum;\n }\n __syncthreads();\n\n // Cholesky decomposition (naive, for D=16)\n for (int i = 0; i < D; i++) {\n for (int j = threadIdx.x; j <= i; j += blockDim.x) {\n float sum = 0.0f;\n for (int k = 0; k < j; k++) {\n sum += Lchol[i*D + k] * Lchol[j*D + k];\n }\n if (i == j) {\n Lchol[i*D + i] = sqrtf(Lambda[i*D + i] - sum);\n } else {\n Lchol[i*D + j] = (Lambda[i*D + j] - sum) / Lchol[j*D + j];\n }\n }\n __syncthreads();\n }\n\n // rhs = noise * X^T y\n for (int i = threadIdx.x; i < D; i += blockDim.x) {\n float sum = 0.0f;\n for (int k = 0; k < N; k++) {\n sum += Xb[k*D + i] * yb[k];\n }\n rhs[i] = noise_precision * sum;\n }\n __syncthreads();\n\n // cholesky_solve: forward then back sub\n // Forward: L z = rhs\n for (int i = 0; i < D; i++) {\n if (threadIdx.x == 0) {\n float sum = 0.0f;\n for (int k = 0; k < i; k++) sum += Lchol[i*D + k] * mu[k];\n mu[i] = (rhs[i] - sum) / Lchol[i*D + i];\n }\n __syncthreads();\n }\n // Back: L^T mu = z\n for (int i = D-1; i >= 0; i--) {\n if (threadIdx.x == 0) {\n float sum = 0.0f;\n for (int k = i+1; k < D; k++) sum += Lchol[k*D + i] * mu[k];\n mu[i] = (mu[i] - sum) / Lchol[i*D + i];\n }\n __syncthreads();\n }\n\n // pred_mean = X_test @ mu\n for (int m = threadIdx.x; m < M; m += blockDim.x) {\n float sum = 0.0f;\n for (int d = 0; d < D; d++) {\n sum += Xt[m*D + d] * mu[d];\n }\n pred_mean[b*M + m] = sum;\n }\n\n // cholesky_inverse: solve L L^T Sigma = I\n for (int col = 0; col < D; col++) {\n // forward sub for each column\n for (int i = 0; i < D; i++) {\n if (threadIdx.x == 0) {\n float sum = (i == col ? 1.0f : 0.0f);\n for (int k = 0; k < i; k++) sum -= Lchol[i*D + k] * temp[k*D + col];\n temp[i*D + col] = sum / Lchol[i*D + i];\n }\n __syncthreads();\n }\n // back sub\n for (int i = D-1; i >= 0; i--) {\n if (threadIdx.x == 0) {\n float sum = temp[i*D + col];\n for (int k = i+1; k < D; k++) sum -= Lchol[k*D + i] * Sigma[k*D + col];\n Sigma[i*D + col] = sum / Lchol[i*D + i];\n }\n __syncthreads();\n }\n }\n\n // pred_var\n for (int m = threadIdx.x; m < M; m += blockDim.x) {\n float sum = 0.0f;\n for (int d = 0; d < D; d++) {\n float tmp = 0.0f;\n for (int e = 0; e < D; e++) {\n tmp += Xt[m*D + e] * Sigma[e*D + d];\n }\n sum += tmp * Xt[m*D + d];\n }\n pred_var[b*M + m] = sum + 1.0f / noise_precision;\n }\n}\n\nstd::vector<torch::Tensor> bayesian_linear_cuda(\n torch::Tensor X, torch::Tensor y, torch::Tensor X_test,\n float prior_precision, float noise_precision\n) {\n int B = X.size(0);\n int N = X.size(1);\n int D = X.size(2);\n int M = X_test.size(1);\n\n auto options = torch::TensorOptions().dtype(X.dtype()).device(X.device());\n auto pred_mean = torch::zeros({B, M, 1}, options);\n auto pred_var = torch::zeros({B, M}, options);\n\n dim3 grid(B);\n dim3 block(256);\n int smem_size = (3*D*D + 2*D + D*D) * sizeof(float); // rough\n\n bayesian_linear_kernel<<<grid, block, smem_size>>>(\n X.data_ptr<float>(), y.data_ptr<float>(), X_test.data_ptr<float>(),\n pred_mean.data_ptr<float>(), pred_var.data_ptr<float>(),\n B, N, D, M, prior_precision, noise_precision\n );\n\n return {pred_mean, pred_var};\n}\n'''\n\ncpp_source = '''\nstd::vector<torch::Tensor> bayesian_linear_cuda(\n torch::Tensor X, torch::Tensor y, torch::Tensor X_test,\n float prior_precision, float noise_precision\n);\n'''\n\nmodule = load_inline(\n name='bayesian_linear',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['bayesian_linear_cuda'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, input_dim, prior_precision=1.0, noise_precision=1.0):\n super().__init__()\n self.input_dim = input_dim\n self.prior_precision = prior_precision\n self.noise_precision = noise_precision\n\n def forward(self, X, y, X_test):\n res = module.bayesian_linear_cuda(X, y, X_test, self.prior_precision, self.noise_precision)\n return res[0], res[1]\n"
}
result ← run_correctness (fail)
failrun_correctness
run_correctness FAILED: (0 / 5) trials did not all match.
correctness_issue: Output mismatch
max_difference: ['0.052969', '0.009739', '0.054024', '0.010747', '0.065366', '0.009737', '0.067590', '0.014611', '0.040142', '0.009076']
avg_difference: ['0.008337', '0.002116', '0.010259', '0.001980', '0.009305', '0.002084', '0.009591', '0.002139', '0.008055', '0.002041']
turn 3 · 1 tool call(s) · 192.6s turn · 17.7s LLM · tokens in=8,013 · out=1,887 · total=10,196 · 7,276 chars (click to expand)
turn 3192.6s turn · 17.7s LLM · 174.9s tools · tokens in=8,013 · out=1,887 · total=10,196
reasoning
The kernel is incorrect. There are bugs in the CUDA code, especially in the Cholesky inverse part, as the temp and Sigma indexing looks wrong, and the parallelization is only using one thread for many...
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void bayesian_linear_kernel(\n const float* __restrict__ X,\n const float* __restrict__ y,\n const float* __restrict__ X_test,\n float* __restrict__ pred_mean,\n float* __restrict__ pred_var,\n int B, int N, int D, int M,\n float prior_precision, float noise_precision\n) {\n int b = blockIdx.x;\n if (b >= B) return;\n\n extern __shared__ float smem[];\n\n const float* Xb = X + b * N * D;\n const float* yb = y + b * N;\n const float* Xt = X_test + b * M * D;\n\n float* Lambda = smem;\n float* L = smem + D*D;\n float* rhs = smem + 2*D*D;\n float* mu_post = smem + 2*D*D + D;\n float* Sigma = smem + 2*D*D + 2*D;\n float* temp = smem + 3*D*D + 2*D;\n\n // Initialize Lambda = alpha * I\n for (int i = threadIdx.x; i < D*D; i += blockDim.x) {\n int r = i / D, c = i % D;\n Lambda[i] = (r == c) ? prior_precision : 0.0f;\n }\n __syncthreads();\n\n // Compute beta * X^T X and add to Lambda, X^T y\n for (int i = threadIdx.x; i < D; i += blockDim.x) {\n for (int j = 0; j < D; j++) {\n float sum_xx = 0.0f;\n for (int k = 0; k < N; k++) {\n sum_xx += Xb[k*D + i] * Xb[k*D + j];\n }\n Lambda[i*D + j] += noise_precision * sum_xx;\n }\n float sum_xy = 0.0f;\n for (int k = 0; k < N; k++) {\n sum_xy += Xb[k*D + i] * yb[k];\n }\n rhs[i] = noise_precision * sum_xy;\n }\n __syncthreads();\n\n // Cholesky L of Lambda, lower triangular\n for (int i = 0; i < D; ++i) {\n for (int j = threadIdx.x; j <= i; j += blockDim.x) {\n float s = 0.0f;\n for (int k = 0; k < j; ++k) {\n s += L[i*D + k] * L[j*D + k];\n }\n if (i == j) {\n L[i*D + i] = sqrtf(Lambda[i*D + i] - s);\n } else {\n L[i*D + j] = (Lambda[i*D + j] - s) / L[j*D + j];\n }\n }\n __syncthreads();\n }\n\n // Forward substitution L z = rhs -> mu_post temporarily\n for (int i = 0; i < D; ++i) {\n if (threadIdx.x == 0) {\n float s = 0.0f;\n for (int k = 0; k < i; ++k) s += L[i*D + k] * mu_post[k];\n mu_post[i] = (rhs[i] - s) / L[i*D + i];\n }\n __syncthreads();\n }\n // Backward L^T mu = z\n for (int i = D - 1; i >= 0; --i) {\n if (threadIdx.x == 0) {\n float s = 0.0f;\n for (int k = i + 1; k < D; ++k) s += L[k*D + i] * mu_post[k];\n mu_post[i] = (mu_post[i] - s) / L[i*D + i];\n }\n __syncthreads();\n }\n\n // pred_mean = X_test @ mu_post\n for (int m = threadIdx.x; m < M; m += blockDim.x) {\n float sum = 0.0f;\n for (int d = 0; d < D; ++d) {\n sum += Xt[m * D + d] * mu_post[d];\n }\n pred_mean[b * M + m] = sum;\n }\n\n // Compute Sigma = inv(Lambda) via cholesky inverse: solve L Y = I then L^T Sigma = Y\n for (int col = 0; col < D; ++col) {\n // solve L Y_col = e_col\n for (int i = 0; i < D; ++i) {\n if (threadIdx.x == 0) {\n float val = (i == col ? 1.0f : 0.0f);\n for (int k = 0; k < i; ++k) val -= L[i*D + k] * temp[k*D + col];\n temp[i*D + col] = val / L[i*D + i];\n }\n __syncthreads();\n }\n // solve L^T Sigma_col = Y_col\n for (int i = D-1; i >= 0; --i) {\n if (threadIdx.x == 0) {\n float val = temp[i*D + col];\n for (int k = i+1; k < D; ++k) val -= L[k*D + i] * Sigma[k*D + col];\n Sigma[i*D + col] = val / L[i*D + i];\n }\n __syncthreads();\n }\n }\n\n // pred_var = diag(X_test @ Sigma @ X_test^T) + 1/beta\n for (int m = threadIdx.x; m < M; m += blockDim.x) {\n float sum = 0.0f;\n for (int d = 0; d < D; ++d) {\n float tmp = 0.0f;\n for (int e = 0; e < D; ++e) {\n tmp += Xt[m*D + e] * Sigma[e * D + d];\n }\n sum += tmp * Xt[m*D + d];\n }\n pred_var[b * M + m] = sum + 1.0f / noise_precision;\n }\n}\n\nstd::vector<torch::Tensor> bayesian_linear_cuda(\n torch::Tensor X, torch::Tensor y, torch::Tensor X_test,\n float prior_precision, float noise_precision\n) {\n int B = X.size(0);\n int N = X.size(1);\n int D = X.size(2);\n int M = X_test.size(1);\n\n auto options = torch::TensorOptions().dtype(X.dtype()).device(X.device());\n auto pred_mean = torch::zeros({B, M, 1}, options);\n auto pred_var = torch::zeros({B, M}, options);\n\n dim3 grid(B);\n dim3 block(256);\n size_t smem_size = (4 * D * D + 2 * D) * sizeof(float);\n\n bayesian_linear_kernel<<<grid, block, smem_size>>>(\n X.data_ptr<float>(), y.data_ptr<float>(), X_test.data_ptr<float>(),\n pred_mean.data_ptr<float>(), pred_var.data_ptr<float>(),\n B, N, D, M, prior_precision, noise_precision\n );\n\n cudaDeviceSynchronize();\n return {pred_mean.view({B, M, 1}), pred_var};\n}\n'''\n\ncpp_source = '''\nstd::vector<torch::Tensor> bayesian_linear_cuda(\n torch::Tensor X, torch::Tensor y, torch::Tensor X_test,\n float prior_precision, float noise_precision\n);\n'''\n\nmodule = load_inline(\n name='bayesian_linear',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['bayesian_linear_cuda'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, input_dim, prior_precision=1.0, noise_precision=1.0):\n super().__init__()\n self.input_dim = input_dim\n self.prior_precision = prior_precision\n self.noise_precision = noise_precision\n\n def forward(self, X, y, X_test):\n res = module.bayesian_linear_cuda(X, y, X_test, self.prior_precision, self.noise_precision)\n return res[0], res[1]\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 4201.2s turn · 26.3s LLM · 174.9s tools · tokens in=10,213 · out=835 · total=11,054
reasoning
Compiled. Now test correctness.
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void bayesian_linear_kernel(\n const float* __restrict__ X,\n const float* __restrict__ y,\n const float* __restrict__ X_test,\n float* __restrict__ pred_mean,\n float* __restrict__ pred_var,\n int B, int N, int D, int M,\n float prior_precision, float noise_precision\n) {\n int b = blockIdx.x;\n if (b >= B) return;\n\n extern __shared__ float smem[];\n\n const float* Xb = X + b * N * D;\n const float* yb = y + b * N;\n const float* Xt = X_test + b * M * D;\n\n float* Lambda = smem;\n float* L = smem + D*D;\n float* rhs = smem + 2*D*D;\n float* mu_post = smem + 2*D*D + D;\n float* Sigma = smem + 2*D*D + 2*D;\n float* temp = smem + 3*D*D + 2*D;\n\n // Initialize Lambda = alpha * I\n for (int i = threadIdx.x; i < D*D; i += blockDim.x) {\n int r = i / D, c = i % D;\n Lambda[i] = (r == c) ? prior_precision : 0.0f;\n }\n __syncthreads();\n\n // Compute beta * X^T X and add to Lambda, X^T y\n for (int i = threadIdx.x; i < D; i += blockDim.x) {\n for (int j = 0; j < D; j++) {\n float sum_xx = 0.0f;\n for (int k = 0; k < N; k++) {\n sum_xx += Xb[k*D + i] * Xb[k*D + j];\n }\n Lambda[i*D + j] += noise_precision * sum_xx;\n }\n float sum_xy = 0.0f;\n for (int k = 0; k < N; k++) {\n sum_xy += Xb[k*D + i] * yb[k];\n }\n rhs[i] = noise_precision * sum_xy;\n }\n __syncthreads();\n\n // Cholesky L of Lambda, lower triangular\n for (int i = 0; i < D; ++i) {\n for (int j = threadIdx.x; j <= i; j += blockDim.x) {\n float s = 0.0f;\n for (int k = 0; k < j; ++k) {\n s += L[i*D + k] * L[j*D + k];\n }\n if (i == j) {\n L[i*D + i] = sqrtf(Lambda[i*D + i] - s);\n } else {\n L[i*D + j] = (Lambda[i*D + j] - s) / L[j*D + j];\n }\n }\n __syncthreads();\n }\n\n // Forward substitution L z = rhs -> mu_post temporarily\n for (int i = 0; i < D; ++i) {\n if (threadIdx.x == 0) {\n float s = 0.0f;\n for (int k = 0; k < i; ++k) s += L[i*D + k] * mu_post[k];\n mu_post[i] = (rhs[i] - s) / L[i*D + i];\n }\n __syncthreads();\n }\n // Backward L^T mu = z\n for (int i = D - "
}
result ← run_correctness (fail)
failrun_correctness
run_correctness FAILED: kernel did not compile.
Syntax error in custom generated code or ModelNew not found
turn 5 · FINAL · 1 tool call(s) · 285.2s turn · 47.5s LLM · tokens in=11,082 · out=1,887 · total=13,046 · 7,725 chars (click to expand)
turn 5285.2s turn · 47.5s LLM · 237.6s tools · tokens in=11,082 · out=1,887 · total=13,046 · FINAL
reasoning
The kernel_code was truncated in the call because of length. The function response shows it cut off.
call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void bayesian_linear_kernel(\n const float* __restrict__ X,\n const float* __restrict__ y,\n const float* __restrict__ X_test,\n float* __restrict__ pred_mean,\n float* __restrict__ pred_var,\n int B, int N, int D, int M,\n float prior_precision, float noise_precision\n) {\n int b = blockIdx.x;\n if (b >= B) return;\n\n extern __shared__ float smem[];\n\n const float* Xb = X + b * N * D;\n const float* yb = y + b * N;\n const float* Xt = X_test + b * M * D;\n\n float* Lambda = smem;\n float* L = smem + D*D;\n float* rhs = smem + 2*D*D;\n float* mu_post = smem + 2*D*D + D;\n float* Sigma = smem + 2*D*D + 2*D;\n float* temp = smem + 3*D*D + 2*D;\n\n // Initialize Lambda = alpha * I\n for (int i = threadIdx.x; i < D*D; i += blockDim.x) {\n int r = i / D, c = i % D;\n Lambda[i] = (r == c) ? prior_precision : 0.0f;\n }\n __syncthreads();\n\n // Compute beta * X^T X and add to Lambda, X^T y\n for (int i = threadIdx.x; i < D; i += blockDim.x) {\n for (int j = 0; j < D; j++) {\n float sum_xx = 0.0f;\n for (int k = 0; k < N; k++) {\n sum_xx += Xb[k*D + i] * Xb[k*D + j];\n }\n Lambda[i*D + j] += noise_precision * sum_xx;\n }\n float sum_xy = 0.0f;\n for (int k = 0; k < N; k++) {\n sum_xy += Xb[k*D + i] * yb[k];\n }\n rhs[i] = noise_precision * sum_xy;\n }\n __syncthreads();\n\n // Cholesky L of Lambda, lower triangular\n for (int i = 0; i < D; ++i) {\n for (int j = threadIdx.x; j <= i; j += blockDim.x) {\n float s = 0.0f;\n for (int k = 0; k < j; ++k) {\n s += L[i*D + k] * L[j*D + k];\n }\n if (i == j) {\n L[i*D + i] = sqrtf(Lambda[i*D + i] - s);\n } else {\n L[i*D + j] = (Lambda[i*D + j] - s) / L[j*D + j];\n }\n }\n __syncthreads();\n }\n\n // Forward substitution L z = rhs -> mu_post temporarily\n for (int i = 0; i < D; ++i) {\n if (threadIdx.x == 0) {\n float s = 0.0f;\n for (int k = 0; k < i; ++k) s += L[i*D + k] * mu_post[k];\n mu_post[i] = (rhs[i] - s) / L[i*D + i];\n }\n __syncthreads();\n }\n // Backward L^T mu = z\n for (int i = D - 1; i >= 0; --i) {\n if (threadIdx.x == 0) {\n float s = 0.0f;\n for (int k = i + 1; k < D; ++k) s += L[k*D + i] * mu_post[k];\n mu_post[i] = (mu_post[i] - s) / L[i*D + i];\n }\n __syncthreads();\n }\n\n // pred_mean = X_test @ mu_post\n for (int m = threadIdx.x; m < M; m += blockDim.x) {\n float sum = 0.0f;\n for (int d = 0; d < D; ++d) {\n sum += Xt[m * D + d] * mu_post[d];\n }\n pred_mean[b * M + m] = sum;\n }\n\n // Compute Sigma = inv(Lambda) via cholesky inverse: solve L Y = I then L^T Sigma = Y\n for (int col = 0; col < D; ++col) {\n // solve L Y_col = e_col\n for (int i = 0; i < D; ++i) {\n if (threadIdx.x == 0) {\n float val = (i == col ? 1.0f : 0.0f);\n for (int k = 0; k < i; ++k) val -= L[i*D + k] * temp[k*D + col];\n temp[i*D + col] = val / L[i*D + i];\n }\n __syncthreads();\n }\n // solve L^T Sigma_col = Y_col\n for (int i = D-1; i >= 0; --i) {\n if (threadIdx.x == 0) {\n float val = temp[i*D + col];\n for (int k = i+1; k < D; ++k) val -= L[k*D + i] * Sigma[k*D + col];\n Sigma[i*D + col] = val / L[i*D + i];\n }\n __syncthreads();\n }\n }\n\n // pred_var = diag(X_test @ Sigma @ X_test^T) + 1/beta\n for (int m = threadIdx.x; m < M; m += blockDim.x) {\n float sum = 0.0f;\n for (int d = 0; d < D; ++d) {\n float tmp = 0.0f;\n for (int e = 0; e < D; ++e) {\n tmp += Xt[m*D + e] * Sigma[e * D + d];\n }\n sum += tmp * Xt[m*D + d];\n }\n pred_var[b * M + m] = sum + 1.0f / noise_precision;\n }\n}\n\nstd::vector<torch::Tensor> bayesian_linear_cuda(\n torch::Tensor X, torch::Tensor y, torch::Tensor X_test,\n float prior_precision, float noise_precision\n) {\n int B = X.size(0);\n int N = X.size(1);\n int D = X.size(2);\n int M = X_test.size(1);\n\n auto options = torch::TensorOptions().dtype(X.dtype()).device(X.device());\n auto pred_mean = torch::zeros({B, M, 1}, options);\n auto pred_var = torch::zeros({B, M}, options);\n\n dim3 grid(B);\n dim3 block(256);\n size_t smem_size = (4 * D * D + 2 * D) * sizeof(float);\n\n bayesian_linear_kernel<<<grid, block, smem_size>>>(\n X.data_ptr<float>(), y.data_ptr<float>(), X_test.data_ptr<float>(),\n pred_mean.data_ptr<float>(), pred_var.data_ptr<float>(),\n B, N, D, M, prior_precision, noise_precision\n );\n\n cudaDeviceSynchronize();\n return {pred_mean.view({B, M, 1}), pred_var};\n}\n'''\n\ncpp_source = '''\nstd::vector<torch::Tensor> bayesian_linear_cuda(\n torch::Tensor X, torch::Tensor y, torch::Tensor X_test,\n float prior_precision, float noise_precision\n);\n'''\n\nmodule = load_inline(\n name='bayesian_linear',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['bayesian_linear_cuda'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, input_dim, prior_precision=1.0, noise_precision=1.0):\n super().__init__()\n self.input_dim = input_dim\n self.prior_precision = prior_precision\n self.noise_precision = noise_precision\n\n def forward(self, X, y, X_test):\n res = module.bayesian_linear_cuda(X, y, X_test, self.prior_precision, self.noise_precision)\n return res[0], res[1]\n"
}
result ← submit_kernel (fail)
failsubmit_kernel
submit_kernel FAILED: correctness check did not pass ((0 / 5) trials).
correctness_issue: Output mismatch
max_difference: ['0.052969', '0.009739', '0.054024', '0.010747', '0.065366', '0.009737', '0.067590', '0.014611', '0.040142', '0.009076']
avg_difference: ['0.008337', '0.002116', '0.010259', '0.001980', '0.009305', '0.002084', '0.009591', '0.002139', '0.008055', '0.002041']
final submitted kernel (192 lines, 5,946 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline
cuda_source = r'''
#include <torch/extension.h>
#include <cuda.h>
#include <cuda_runtime.h>
__global__ void bayesian_linear_kernel(
const float* __restrict__ X,
const float* __restrict__ y,
const float* __restrict__ X_test,
float* __restrict__ pred_mean,
float* __restrict__ pred_var,
int B, int N, int D, int M,
float prior_precision, float noise_precision
) {
int b = blockIdx.x;
if (b >= B) return;
extern __shared__ float smem[];
const float* Xb = X + b * N * D;
const float* yb = y + b * N;
const float* Xt = X_test + b * M * D;
float* Lambda = smem;
float* L = smem + D*D;
float* rhs = smem + 2*D*D;
float* mu_post = smem + 2*D*D + D;
float* Sigma = smem + 2*D*D + 2*D;
float* temp = smem + 3*D*D + 2*D;
// Initialize Lambda = alpha * I
for (int i = threadIdx.x; i < D*D; i += blockDim.x) {
int r = i / D, c = i % D;
Lambda[i] = (r == c) ? prior_precision : 0.0f;
}
__syncthreads();
// Compute beta * X^T X and add to Lambda, X^T y
for (int i = threadIdx.x; i < D; i += blockDim.x) {
for (int j = 0; j < D; j++) {
float sum_xx = 0.0f;
for (int k = 0; k < N; k++) {
sum_xx += Xb[k*D + i] * Xb[k*D + j];
}
Lambda[i*D + j] += noise_precision * sum_xx;
}
float sum_xy = 0.0f;
for (int k = 0; k < N; k++) {
sum_xy += Xb[k*D + i] * yb[k];
}
rhs[i] = noise_precision * sum_xy;
}
__syncthreads();
// Cholesky L of Lambda, lower triangular
for (int i = 0; i < D; ++i) {
for (int j = threadIdx.x; j <= i; j += blockDim.x) {
float s = 0.0f;
for (int k = 0; k < j; ++k) {
s += L[i*D + k] * L[j*D + k];
}
if (i == j) {
L[i*D + i] = sqrtf(Lambda[i*D + i] - s);
} else {
L[i*D + j] = (Lambda[i*D + j] - s) / L[j*D + j];
}
}
__syncthreads();
}
// Forward substitution L z = rhs -> mu_post temporarily
for (int i = 0; i < D; ++i) {
if (threadIdx.x == 0) {
float s = 0.0f;
for (int k = 0; k < i; ++k) s += L[i*D + k] * mu_post[k];
mu_post[i] = (rhs[i] - s) / L[i*D + i];
}
__syncthreads();
}
// Backward L^T mu = z
for (int i = D - 1; i >= 0; --i) {
if (threadIdx.x == 0) {
float s = 0.0f;
for (int k = i + 1; k < D; ++k) s += L[k*D + i] * mu_post[k];
mu_post[i] = (mu_post[i] - s) / L[i*D + i];
}
__syncthreads();
}
// pred_mean = X_test @ mu_post
for (int m = threadIdx.x; m < M; m += blockDim.x) {
float sum = 0.0f;
for (int d = 0; d < D; ++d) {
sum += Xt[m * D + d] * mu_post[d];
}
pred_mean[b * M + m] = sum;
}
// Compute Sigma = inv(Lambda) via cholesky inverse: solve L Y = I then L^T Sigma = Y
for (int col = 0; col < D; ++col) {
// solve L Y_col = e_col
for (int i = 0; i < D; ++i) {
if (threadIdx.x == 0) {
float val = (i == col ? 1.0f : 0.0f);
for (int k = 0; k < i; ++k) val -= L[i*D + k] * temp[k*D + col];
temp[i*D + col] = val / L[i*D + i];
}
__syncthreads();
}
// solve L^T Sigma_col = Y_col
for (int i = D-1; i >= 0; --i) {
if (threadIdx.x == 0) {
float val = temp[i*D + col];
for (int k = i+1; k < D; ++k) val -= L[k*D + i] * Sigma[k*D + col];
Sigma[i*D + col] = val / L[i*D + i];
}
__syncthreads();
}
}
// pred_var = diag(X_test @ Sigma @ X_test^T) + 1/beta
for (int m = threadIdx.x; m < M; m += blockDim.x) {
float sum = 0.0f;
for (int d = 0; d < D; ++d) {
float tmp = 0.0f;
for (int e = 0; e < D; ++e) {
tmp += Xt[m*D + e] * Sigma[e * D + d];
}
sum += tmp * Xt[m*D + d];
}
pred_var[b * M + m] = sum + 1.0f / noise_precision;
}
}
std::vector<torch::Tensor> bayesian_linear_cuda(
torch::Tensor X, torch::Tensor y, torch::Tensor X_test,
float prior_precision, float noise_precision
) {
int B = X.size(0);
int N = X.size(1);
int D = X.size(2);
int M = X_test.size(1);
auto options = torch::TensorOptions().dtype(X.dtype()).device(X.device());
auto pred_mean = torch::zeros({B, M, 1}, options);
auto pred_var = torch::zeros({B, M}, options);
dim3 grid(B);
dim3 block(256);
size_t smem_size = (4 * D * D + 2 * D) * sizeof(float);
bayesian_linear_kernel<<<grid, block, smem_size>>>(
X.data_ptr<float>(), y.data_ptr<float>(), X_test.data_ptr<float>(),
pred_mean.data_ptr<float>(), pred_var.data_ptr<float>(),
B, N, D, M, prior_precision, noise_precision
);
cudaDeviceSynchronize();
return {pred_mean.view({B, M, 1}), pred_var};
}
'''
cpp_source = '''
std::vector<torch::Tensor> bayesian_linear_cuda(
torch::Tensor X, torch::Tensor y, torch::Tensor X_test,
float prior_precision, float noise_precision
);
'''
module = load_inline(
name='bayesian_linear',
cpp_sources=cpp_source,
cuda_sources=cuda_source,
functions=['bayesian_linear_cuda'],
verbose=False
)
class ModelNew(nn.Module):
def __init__(self, input_dim, prior_precision=1.0, noise_precision=1.0):
super().__init__()
self.input_dim = input_dim
self.prior_precision = prior_precision
self.noise_precision = noise_precision
def forward(self, X, y, X_test):
res = module.bayesian_linear_cuda(X, y, X_test, self.prior_precision, self.noise_precision)
return res[0], res[1]