compile_fail
11_pipeline_three_stage_mlp.py
started
2026-05-11T12:31:32Z
compile error: Syntax error in custom generated code or ModelNew not found
timingkernelbench.timing
kernel mean / median / std
—
reference PyTorch source (the prompt the agent sees)
"""
Three-stage MLP on packed activations: h1 = relu(h0 @ W1), h2 = relu(h1 @ W2), out = h2 @ W3.
Dimensions are fixed; weights are trainable parameters with default init.
"""
import torch
import torch.nn as nn
from kernelbench.distributed_collectives import default_device
B = 16
H0 = 48
H1 = 64
H2 = 40
H3 = 24
class Model(nn.Module):
def __init__(self):
super().__init__()
self.W1 = nn.Linear(H0, H1, bias=False)
self.W2 = nn.Linear(H1, H2, bias=False)
self.W3 = nn.Linear(H2, H3, bias=False)
def forward(self, h0: torch.Tensor) -> torch.Tensor:
h1 = torch.relu(self.W1(h0))
h2 = torch.relu(self.W2(h1))
return self.W3(h2)
def get_inputs():
dev = default_device()
p = popcorn_pri
return [torch.randn(p.jitter_int(B), H0, device=dev)]
def get_init_inputs():
return []
turn 0450.4s turn · 6.4s LLM · 444.0s tools · tokens in=1,498 · out=6 · total=1,684
reasoning
The task is to replace the forward computation of a three-stage MLP with a custom CUDA kernel. The model has three linear layers without bias, with ReLUs in between, and fixed dimensions: B=16, H0=48,...
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 1636.5s turn · 10.9s LLM · 625.6s tools · tokens in=1,917 · out=867 · total=3,159
reasoning
It's an H100, high bandwidth, tensor cores, but since dimensions are tiny (16x48, etc.), probably not using tensor cores, just efficient GEMM on CUDA cores.
I need to replace the forward computation of a PyTorch model with a custom CUDA kernel. The model is called ModelNew and must accept the same inputs as the original Model, implement forward with the same signature, and produce the same numerical outputs.
The original forward is something like: relu(self.
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 = \"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void mlp_kernel(\n const float* __restrict__ h0,\n const float* __restrict__ W1,\n const float* __restrict__ W2,\n const float* __restrict__ W3,\n float* __restrict__ out,\n int B, int H0, int H1, int H2, int H3\n) {\n int row = blockIdx.x * blockDim.x + threadIdx.x;\n if (row >= B) return;\n\n // Compute h1 = relu(h0[row] @ W1.T)\n extern __shared__ float smem[];\n float* h1 = smem;\n float* h2 = h1 + H1;\n\n for (int j = 0; j < H1; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H0; ++k) {\n sum += h0[row * H0 + k] * W1[j * H0 + k];\n }\n h1[j] = fmaxf(sum, 0.0f);\n }\n\n // h2 = relu(h1 @ W2.T)\n for (int j = 0; j < H2; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H1; ++k) {\n sum += h1[k] * W2[j * H1 + k];\n }\n h2[j] = fmaxf(sum, 0.0f);\n }\n\n // out = h2 @ W3.T\n for (int j = 0; j < H3; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H2; ++k) {\n sum += h2[k] * W3[j * H2 + k];\n }\n out[row * H3 + j] = sum;\n }\n}\n\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3) {\n int B = h0.size(0);\n int H0 = h0.size(1);\n int H1 = W1.size(0);\n int H2 = W2.size(0);\n int H3 = W3.size(0);\n\n auto out = torch::zeros({B, H3}, h0.options());\n\n int threads = 256;\n int blocks = (B + threads - 1) / threads;\n size_t smem_size = (H1 + H2) * sizeof(float);\n\n mlp_kernel<<<blocks, threads, smem_size>>>(\n h0.data_ptr<float>(),\n W1.data_ptr<float>(),\n W2.data_ptr<float>(),\n W3.data_ptr<float>(),\n out.data_ptr<float>(),\n B, H0, H1, H2, H3\n );\n\n return out;\n}\n\"\"\"\n\ncpp_source = \"\"\"\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3);\n\"\"\"\n\nmodule = load_inline(\n name='mlp_cuda',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['mlp_forward'],\n verbose=True\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.W1 = nn.Linear(48, 64, bias=False)\n self.W2 = nn.Linear(64, 40, bias=False)\n self.W3 = nn.Linear(40, 24, bias=False)\n\n def forward(self, h0: torch.Tensor) -> torch.Tensor:\n return module.mlp_forward(h0, self.W1.weight, self.W2.weight, self.W3.weight)\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 2381.2s turn · 9.4s LLM · 371.8s tools · tokens in=3,176 · out=868 · total=4,051
reasoning
Compiled successfully. Now check 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 = \"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void mlp_kernel(\n const float* __restrict__ h0,\n const float* __restrict__ W1,\n const float* __restrict__ W2,\n const float* __restrict__ W3,\n float* __restrict__ out,\n int B, int H0, int H1, int H2, int H3\n) {\n int row = blockIdx.x * blockDim.x + threadIdx.x;\n if (row >= B) return;\n\n // Compute h1 = relu(h0[row] @ W1.T)\n extern __shared__ float smem[];\n float* h1 = smem;\n float* h2 = h1 + H1;\n\n for (int j = 0; j < H1; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H0; ++k) {\n sum += h0[row * H0 + k] * W1[j * H0 + k];\n }\n h1[j] = fmaxf(sum, 0.0f);\n }\n\n // h2 = relu(h1 @ W2.T)\n for (int j = 0; j < H2; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H1; ++k) {\n sum += h1[k] * W2[j * H1 + k];\n }\n h2[j] = fmaxf(sum, 0.0f);\n }\n\n // out = h2 @ W3.T\n for (int j = 0; j < H3; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H2; ++k) {\n sum += h2[k] * W3[j * H2 + k];\n }\n out[row * H3 + j] = sum;\n }\n}\n\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3) {\n int B = h0.size(0);\n int H0 = h0.size(1);\n int H1 = W1.size(0);\n int H2 = W2.size(0);\n int H3 = W3.size(0);\n\n auto out = torch::zeros({B, H3}, h0.options());\n\n int threads = 256;\n int blocks = (B + threads - 1) / threads;\n size_t smem_size = (H1 + H2) * sizeof(float);\n\n mlp_kernel<<<blocks, threads, smem_size>>>(\n h0.data_ptr<float>(),\n W1.data_ptr<float>(),\n W2.data_ptr<float>(),\n W3.data_ptr<float>(),\n out.data_ptr<float>(),\n B, H0, H1, H2, H3\n );\n\n return out;\n}\n\"\"\"\n\ncpp_source = \"\"\"\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3);\n\"\"\"\n\nmodule = load_inline(\n name='mlp_cuda',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['mlp_forward'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.W1 = nn.Linear(48, 64, bias=False)\n self.W2 = nn.Linear(64, 40, bias=False)\n self.W3 = nn.Linear(40, 24, bias=False)\n\n def forward(self, h0: torch.Tensor) -> torch.Tensor:\n return module.mlp_forward(h0, self.W1.weight, self.W2.weight, self.W3.weight)\n"
}
result ← run_correctness (fail)
failrun_correctness
run_correctness FAILED: (0 / 5) trials did not all match.
correctness_issue: Output mismatch
max_difference: ['0.207420', '0.207420', '0.207420', '0.207420', '0.207420']
avg_difference: ['0.054256', '0.054256', '0.054256', '0.054256', '0.054256']
turn 3477.7s turn · 22.1s LLM · 455.7s tools · tokens in=4,148 · out=789 · total=5,332
reasoning
There's a mismatch. Probably because the kernel uses W1[j * H0 + k] which assumes row-major as (out, in), yes that's correct for nn.Linear.weight.
The thinking trace reveals a critical bug in the proposed CUDA kernel for replacing the PyTorch model's forward pass. The issue stems from the shared memory being used incorrectly.
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 = \"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void mlp_kernel(\n const float* __restrict__ h0,\n const float* __restrict__ W1,\n const float* __restrict__ W2,\n const float* __restrict__ W3,\n float* __restrict__ out,\n int B, int H0, int H1, int H2, int H3\n) {\n int row = blockIdx.x * blockDim.x + threadIdx.x;\n if (row >= B) return;\n\n float h1[64];\n float h2[40];\n\n for (int j = 0; j < H1; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H0; ++k) {\n sum += h0[row * H0 + k] * W1[j * H0 + k];\n }\n h1[j] = fmaxf(sum, 0.0f);\n }\n\n for (int j = 0; j < H2; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H1; ++k) {\n sum += h1[k] * W2[j * H1 + k];\n }\n h2[j] = fmaxf(sum, 0.0f);\n }\n\n for (int j = 0; j < H3; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H2; ++k) {\n sum += h2[k] * W3[j * H2 + k];\n }\n out[row * H3 + j] = sum;\n }\n}\n\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3) {\n int B = h0.size(0);\n int H0 = h0.size(1);\n int H1 = W1.size(0);\n int H2 = W2.size(0);\n int H3 = W3.size(0);\n\n auto out = torch::zeros({B, H3}, h0.options());\n\n int threads = 256;\n int blocks = (B + threads - 1) / threads;\n\n mlp_kernel<<<blocks, threads>>>(\n h0.data_ptr<float>(),\n W1.data_ptr<float>(),\n W2.data_ptr<float>(),\n W3.data_ptr<float>(),\n out.data_ptr<float>(),\n B, H0, H1, H2, H3\n );\n\n return out;\n}\n\"\"\"\n\ncpp_source = \"\"\"\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3);\n\"\"\"\n\nmodule = load_inline(\n name='mlp_cuda',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['mlp_forward'],\n verbose=True\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.W1 = nn.Linear(48, 64, bias=False)\n self.W2 = nn.Linear(64, 40, bias=False)\n self.W3 = nn.Linear(40, 24, bias=False)\n\n def forward(self, h0: torch.Tensor) -> torch.Tensor:\n return module.mlp_forward(h0, self.W1.weight, self.W2.weight, self.W3.weight)\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 4396.9s turn · 17.6s LLM · 379.3s tools · tokens in=5,349 · out=792 · total=6,145
reasoning
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 = \"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void mlp_kernel(\n const float* __restrict__ h0,\n const float* __restrict__ W1,\n const float* __restrict__ W2,\n const float* __restrict__ W3,\n float* __restrict__ out,\n int B, int H0, int H1, int H2, int H3\n) {\n int row = blockIdx.x * blockDim.x + threadIdx.x;\n if (row >= B) return;\n\n float h1[64];\n float h2[40];\n\n for (int j = 0; j < H1; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H0; ++k) {\n sum += h0[row * H0 + k] * W1[j * H0 + k];\n }\n h1[j] = fmaxf(sum, 0.0f);\n }\n\n for (int j = 0; j < H2; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H1; ++k) {\n sum += h1[k] * W2[j * H1 + k];\n }\n h2[j] = fmaxf(sum, 0.0f);\n }\n\n for (int j = 0; j < H3; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H2; ++k) {\n sum += h2[k] * W3[j * H2 + k];\n }\n out[row * H3 + j] = sum;\n }\n}\n\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3) {\n int B = h0.size(0);\n int H0 = h0.size(1);\n int H1 = W1.size(0);\n int H2 = W2.size(0);\n int H3 = W3.size(0);\n\n auto out = torch::zeros({B, H3}, h0.options());\n\n int threads = 256;\n int blocks = (B + threads - 1) / threads;\n\n mlp_kernel<<<blocks, threads>>>(\n h0.data_ptr<float>(),\n W1.data_ptr<float>(),\n W2.data_ptr<float>(),\n W3.data_ptr<float>(),\n out.data_ptr<float>(),\n B, H0, H1, H2, H3\n );\n\n return out;\n}\n\"\"\"\n\ncpp_source = \"\"\"\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3);\n\"\"\"\n\nmodule = load_inline(\n name='mlp_cuda',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['mlp_forward'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.W1 = nn.Linear(48, 64, bias=False);\n self.W2 = nn.Linear(64, 40, bias=False);\n self.W3 = nn.Linear(40, 24, bias=False);\n\n def forward(self, h0: torch.Tensor) -> torch.Tensor {\n return module.mlp_forward(h0, self.W1.weight, self.W2.weight, self.W3.weight);\n }\n"
}
result ← run_correctness (fail)
failrun_correctness
run_correctness FAILED: kernel did not compile.
Syntax error in custom generated code or ModelNew not found
turn 5284.3s turn · 6.0s LLM · 278.2s tools · tokens in=6,173 · out=790 · total=7,024
reasoning
Oops, syntax error because I put ; in class definition in the test code. Need to fix for submission, but in actual it's python.
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 = \"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void mlp_kernel(\n const float* __restrict__ h0,\n const float* __restrict__ W1,\n const float* __restrict__ W2,\n const float* __restrict__ W3,\n float* __restrict__ out,\n int B, int H0, int H1, int H2, int H3\n) {\n int row = blockIdx.x * blockDim.x + threadIdx.x;\n if (row >= B) return;\n\n float h1[64];\n float h2[40];\n\n for (int j = 0; j < H1; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H0; ++k) {\n sum += h0[row * H0 + k] * W1[j * H0 + k];\n }\n h1[j] = fmaxf(sum, 0.0f);\n }\n\n for (int j = 0; j < H2; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H1; ++k) {\n sum += h1[k] * W2[j * H1 + k];\n }\n h2[j] = fmaxf(sum, 0.0f);\n }\n\n for (int j = 0; j < H3; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H2; ++k) {\n sum += h2[k] * W3[j * H2 + k];\n }\n out[row * H3 + j] = sum;\n }\n}\n\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3) {\n int B = h0.size(0);\n int H0 = h0.size(1);\n int H1 = W1.size(0);\n int H2 = W2.size(0);\n int H3 = W3.size(0);\n\n auto out = torch::zeros({B, H3}, h0.options());\n\n int threads = 256;\n int blocks = (B + threads - 1) / threads;\n\n mlp_kernel<<<blocks, threads>>>(\n h0.data_ptr<float>(),\n W1.data_ptr<float>(),\n W2.data_ptr<float>(),\n W3.data_ptr<float>(),\n out.data_ptr<float>(),\n B, H0, H1, H2, H3\n );\n\n return out;\n}\n\"\"\"\n\ncpp_source = \"\"\"\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3);\n\"\"\"\n\nmodule = load_inline(\n name='mlp_cuda',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['mlp_forward'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.W1 = nn.Linear(48, 64, bias=False)\n self.W2 = nn.Linear(64, 40, bias=False)\n self.W3 = nn.Linear(40, 24, bias=False)\n\n def forward(self, h0: torch.Tensor) -> torch.Tensor:\n return module.mlp_forward(h0, self.W1.weight, self.W2.weight, self.W3.weight)\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=7.45e-08 mean_abs_err=1.56e-08 max_rel_err=1.76e-05
turn 66.9s turn · 6.9s LLM · 0.0s tools · tokens in=7,084 · out=789 · total=7,898
reasoning
Great, correct now. Since it's faster likely due to fusion, no multiple launches, and small sizes.
call → static_check
callstatic_check
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = \"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void mlp_kernel(\n const float* __restrict__ h0,\n const float* __restrict__ W1,\n const float* __restrict__ W2,\n const float* __restrict__ W3,\n float* __restrict__ out,\n int B, int H0, int H1, int H2, int H3\n) {\n int row = blockIdx.x * blockDim.x + threadIdx.x;\n if (row >= B) return;\n\n float h1[64];\n float h2[40];\n\n for (int j = 0; j < H1; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H0; ++k) {\n sum += h0[row * H0 + k] * W1[j * H0 + k];\n }\n h1[j] = fmaxf(sum, 0.0f);\n }\n\n for (int j = 0; j < H2; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H1; ++k) {\n sum += h1[k] * W2[j * H1 + k];\n }\n h2[j] = fmaxf(sum, 0.0f);\n }\n\n for (int j = 0; j < H3; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H2; ++k) {\n sum += h2[k] * W3[j * H2 + k];\n }\n out[row * H3 + j] = sum;\n }\n}\n\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3) {\n int B = h0.size(0);\n int H0 = h0.size(1);\n int H1 = W1.size(0);\n int H2 = W2.size(0);\n int H3 = W3.size(0);\n\n auto out = torch::zeros({B, H3}, h0.options());\n\n int threads = 256;\n int blocks = (B + threads - 1) / threads;\n\n mlp_kernel<<<blocks, threads>>>(\n h0.data_ptr<float>(),\n W1.data_ptr<float>(),\n W2.data_ptr<float>(),\n W3.data_ptr<float>(),\n out.data_ptr<float>(),\n B, H0, H1, H2, H3\n );\n\n return out;\n}\n\"\"\"\n\ncpp_source = \"\"\"\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3);\n\"\"\"\n\nmodule = load_inline(\n name='mlp_cuda',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['mlp_forward'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.W1 = nn.Linear(48, 64, bias=False)\n self.W2 = nn.Linear(64, 40, bias=False)\n self.W3 = nn.Linear(40, 24, bias=False)\n\n def forward(self, h0: torch.Tensor) -> torch.Tensor:\n return module.mlp_forward(h0, self.W1.weight, self.W2.weight, self.W3.weight)\n"
}
result ← static_check (ok)
okstatic_check
static_check PASSED: no violations or warnings detected.
turn 7204.8s turn · 9.2s LLM · 195.6s tools · tokens in=7,916 · out=790 · total=8,710 · FINAL
reasoning
Good, submit.
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 = \"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void mlp_kernel(\n const float* __restrict__ h0,\n const float* __restrict__ W1,\n const float* __restrict__ W2,\n const float* __restrict__ W3,\n float* __restrict__ out,\n int B, int H0, int H1, int H2, int H3\n) {\n int row = blockIdx.x * blockDim.x + threadIdx.x;\n if (row >= B) return;\n\n float h1[64];\n float h2[40];\n\n for (int j = 0; j < H1; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H0; ++k) {\n sum += h0[row * H0 + k] * W1[j * H0 + k];\n }\n h1[j] = fmaxf(sum, 0.0f);\n }\n\n for (int j = 0; j < H2; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H1; ++k) {\n sum += h1[k] * W2[j * H1 + k];\n }\n h2[j] = fmaxf(sum, 0.0f);\n }\n\n for (int j = 0; j < H3; ++j) {\n float sum = 0.0f;\n for (int k = 0; k < H2; ++k) {\n sum += h2[k] * W3[j * H2 + k];\n }\n out[row * H3 + j] = sum;\n }\n}\n\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3) {\n int B = h0.size(0);\n int H0 = h0.size(1);\n int H1 = W1.size(0);\n int H2 = W2.size(0);\n int H3 = W3.size(0);\n\n auto out = torch::zeros({B, H3}, h0.options());\n\n int threads = 256;\n int blocks = (B + threads - 1) / threads;\n\n mlp_kernel<<<blocks, threads>>>(\n h0.data_ptr<float>(),\n W1.data_ptr<float>(),\n W2.data_ptr<float>(),\n W3.data_ptr<float>(),\n out.data_ptr<float>(),\n B, H0, H1, H2, H3\n );\n\n return out;\n}\n\"\"\"\n\ncpp_source = \"\"\"\ntorch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3);\n\"\"\"\n\nmodule = load_inline(\n name='mlp_cuda',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['mlp_forward'],\n verbose=False\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.W1 = nn.Linear(48, 64, bias=False)\n self.W2 = nn.Linear(64, 40, bias=False)\n self.W3 = nn.Linear(40, 24, bias=False)\n\n def forward(self, h0: torch.Tensor) -> torch.Tensor:\n return module.mlp_forward(h0, self.W1.weight, self.W2.weight, self.W3.weight)\n```"
}
result ← submit_kernel (fail)
failsubmit_kernel
submit_kernel FAILED: kernel did not compile.
Syntax error in custom generated code or ModelNew not found
final submitted kernel (95 lines, 2,364 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline
cuda_source = """
#include <torch/extension.h>
#include <cuda.h>
#include <cuda_runtime.h>
__global__ void mlp_kernel(
const float* __restrict__ h0,
const float* __restrict__ W1,
const float* __restrict__ W2,
const float* __restrict__ W3,
float* __restrict__ out,
int B, int H0, int H1, int H2, int H3
) {
int row = blockIdx.x * blockDim.x + threadIdx.x;
if (row >= B) return;
float h1[64];
float h2[40];
for (int j = 0; j < H1; ++j) {
float sum = 0.0f;
for (int k = 0; k < H0; ++k) {
sum += h0[row * H0 + k] * W1[j * H0 + k];
}
h1[j] = fmaxf(sum, 0.0f);
}
for (int j = 0; j < H2; ++j) {
float sum = 0.0f;
for (int k = 0; k < H1; ++k) {
sum += h1[k] * W2[j * H1 + k];
}
h2[j] = fmaxf(sum, 0.0f);
}
for (int j = 0; j < H3; ++j) {
float sum = 0.0f;
for (int k = 0; k < H2; ++k) {
sum += h2[k] * W3[j * H2 + k];
}
out[row * H3 + j] = sum;
}
}
torch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3) {
int B = h0.size(0);
int H0 = h0.size(1);
int H1 = W1.size(0);
int H2 = W2.size(0);
int H3 = W3.size(0);
auto out = torch::zeros({B, H3}, h0.options());
int threads = 256;
int blocks = (B + threads - 1) / threads;
mlp_kernel<<<blocks, threads>>>(
h0.data_ptr<float>(),
W1.data_ptr<float>(),
W2.data_ptr<float>(),
W3.data_ptr<float>(),
out.data_ptr<float>(),
B, H0, H1, H2, H3
);
return out;
}
"""
cpp_source = """
torch::Tensor mlp_forward(torch::Tensor h0, torch::Tensor W1, torch::Tensor W2, torch::Tensor W3);
"""
module = load_inline(
name='mlp_cuda',
cpp_sources=cpp_source,
cuda_sources=cuda_source,
functions=['mlp_forward'],
verbose=False
)
class ModelNew(nn.Module):
def __init__(self):
super().__init__()
self.W1 = nn.Linear(48, 64, bias=False)
self.W2 = nn.Linear(64, 40, bias=False)
self.W3 = nn.Linear(40, 24, bias=False)
def forward(self, h0: torch.Tensor) -> torch.Tensor:
return module.mlp_forward(h0, self.W1.weight, self.W2.weight, self.W3.weight)
```