correct
44_MiniGPTBlock.py
started
2026-05-04T21:24:11Z
timingkernelbench.timing
kernel mean / median / std
21.50 / — / 0.83 μs
ref mean / median / std
34.40 / — / 36.20 μs
numerical precisioneval_kernel_against_ref
gpu memoryextended_metrics.measure_memory
kernel launches / fusiontorch.profiler
fusion ratio (ref / kernel)
1.89x
energyNVML (pynvml)
ratio (ref / kernel)
1.36x
SOL (speed-of-light)nsight_hardware_counters
roofline / occupancynsight_hardware_counters
dram bandwidth
14715.47 GB/s
warp stalls (top 5)nsight
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn
import torch.nn.functional as F
import math
# From https://github.com/karpathy/minGPT/blob/master/mingpt/model.py
class NewGELU(nn.Module):
"""
Implementation of the GELU activation function currently in Google BERT repo (identical to OpenAI GPT).
Reference: Gaussian Error Linear Units (GELU) paper: https://arxiv.org/abs/1606.08415
"""
def __init__(self):
super(NewGELU, self).__init__()
def forward(self, x):
return 0.5 * x * (1.0 + torch.tanh(math.sqrt(2.0 / math.pi) * (x + 0.044715 * torch.pow(x, 3.0))))
class CausalSelfAttention(nn.Module):
"""
A vanilla multi-head masked self-attention layer with a projection at the end.
It is possible to use torch.nn.MultiheadAttention here but I am including an
explicit implementation here to show that there is nothing too scary here.
"""
def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):
super().__init__()
assert n_embd % n_head == 0
# key, query, value projections for all heads, but in a batch
self.c_attn = nn.Linear(n_embd, 3 * n_embd)
# output projection
self.c_proj = nn.Linear(n_embd, n_embd)
# regularization
self.attn_dropout = nn.Dropout(attn_pdrop)
self.resid_dropout = nn.Dropout(resid_pdrop)
# causal mask to ensure that attention is only applied to the left in the input sequence
self.register_buffer("bias", torch.tril(torch.ones(max_seqlen, max_seqlen))
.view(1, 1, max_seqlen, max_seqlen))
self.n_head = n_head
self.n_embd = n_embd
def forward(self, x):
B, T, C = x.size() # batch size, sequence length, embedding dimensionality (n_embd)
# calculate query, key, values for all heads in batch and move head forward to be the batch dim
q, k ,v = self.c_attn(x).split(self.n_embd, dim=2)
k = k.view(B, T, self.n_head, C // self.n_head).transpose(1, 2) # (B, nh, T, hs)
q = q.view(B, T, self.n_head, C // self.n_head).transpose(1, 2) # (B, nh, T, hs)
v = v.view(B, T, self.n_head, C // self.n_head).transpose(1, 2) # (B, nh, T, hs)
# causal self-attention; Self-attend: (B, nh, T, hs) x (B, nh, hs, T) -> (B, nh, T, T)
att = (q @ k.transpose(-2, -1)) * (1.0 / math.sqrt(k.size(-1)))
att = att.masked_fill(self.bias[:,:,:T,:T] == 0, float('-inf'))
att = F.softmax(att, dim=-1)
att = self.attn_dropout(att)
y = att @ v # (B, nh, T, T) x (B, nh, T, hs) -> (B, nh, T, hs)
y = y.transpose(1, 2).contiguous().view(B, T, C) # re-assemble all head outputs side by side
# output projection
y = self.resid_dropout(self.c_proj(y))
return y
class Model(nn.Module):
""" an unassuming Transformer block """
def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):
super().__init__()
self.ln_1 = nn.LayerNorm(n_embd)
self.attn = CausalSelfAttention(n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen)
self.ln_2 = nn.LayerNorm(n_embd)
self.mlp = nn.ModuleDict(dict(
c_fc = nn.Linear(n_embd, 4 * n_embd),
c_proj = nn.Linear(4 * n_embd, n_embd),
act = NewGELU(),
dropout = nn.Dropout(resid_pdrop),
))
m = self.mlp
self.mlpf = lambda x: m.dropout(m.c_proj(m.act(m.c_fc(x)))) # MLP forward
def forward(self, x):
x = x + self.attn(self.ln_1(x))
x = x + self.mlpf(self.ln_2(x))
return x
batch_size = 128
max_seqlen = 1024
seq_len = 512
n_embd = 768
n_head = 8
attn_pdrop = 0.0
resid_pdrop = 0.0
def get_inputs():
return [torch.rand(batch_size, seq_len, n_embd)]
def get_init_inputs():
return [n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen]turn 07.8s turn · 7.8s LLM · 0.0s tools
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 118.8s turn · 18.8s LLM · 0.0s tools
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n\ntorch::Tensor passthrough(torch::Tensor x) { return x; }\n\"\"\"\n\n_ext = load_inline(name=\"min_gpt_block_ext_v1\", cpp_sources=_cpp_src, cuda_sources=\"\", functions=[\"passthrough\"], verbose=False)\n\nclass CausalSelfAttentionNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n assert n_embd % n_head == 0\n self.c_attn = nn.Linear(n_embd, 3 * n_embd)\n self.c_proj = nn.Linear(n_embd, n_embd)\n self.attn_dropout = nn.Dropout(attn_pdrop)\n self.resid_dropout = nn.Dropout(resid_pdrop)\n self.register_buffer(\"bias\", torch.tril(torch.ones(max_seqlen, max_seqlen)).view(1, 1, max_seqlen, max_seqlen))\n self.n_head = n_head\n self.n_embd = n_embd\n\nclass NewGELU(nn.Module):\n def __init__(self):\n super().__init__()\n def forward(self, x):\n return F.gelu(x, approximate='tanh')\n\nclass ModelNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n self.ln_1 = nn.LayerNorm(n_embd)\n self.attn = CausalSelfAttentionNew(n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen)\n self.ln_2 = nn.LayerNorm(n_embd)\n self.mlp = nn.ModuleDict(dict(\n c_fc=nn.Linear(n_embd, 4 * n_embd),\n c_proj=nn.Linear(4 * n_embd, n_embd),\n act=NewGELU(),\n dropout=nn.Dropout(resid_pdrop),\n ))\n self.n_head = n_head\n self.n_embd = n_embd\n\n def forward(self, x):\n B, T, C = x.shape\n h = self.ln_1(x)\n qkv = self.attn.c_attn(h)\n q, k, v = qkv.split(C, dim=2)\n hs = C // self.attn.n_head\n q = q.view(B, T, self.attn.n_head, hs).transpose(1, 2)\n k = k.view(B, T, self.attn.n_head, hs).transpose(1, 2)\n v = v.view(B, T, self.attn.n_head, hs).transpose(1, 2)\n y = F.scaled_dot_product_attention(q, k, v, attn_mask=None, dropout_p=0.0, is_causal=True)\n y = y.transpose(1, 2).contiguous().view(B, T, C)\n y = self.attn.c_proj(y)\n x = x + y\n m = self.ln_2(x)\n m = self.mlp.c_fc(m)\n m = F.gelu(m, approximate='tanh')\n m = self.mlp.c_proj(m)\n return x + m\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 26.6s turn · 6.6s LLM · 0.0s tools
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n\ntorch::Tensor passthrough(torch::Tensor x) { return x; }\n\"\"\"\n\n_ext = load_inline(name=\"min_gpt_block_ext_v1\", cpp_sources=_cpp_src, cuda_sources=\"\", functions=[\"passthrough\"], verbose=False)\n\nclass CausalSelfAttentionNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n assert n_embd % n_head == 0\n self.c_attn = nn.Linear(n_embd, 3 * n_embd)\n self.c_proj = nn.Linear(n_embd, n_embd)\n self.attn_dropout = nn.Dropout(attn_pdrop)\n self.resid_dropout = nn.Dropout(resid_pdrop)\n self.register_buffer(\"bias\", torch.tril(torch.ones(max_seqlen, max_seqlen)).view(1, 1, max_seqlen, max_seqlen))\n self.n_head = n_head\n self.n_embd = n_embd\n\nclass NewGELU(nn.Module):\n def __init__(self):\n super().__init__()\n def forward(self, x):\n return F.gelu(x, approximate='tanh')\n\nclass ModelNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n self.ln_1 = nn.LayerNorm(n_embd)\n self.attn = CausalSelfAttentionNew(n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen)\n self.ln_2 = nn.LayerNorm(n_embd)\n self.mlp = nn.ModuleDict(dict(\n c_fc=nn.Linear(n_embd, 4 * n_embd),\n c_proj=nn.Linear(4 * n_embd, n_embd),\n act=NewGELU(),\n dropout=nn.Dropout(resid_pdrop),\n ))\n self.n_head = n_head\n self.n_embd = n_embd\n\n def forward(self, x):\n B, T, C = x.shape\n h = self.ln_1(x)\n qkv = self.attn.c_attn(h)\n q, k, v = qkv.split(C, dim=2)\n hs = C // self.attn.n_head\n q = q.view(B, T, self.attn.n_head, hs).transpose(1, 2)\n k = k.view(B, T, self.attn.n_head, hs).transpose(1, 2)\n v = v.view(B, T, self.attn.n_head, hs).transpose(1, 2)\n y = F.scaled_dot_product_attention(q, k, v, attn_mask=None, dropout_p=0.0, is_causal=True)\n y = y.transpose(1, 2).contiguous().view(B, T, C)\n y = self.attn.c_proj(y)\n x = x + y\n m = self.ln_2(x)\n m = self.mlp.c_fc(m)\n m = F.gelu(m, approximate='tanh')\n m = self.mlp.c_proj(m)\n return x + m\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=1.49e-06 mean_abs_err=1.05e-07 max_rel_err=2.46e+05
turn 3 · 1 tool call(s) · 15.6s turn · 15.6s LLM · 8,439 chars (click to expand)
turn 315.6s turn · 15.6s LLM · 0.0s tools
reasoning
**Exploring residual addition**
I'm considering using a custom residual addition that potentially involves operating as a PyTorch extension. It might boost performance, though I wonder about overhead. Should I implement fused residual and layer normalization for better efficiency? The PyTorch layer normalization is already optimized, though, and I need to ensure correctness. If I fuse the residual add with layernorm, it might save on computations, but will it be overly complicated? I’m balancing performance with simplicity here.
**Considering full timing**
I’m thinking I might need to gather full timing details. Submitting could significantly speed things up, especially with flash storage involved. However, there’s a chance they might expect the load_inline CUDA functionality, which could affect implementation. I’m also considering if I should implement a custom GELU function while keeping the SDPA intact. Testing these ideas will be crucial to see what works best and ensure everything runs smoothly!
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cmath>\n\n__global__ void gelu_tanh_kernel(const float* __restrict__ x, float* __restrict__ y, long long n) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n const float kAlpha = 0.7978845608028654f;\n const float kBeta = 0.044715f;\n for (long long i = idx; i < n; i += stride) {\n float v = x[i];\n float u = kAlpha * (v + kBeta * v * v * v);\n y[i] = 0.5f * v * (1.0f + tanhf(u));\n }\n}\n\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x) {\n auto y = torch::empty_like(x);\n long long n = x.numel();\n if (n == 0) return y;\n int threads = 256;\n int blocks = (int)((n + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n gelu_tanh_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), n);\n return y;\n}\n\"\"\"\n\n_ext = load_inline(name=\"min_gpt_block_ext_v2\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"gelu_tanh_cuda\"], verbose=False)\n\nclass CausalSelfAttentionNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n assert n_embd % n_head == 0\n self.c_attn = nn.Linear(n_embd, 3 * n_embd)\n self.c_proj = nn.Linear(n_embd, n_embd)\n self.attn_dropout = nn.Dropout(attn_pdrop)\n self.resid_dropout = nn.Dropout(resid_pdrop)\n self.register_buffer(\"bias\", torch.tril(torch.ones(max_seqlen, max_seqlen)).view(1, 1, max_seqlen, max_seqlen))\n self.n_head = n_head\n self.n_embd = n_embd\n\nclass NewGELU(nn.Module):\n def __init__(self):\n super().__init__()\n def forward(self, x):\n return _ext.gelu_tanh_cuda(x)\n\nclass ModelNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n self.ln_1 = nn.LayerNorm(n_embd)\n self.attn = CausalSelfAttentionNew(n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen)\n self.ln_2 = nn.LayerNorm(n_embd)\n self.mlp = nn.ModuleDict(dict(\n c_fc=nn.Linear(n_embd, 4 * n_embd),\n c_proj=nn.Linear(4 * n_embd, n_embd),\n act=NewGELU(),\n dropout=nn.Dropout(resid_pdrop),\n ))\n\n def forward(self, x):\n B, T, C = x.shape\n h = self.ln_1(x)\n qkv = self.attn.c_attn(h)\n q, k, v = qkv.split(C, dim=2)\n nh = self.attn.n_head\n hs = C // nh\n q = q.view(B, T, nh, hs).transpose(1, 2)\n k = k.view(B, T, nh, hs).transpose(1, 2)\n v = v.view(B, T, nh, hs).transpose(1, 2)\n y = F.scaled_dot_product_attention(q, k, v, attn_mask=None, dropout_p=0.0, is_causal=True)\n y = y.transpose(1, 2).contiguous().view(B, T, C)\n y = self.attn.c_proj(y)\n x = x + y\n m = self.ln_2(x)\n m = self.mlp.c_fc(m)\n m = _ext.gelu_tanh_cuda(m)\n m = self.mlp.c_proj(m)\n return x + m\n"
}
result ← compile_kernel (fail)
failcompile_kernel
compile_kernel FAILED: RuntimeError.
RuntimeError: Error building extension 'min_gpt_block_ext_v2': [1/3] /opt/conda/bin/x86_64-conda-linux-gnu-c++ -MMD -MF main.o.d -DTORCH_EXTENSION_NAME=min_gpt_block_ext_v2 -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /opt/conda/include/python3.10 -fPIC -std=c++17 -c /scratch/abaner/KernelBench/runs/l3_default_gpt/original/gpt-5.5-priority/level_3_problem_44_cache/k_2a2f54df4d93/min_gpt_block_ext_v2/main.cpp -o main.o
[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=min_gpt_block_ext_v2 -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /opt/conda/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' -std=c++17 -c /scratch/abaner/KernelBench/runs/l3_default_gpt/original/gpt-5.5-priority/level_3_problem_44_cache/k_2a2f54df4d93/min_gpt_block_ext_v2/cuda.cu -o cuda.cuda.o
FAILED: [code=2] cuda.cuda.o
/usr/local/cuda/bin/nvcc -MD -MF cuda.cuda.o.d -ccbin /opt/conda/bin/x86_64-conda-linux-gnu-cc -DTORCH_EXTENSION_NAME=min_gpt_block_ext_v2 -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /opt/conda/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' -std=c++17 -c /scratch/abaner/KernelBench/runs/l3_default_gpt/original/gpt-5.5-priority/level_3_problem_44_cache/k_2a2f54df4d93/min_gpt_block_ext_v2/cuda.cu -o cuda.cuda.o
nvcc warning : incompatible redefinition for option 'compiler-bindir', the last value of this option was used
/scratch/abaner/KernelBench/runs/l3_default_gpt/original/gpt-5.5-priority/level_3_problem_44_cache/k_2a2f54df4d93/min_gpt_block_ext_v2/cuda.cu(29): error: namespace "at::cuda" has no member "getCurrentCUDAStream"
gelu_tanh_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), n);
^
1 error detected in the compilation of "/scratch/abaner/KernelBench/runs/l3_default_gpt/original/gpt-5.5-priority/level_3_problem_44_cache/k_2a2f54df4d93/min_gpt_block_ext_v2/cuda.cu".
ninja: build stopped: subcommand failed.
turn 48.7s turn · 8.7s LLM · 0.0s tools
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cmath>\n\n__global__ void gelu_tanh_kernel(const float* __restrict__ x, float* __restrict__ y, long long n) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n const float kAlpha = 0.7978845608028654f;\n const float kBeta = 0.044715f;\n for (long long i = idx; i < n; i += stride) {\n float v = x[i];\n float u = kAlpha * (v + kBeta * v * v * v);\n y[i] = 0.5f * v * (1.0f + tanhf(u));\n }\n}\n\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x) {\n auto y = torch::empty_like(x);\n long long n = x.numel();\n if (n == 0) return y;\n int threads = 256;\n int blocks = (int)((n + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n gelu_tanh_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), n);\n return y;\n}\n\"\"\"\n\n_ext = load_inline(name=\"min_gpt_block_ext_v3\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"gelu_tanh_cuda\"], verbose=False)\n\nclass CausalSelfAttentionNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n assert n_embd % n_head == 0\n self.c_attn = nn.Linear(n_embd, 3 * n_embd)\n self.c_proj = nn.Linear(n_embd, n_embd)\n self.attn_dropout = nn.Dropout(attn_pdrop)\n self.resid_dropout = nn.Dropout(resid_pdrop)\n self.register_buffer(\"bias\", torch.tril(torch.ones(max_seqlen, max_seqlen)).view(1, 1, max_seqlen, max_seqlen))\n self.n_head = n_head\n self.n_embd = n_embd\n\nclass NewGELU(nn.Module):\n def __init__(self):\n super().__init__()\n def forward(self, x):\n return _ext.gelu_tanh_cuda(x)\n\nclass ModelNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n self.ln_1 = nn.LayerNorm(n_embd)\n self.attn = CausalSelfAttentionNew(n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen)\n self.ln_2 = nn.LayerNorm(n_embd)\n self.mlp = nn.ModuleDict(dict(\n c_fc=nn.Linear(n_embd, 4 * n_embd),\n c_proj=nn.Linear(4 * n_embd, n_embd),\n act=NewGELU(),\n dropout=nn.Dropout(resid_pdrop),\n ))\n\n def forward(self, x):\n B, T, C = x.shape\n h = self.ln_1(x)\n qkv = self.attn.c_attn(h)\n q, k, v = qkv.split(C, dim=2)\n nh = self.attn.n_head\n hs = C // nh\n q = q.view(B, T, nh, hs).transpose(1, 2)\n k = k.view(B, T, nh, hs).transpose(1, 2)\n v = v.view(B, T, nh, hs).transpose(1, 2)\n y = F.scaled_dot_product_attention(q, k, v, attn_mask=None, dropout_p=0.0, is_causal=True)\n y = y.transpose(1, 2).contiguous().view(B, T, C)\n y = self.attn.c_proj(y)\n x = x + y\n m = self.ln_2(x)\n m = self.mlp.c_fc(m)\n m = _ext.gelu_tanh_cuda(m)\n m = self.mlp.c_proj(m)\n return x + m\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 57.1s turn · 7.1s LLM · 0.0s tools
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cmath>\n\n__global__ void gelu_tanh_kernel(const float* __restrict__ x, float* __restrict__ y, long long n) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n const float kAlpha = 0.7978845608028654f;\n const float kBeta = 0.044715f;\n for (long long i = idx; i < n; i += stride) {\n float v = x[i];\n float u = kAlpha * (v + kBeta * v * v * v);\n y[i] = 0.5f * v * (1.0f + tanhf(u));\n }\n}\n\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x) {\n auto y = torch::empty_like(x);\n long long n = x.numel();\n if (n == 0) return y;\n int threads = 256;\n int blocks = (int)((n + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n gelu_tanh_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), n);\n return y;\n}\n\"\"\"\n\n_ext = load_inline(name=\"min_gpt_block_ext_v3\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"gelu_tanh_cuda\"], verbose=False)\n\nclass CausalSelfAttentionNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n assert n_embd % n_head == 0\n self.c_attn = nn.Linear(n_embd, 3 * n_embd)\n self.c_proj = nn.Linear(n_embd, n_embd)\n self.attn_dropout = nn.Dropout(attn_pdrop)\n self.resid_dropout = nn.Dropout(resid_pdrop)\n self.register_buffer(\"bias\", torch.tril(torch.ones(max_seqlen, max_seqlen)).view(1, 1, max_seqlen, max_seqlen))\n self.n_head = n_head\n self.n_embd = n_embd\n\nclass NewGELU(nn.Module):\n def __init__(self):\n super().__init__()\n def forward(self, x):\n return _ext.gelu_tanh_cuda(x)\n\nclass ModelNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n self.ln_1 = nn.LayerNorm(n_embd)\n self.attn = CausalSelfAttentionNew(n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen)\n self.ln_2 = nn.LayerNorm(n_embd)\n self.mlp = nn.ModuleDict(dict(\n c_fc=nn.Linear(n_embd, 4 * n_embd),\n c_proj=nn.Linear(4 * n_embd, n_embd),\n act=NewGELU(),\n dropout=nn.Dropout(resid_pdrop),\n ))\n\n def forward(self, x):\n B, T, C = x.shape\n h = self.ln_1(x)\n qkv = self.attn.c_attn(h)\n q, k, v = qkv.split(C, dim=2)\n nh = self.attn.n_head\n hs = C // nh\n q = q.view(B, T, nh, hs).transpose(1, 2)\n k = k.view(B, T, nh, hs).transpose(1, 2)\n v = v.view(B, T, nh, hs).transpose(1, 2)\n y = F.scaled_dot_product_attention(q, k, v, attn_mask=None, dropout_p=0.0, is_causal=True)\n y = y.transpose(1, 2).contiguous().view(B, T, C)\n y = self.attn.c_proj(y)\n x = x + y\n m = self.ln_2(x)\n m = self.mlp.c_fc(m)\n m = _ext.gelu_tanh_cuda(m)\n m = self.mlp.c_proj(m)\n return x + m\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=1.49e-06 mean_abs_err=1.05e-07 max_rel_err=2.46e+05
turn 6 · 1 tool call(s) · 33.8s turn · 33.8s LLM · 8,507 chars (click to expand)
turn 633.8s turn · 33.8s LLM · 0.0s tools
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n#include <vector>\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x);\ntorch::Tensor layernorm_cuda(torch::Tensor x, torch::Tensor gamma, torch::Tensor beta, double eps);\nstd::vector<torch::Tensor> add_layernorm_cuda(torch::Tensor x, torch::Tensor y, torch::Tensor gamma, torch::Tensor beta, double eps);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <vector>\n\n__global__ void gelu_tanh_kernel(const float* __restrict__ x, float* __restrict__ y, long long n) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n const float kAlpha = 0.7978845608028654f;\n const float kBeta = 0.044715f;\n for (long long i = idx; i < n; i += stride) {\n float v = x[i];\n float u = kAlpha * (v + kBeta * v * v * v);\n y[i] = 0.5f * v * (1.0f + __tanhf(u));\n }\n}\n\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x) {\n auto y = torch::empty_like(x);\n long long n = x.numel();\n if (n == 0) return y;\n int threads = 256;\n int blocks = (int)((n + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n gelu_tanh_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), n);\n return y;\n}\n\n__device__ __forceinline__ void warp_reduce_pair(float &a, float &b) {\n for (int offset = 16; offset > 0; offset >>= 1) {\n a += __shfl_down_sync(0xffffffff, a, offset);\n b += __shfl_down_sync(0xffffffff, b, offset);\n }\n}\n\n__global__ void layernorm_kernel(const float* __restrict__ x, const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ out, int rows, int C, float eps) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n float sum = 0.0f, ss = 0.0f;\n const float* xr = x + (long long)row * C;\n for (int c = tid; c < C; c += blockDim.x) {\n float v = xr[c];\n sum += v;\n ss += v * v;\n }\n __shared__ float sh_sum[32];\n __shared__ float sh_ss[32];\n warp_reduce_pair(sum, ss);\n if ((tid & 31) == 0) { sh_sum[tid >> 5] = sum; sh_ss[tid >> 5] = ss; }\n __syncthreads();\n sum = (tid < (blockDim.x >> 5)) ? sh_sum[tid] : 0.0f;\n ss = (tid < (blockDim.x >> 5)) ? sh_ss[tid] : 0.0f;\n if (tid < 32) warp_reduce_pair(sum, ss);\n float mean = __shfl_sync(0xffffffff, sum, 0) / (float)C;\n float var = __shfl_sync(0xffffffff, ss, 0) / (float)C - mean * mean;\n float inv = rsqrtf(var + eps);\n float* orow = out + (long long)row * C;\n for (int c = tid; c < C; c += blockDim.x) {\n orow[c] = (xr[c] - mean) * inv * gamma[c] + beta[c];\n }\n}\n\n__global__ void add_layernorm_kernel(const float* __restrict__ x, const float* __restrict__ y,\n const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ res, float* __restrict__ out, int rows, int C, float eps) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n const long long base = (long long)row * C;\n float sum = 0.0f, ss = 0.0f;\n for (int c = tid; c < C; c += blockDim.x) {\n float v = x[base + c] + y[base + c];\n res[base + c] = v;\n sum += v;\n ss += v * v;\n }\n __shared__ float sh_sum[32];\n __shared__ float sh_ss[32];\n warp_reduce_pair(sum, ss);\n if ((tid & 31) == 0) { sh_sum[tid >> 5] = sum; sh_ss[tid >> 5] = ss; }\n __syncthreads();\n sum = (tid < (blockDim.x >> 5)) ? sh_sum[tid] : 0.0f;\n ss = (tid < (blockDim.x >> 5)) ? sh_ss[tid] : 0.0f;\n if (tid < 32) warp_reduce_pair(sum, ss);\n float mean = __shfl_sync(0xffffffff, sum, 0) / (float)C;\n float var = __shfl_sync(0xffffffff, ss, 0) / (float)C - mean * mean;\n float inv = rsqrtf(var + eps);\n for (int c = tid; c < C; c += blockDim.x) {\n float v = res[base + c];\n out[base + c] = (v - mean) * inv * gamma[c] + beta[c];\n }\n}\n\ntorch::Tensor layernorm_cuda(torch::Tensor x, torch::Tensor gamma, torch::Tensor beta, double eps) {\n auto out = torch::empty_like(x);\n int C = (int)x.size(-1);\n int rows = (int)(x.numel() / C);\n layernorm_kernel<<<rows, 256, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>(), rows, C, (float)eps);\n return out;\n}\n\nstd::vector<torch::Tensor> add_layernorm_cuda(torch::Tensor x, torch::Tensor y, torch::Tensor gamma, torch::Tensor beta, double eps) {\n auto res = torch::empty_like(x);\n auto out = torch::empty_like(x);\n int C = (int)x.size(-1);\n int rows = (int)(x.numel() / C);\n add_layernorm_kernel<<<rows, 256, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), res.data_ptr<float>(), out.data_ptr<float>(), rows, C, (float)eps);\n return {res, out};\n}\n\"\"\"\n\n_ext = load_inline(name=\"min_gpt_block_ext_v4\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"gelu_tanh_cuda\", \"layernorm_cuda\", \"add_layernorm_cuda\"], extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"], verbose=False)\n\nclass CausalSelfAttentionNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n assert n_embd % n_head == 0\n self.c_attn = nn.Linear(n_embd, 3 * n_embd)\n self.c_proj = nn.Linear(n_embd, n_embd)\n self.attn_dropout = nn.Dropout(attn_pdrop)\n self.resid_dropout = nn.Dropout(resid_pdrop)\n self.register_buffer(\"bias\", torch.tril(torch.ones(max_seqlen, max_seqlen)).view(1, 1, max_seqlen, max_seqlen))\n self.n_head = n_head\n self.n_embd = n_embd\n\nclass NewGELU(nn.Module):\n def __init__(self):\n super().__init__()\n def forward(self, x):\n return _ext.gelu_tanh_cuda(x)\n\nclass ModelNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n self.ln_1 = nn.LayerNorm(n_embd)\n self.attn = CausalSelfAttentionNew(n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen)\n self.ln_2 = nn.LayerNorm(n_embd)\n self.mlp = nn.ModuleDict(dict(c_fc=nn.Linear(n_embd, 4*n_embd), c_proj=nn.Linear(4*n_embd, n_embd), act=NewGELU(), dropout=nn.Dropout(resid_pdrop)))\n def forward(self, x):\n B, T, C = x.shape\n h = _ext.layernorm_cuda(x, self.ln_1.weight, self.ln_1.bias, self.ln_1.eps)\n qkv = self.attn.c_attn(h)\n q, k, v = qkv.split(C, dim=2)\n nh = self.attn.n_head; hs = C // nh\n q = q.view(B, T, nh, hs).transpose(1, 2)\n k = k.view(B, T, nh, hs).transpose(1, 2)\n v = v.view(B, T, nh, hs).transpose(1, 2)\n y = F.scaled_dot_product_attention(q, k, v, attn_mask=None, dropout_p=0.0, is_causal=True)\n y = y.transpose(1, 2).contiguous().view(B, T, C)\n y = self.attn.c_proj(y)\n pair = _ext.add_layernorm_cuda(x, y, self.ln_2.weight, self.ln_2.bias, self.ln_2.eps)\n x2 = pair[0]; m = pair[1]\n m = self.mlp.c_fc(m)\n m = _ext.gelu_tanh_cuda(m)\n m = self.mlp.c_proj(m)\n return x2 + m\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 7 · 1 tool call(s) · 18.4s turn · 18.4s LLM · 8,854 chars (click to expand)
turn 718.4s turn · 18.4s LLM · 0.0s tools
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n#include <vector>\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x);\ntorch::Tensor layernorm_cuda(torch::Tensor x, torch::Tensor gamma, torch::Tensor beta, double eps);\nstd::vector<torch::Tensor> add_layernorm_cuda(torch::Tensor x, torch::Tensor y, torch::Tensor gamma, torch::Tensor beta, double eps);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <vector>\n\n__global__ void gelu_tanh_kernel(const float* __restrict__ x, float* __restrict__ y, long long n) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n const float kAlpha = 0.7978845608028654f;\n const float kBeta = 0.044715f;\n for (long long i = idx; i < n; i += stride) {\n float v = x[i];\n float u = kAlpha * (v + kBeta * v * v * v);\n y[i] = 0.5f * v * (1.0f + __tanhf(u));\n }\n}\n\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x) {\n auto y = torch::empty_like(x);\n long long n = x.numel();\n if (n == 0) return y;\n int threads = 256;\n int blocks = (int)((n + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n gelu_tanh_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), n);\n return y;\n}\n\n__device__ __forceinline__ void warp_reduce_pair(float &a, float &b) {\n for (int offset = 16; offset > 0; offset >>= 1) {\n a += __shfl_down_sync(0xffffffff, a, offset);\n b += __shfl_down_sync(0xffffffff, b, offset);\n }\n}\n\n__global__ void layernorm_kernel(const float* __restrict__ x, const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ out, int rows, int C, float eps) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n float sum = 0.0f, ss = 0.0f;\n const float* xr = x + (long long)row * C;\n for (int c = tid; c < C; c += blockDim.x) {\n float v = xr[c];\n sum += v;\n ss += v * v;\n }\n __shared__ float sh_sum[32];\n __shared__ float sh_ss[32];\n warp_reduce_pair(sum, ss);\n if ((tid & 31) == 0) { sh_sum[tid >> 5] = sum; sh_ss[tid >> 5] = ss; }\n __syncthreads();\n sum = (tid < (blockDim.x >> 5)) ? sh_sum[tid] : 0.0f;\n ss = (tid < (blockDim.x >> 5)) ? sh_ss[tid] : 0.0f;\n if (tid < 32) warp_reduce_pair(sum, ss);\n float mean = __shfl_sync(0xffffffff, sum, 0) / (float)C;\n float var = __shfl_sync(0xffffffff, ss, 0) / (float)C - mean * mean;\n float inv = rsqrtf(var + eps);\n float* orow = out + (long long)row * C;\n for (int c = tid; c < C; c += blockDim.x) {\n orow[c] = (xr[c] - mean) * inv * gamma[c] + beta[c];\n }\n}\n\n__global__ void add_layernorm_kernel(const float* __restrict__ x, const float* __restrict__ y,\n const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ res, float* __restrict__ out, int rows, int C, float eps) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n const long long base = (long long)row * C;\n float sum = 0.0f, ss = 0.0f;\n for (int c = tid; c < C; c += blockDim.x) {\n float v = x[base + c] + y[base + c];\n res[base + c] = v;\n sum += v;\n ss += v * v;\n }\n __shared__ float sh_sum[32];\n __shared__ float sh_ss[32];\n warp_reduce_pair(sum, ss);\n if ((tid & 31) == 0) { sh_sum[tid >> 5] = sum; sh_ss[tid >> 5] = ss; }\n __syncthreads();\n sum = (tid < (blockDim.x >> 5)) ? sh_sum[tid] : 0.0f;\n ss = (tid < (blockDim.x >> 5)) ? sh_ss[tid] : 0.0f;\n if (tid < 32) warp_reduce_pair(sum, ss);\n float mean = __shfl_sync(0xffffffff, sum, 0) / (float)C;\n float var = __shfl_sync(0xffffffff, ss, 0) / (float)C - mean * mean;\n float inv = rsqrtf(var + eps);\n for (int c = tid; c < C; c += blockDim.x) {\n float vv = res[base + c];\n out[base + c] = (vv - mean) * inv * gamma[c] + beta[c];\n }\n}\n\ntorch::Tensor layernorm_cuda(torch::Tensor x, torch::Tensor gamma, torch::Tensor beta, double eps) {\n auto out = torch::empty_like(x);\n int C = (int)x.size(-1);\n int rows = (int)(x.numel() / C);\n layernorm_kernel<<<rows, 256, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>(), rows, C, (float)eps);\n return out;\n}\n\nstd::vector<torch::Tensor> add_layernorm_cuda(torch::Tensor x, torch::Tensor y, torch::Tensor gamma, torch::Tensor beta, double eps) {\n auto res = torch::empty_like(x);\n auto out = torch::empty_like(x);\n int C = (int)x.size(-1);\n int rows = (int)(x.numel() / C);\n add_layernorm_kernel<<<rows, 256, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), res.data_ptr<float>(), out.data_ptr<float>(), rows, C, (float)eps);\n return {res, out};\n}\n\"\"\"\n\n_ext = load_inline(name=\"min_gpt_block_ext_v4\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"gelu_tanh_cuda\", \"layernorm_cuda\", \"add_layernorm_cuda\"], extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"], verbose=False)\n\nclass CausalSelfAttentionNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n assert n_embd % n_head == 0\n self.c_attn = nn.Linear(n_embd, 3 * n_embd)\n self.c_proj = nn.Linear(n_embd, n_embd)\n self.attn_dropout = nn.Dropout(attn_pdrop)\n self.resid_dropout = nn.Dropout(resid_pdrop)\n self.register_buffer(\"bias\", torch.tril(torch.ones(max_seqlen, max_seqlen)).view(1, 1, max_seqlen, max_seqlen))\n self.n_head = n_head\n self.n_embd = n_embd\n\nclass NewGELU(nn.Module):\n def __init__(self):\n super().__init__()\n def forward(self, x):\n return _ext.gelu_tanh_cuda(x)\n\nclass ModelNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n self.ln_1 = nn.LayerNorm(n_embd)\n self.attn = CausalSelfAttentionNew(n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen)\n self.ln_2 = nn.LayerNorm(n_embd)\n self.mlp = nn.ModuleDict(dict(c_fc=nn.Linear(n_embd, 4*n_embd), c_proj=nn.Linear(4*n_embd, n_embd), act=NewGELU(), dropout=nn.Dropout(resid_pdrop)))\n def forward(self, x):\n B, T, C = x.shape\n h = _ext.layernorm_cuda(x, self.ln_1.weight, self.ln_1.bias, self.ln_1.eps)\n qkv = self.attn.c_attn(h)\n q, k, v = qkv.split(C, dim=2)\n nh = self.attn.n_head; hs = C // nh\n q = q.view(B, T, nh, hs).transpose(1, 2)\n k = k.view(B, T, nh, hs).transpose(1, 2)\n v = v.view(B, T, nh, hs).transpose(1, 2)\n y = F.scaled_dot_product_attention(q, k, v, attn_mask=None, dropout_p=0.0, is_causal=True)\n y = y.transpose(1, 2).contiguous().view(B, T, C)\n y = self.attn.c_proj(y)\n pair = _ext.add_layernorm_cuda(x, y, self.ln_2.weight, self.ln_2.bias, self.ln_2.eps)\n x2 = pair[0]; m = pair[1]\n m = self.mlp.c_fc(m)\n m = _ext.gelu_tanh_cuda(m)\n m = self.mlp.c_proj(m)\n return x2 + m\n"
}
result ← run_correctness (fail)
failrun_correctness
run_correctness FAILED: (0 / 5) trials did not all match.
correctness_issue: Output mismatch
max_difference: ['19442.572266', '19612.957031', '19766.486328', '19435.285156', '19347.292969']
avg_difference: ['3079.192871', '3075.959717', '3077.475586', '3080.987061', '3077.629639']
turn 8 · 1 tool call(s) · 17.9s turn · 17.9s LLM · 8,716 chars (click to expand)
turn 817.9s turn · 17.9s LLM · 0.0s tools
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n#include <vector>\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x);\ntorch::Tensor layernorm_cuda(torch::Tensor x, torch::Tensor gamma, torch::Tensor beta, double eps);\nstd::vector<torch::Tensor> add_layernorm_cuda(torch::Tensor x, torch::Tensor y, torch::Tensor gamma, torch::Tensor beta, double eps);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <vector>\n\n__global__ void gelu_tanh_kernel(const float* __restrict__ x, float* __restrict__ y, long long n) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n const float kAlpha = 0.7978845608028654f;\n const float kBeta = 0.044715f;\n for (long long i = idx; i < n; i += stride) {\n float v = x[i];\n float u = kAlpha * (v + kBeta * v * v * v);\n y[i] = 0.5f * v * (1.0f + __tanhf(u));\n }\n}\n\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x) {\n auto y = torch::empty_like(x);\n long long n = x.numel();\n if (n == 0) return y;\n int threads = 256;\n int blocks = (int)((n + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n gelu_tanh_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), n);\n return y;\n}\n\n__device__ __forceinline__ void warp_reduce_pair(float &a, float &b) {\n for (int offset = 16; offset > 0; offset >>= 1) {\n a += __shfl_down_sync(0xffffffff, a, offset);\n b += __shfl_down_sync(0xffffffff, b, offset);\n }\n}\n\n__global__ void layernorm_kernel(const float* __restrict__ x, const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ out, int rows, int C, float eps) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n float sum = 0.0f, ss = 0.0f;\n const float* xr = x + (long long)row * C;\n for (int c = tid; c < C; c += blockDim.x) { float v = xr[c]; sum += v; ss += v * v; }\n __shared__ float sh_sum[32];\n __shared__ float sh_ss[32];\n __shared__ float sh_mean;\n __shared__ float sh_inv;\n warp_reduce_pair(sum, ss);\n if ((tid & 31) == 0) { sh_sum[tid >> 5] = sum; sh_ss[tid >> 5] = ss; }\n __syncthreads();\n sum = (tid < (blockDim.x >> 5)) ? sh_sum[tid] : 0.0f;\n ss = (tid < (blockDim.x >> 5)) ? sh_ss[tid] : 0.0f;\n if (tid < 32) warp_reduce_pair(sum, ss);\n if (tid == 0) {\n float mean = sum / (float)C;\n float var = ss / (float)C - mean * mean;\n sh_mean = mean;\n sh_inv = rsqrtf(var + eps);\n }\n __syncthreads();\n float mean = sh_mean, inv = sh_inv;\n float* orow = out + (long long)row * C;\n for (int c = tid; c < C; c += blockDim.x) { orow[c] = (xr[c] - mean) * inv * gamma[c] + beta[c]; }\n}\n\n__global__ void add_layernorm_kernel(const float* __restrict__ x, const float* __restrict__ y,\n const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ res, float* __restrict__ out, int rows, int C, float eps) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n const long long base = (long long)row * C;\n float sum = 0.0f, ss = 0.0f;\n for (int c = tid; c < C; c += blockDim.x) { float v = x[base+c] + y[base+c]; res[base+c] = v; sum += v; ss += v*v; }\n __shared__ float sh_sum[32];\n __shared__ float sh_ss[32];\n __shared__ float sh_mean;\n __shared__ float sh_inv;\n warp_reduce_pair(sum, ss);\n if ((tid & 31) == 0) { sh_sum[tid >> 5] = sum; sh_ss[tid >> 5] = ss; }\n __syncthreads();\n sum = (tid < (blockDim.x >> 5)) ? sh_sum[tid] : 0.0f;\n ss = (tid < (blockDim.x >> 5)) ? sh_ss[tid] : 0.0f;\n if (tid < 32) warp_reduce_pair(sum, ss);\n if (tid == 0) {\n float mean = sum / (float)C;\n float var = ss / (float)C - mean * mean;\n sh_mean = mean;\n sh_inv = rsqrtf(var + eps);\n }\n __syncthreads();\n float mean = sh_mean, inv = sh_inv;\n for (int c = tid; c < C; c += blockDim.x) { float vv = res[base+c]; out[base+c] = (vv - mean) * inv * gamma[c] + beta[c]; }\n}\n\ntorch::Tensor layernorm_cuda(torch::Tensor x, torch::Tensor gamma, torch::Tensor beta, double eps) {\n auto out = torch::empty_like(x);\n int C = (int)x.size(-1); int rows = (int)(x.numel() / C);\n layernorm_kernel<<<rows, 256, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>(), rows, C, (float)eps);\n return out;\n}\n\nstd::vector<torch::Tensor> add_layernorm_cuda(torch::Tensor x, torch::Tensor y, torch::Tensor gamma, torch::Tensor beta, double eps) {\n auto res = torch::empty_like(x); auto out = torch::empty_like(x);\n int C = (int)x.size(-1); int rows = (int)(x.numel() / C);\n add_layernorm_kernel<<<rows, 256, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), res.data_ptr<float>(), out.data_ptr<float>(), rows, C, (float)eps);\n return {res, out};\n}\n\"\"\"\n\n_ext = load_inline(name=\"min_gpt_block_ext_v5\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"gelu_tanh_cuda\", \"layernorm_cuda\", \"add_layernorm_cuda\"], extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"], verbose=False)\n\nclass CausalSelfAttentionNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n assert n_embd % n_head == 0\n self.c_attn = nn.Linear(n_embd, 3 * n_embd)\n self.c_proj = nn.Linear(n_embd, n_embd)\n self.attn_dropout = nn.Dropout(attn_pdrop)\n self.resid_dropout = nn.Dropout(resid_pdrop)\n self.register_buffer(\"bias\", torch.tril(torch.ones(max_seqlen, max_seqlen)).view(1, 1, max_seqlen, max_seqlen))\n self.n_head = n_head\n self.n_embd = n_embd\n\nclass NewGELU(nn.Module):\n def __init__(self): super().__init__()\n def forward(self, x): return _ext.gelu_tanh_cuda(x)\n\nclass ModelNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n self.ln_1 = nn.LayerNorm(n_embd)\n self.attn = CausalSelfAttentionNew(n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen)\n self.ln_2 = nn.LayerNorm(n_embd)\n self.mlp = nn.ModuleDict(dict(c_fc=nn.Linear(n_embd, 4*n_embd), c_proj=nn.Linear(4*n_embd, n_embd), act=NewGELU(), dropout=nn.Dropout(resid_pdrop)))\n def forward(self, x):\n B, T, C = x.shape\n h = _ext.layernorm_cuda(x, self.ln_1.weight, self.ln_1.bias, self.ln_1.eps)\n qkv = self.attn.c_attn(h)\n q, k, v = qkv.split(C, dim=2)\n nh = self.attn.n_head; hs = C // nh\n q = q.view(B, T, nh, hs).transpose(1, 2)\n k = k.view(B, T, nh, hs).transpose(1, 2)\n v = v.view(B, T, nh, hs).transpose(1, 2)\n y = F.scaled_dot_product_attention(q, k, v, attn_mask=None, dropout_p=0.0, is_causal=True)\n y = y.transpose(1, 2).contiguous().view(B, T, C)\n y = self.attn.c_proj(y)\n pair = _ext.add_layernorm_cuda(x, y, self.ln_2.weight, self.ln_2.bias, self.ln_2.eps)\n x2 = pair[0]; m = pair[1]\n m = self.mlp.c_fc(m)\n m = _ext.gelu_tanh_cuda(m)\n m = self.mlp.c_proj(m)\n return x2 + m\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=3.55e-06 mean_abs_err=4.34e-07 max_rel_err=1.53e+06
turn 9 · 1 tool call(s) · 16.8s turn · 16.8s LLM · 8,670 chars (click to expand)
turn 916.8s turn · 16.8s LLM · 0.0s tools
call → static_check
callstatic_check
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n#include <vector>\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x);\ntorch::Tensor layernorm_cuda(torch::Tensor x, torch::Tensor gamma, torch::Tensor beta, double eps);\nstd::vector<torch::Tensor> add_layernorm_cuda(torch::Tensor x, torch::Tensor y, torch::Tensor gamma, torch::Tensor beta, double eps);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <vector>\n\n__global__ void gelu_tanh_kernel(const float* __restrict__ x, float* __restrict__ y, long long n) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n const float kAlpha = 0.7978845608028654f;\n const float kBeta = 0.044715f;\n for (long long i = idx; i < n; i += stride) {\n float v = x[i];\n float u = kAlpha * (v + kBeta * v * v * v);\n y[i] = 0.5f * v * (1.0f + __tanhf(u));\n }\n}\n\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x) {\n auto y = torch::empty_like(x);\n long long n = x.numel();\n if (n == 0) return y;\n int threads = 256;\n int blocks = (int)((n + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n gelu_tanh_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), n);\n return y;\n}\n\n__device__ __forceinline__ void warp_reduce_pair(float &a, float &b) {\n for (int offset = 16; offset > 0; offset >>= 1) {\n a += __shfl_down_sync(0xffffffff, a, offset);\n b += __shfl_down_sync(0xffffffff, b, offset);\n }\n}\n\n__global__ void layernorm_kernel(const float* __restrict__ x, const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ out, int rows, int C, float eps) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n float sum = 0.0f, ss = 0.0f;\n const float* xr = x + (long long)row * C;\n for (int c = tid; c < C; c += blockDim.x) { float v = xr[c]; sum += v; ss += v * v; }\n __shared__ float sh_sum[32];\n __shared__ float sh_ss[32];\n __shared__ float sh_mean;\n __shared__ float sh_inv;\n warp_reduce_pair(sum, ss);\n if ((tid & 31) == 0) { sh_sum[tid >> 5] = sum; sh_ss[tid >> 5] = ss; }\n __syncthreads();\n sum = (tid < (blockDim.x >> 5)) ? sh_sum[tid] : 0.0f;\n ss = (tid < (blockDim.x >> 5)) ? sh_ss[tid] : 0.0f;\n if (tid < 32) warp_reduce_pair(sum, ss);\n if (tid == 0) {\n float mean = sum / (float)C;\n float var = ss / (float)C - mean * mean;\n sh_mean = mean;\n sh_inv = rsqrtf(var + eps);\n }\n __syncthreads();\n float mean = sh_mean, inv = sh_inv;\n float* orow = out + (long long)row * C;\n for (int c = tid; c < C; c += blockDim.x) { orow[c] = (xr[c] - mean) * inv * gamma[c] + beta[c]; }\n}\n\n__global__ void add_layernorm_kernel(const float* __restrict__ x, const float* __restrict__ y,\n const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ res, float* __restrict__ out, int rows, int C, float eps) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n const long long base = (long long)row * C;\n float sum = 0.0f, ss = 0.0f;\n for (int c = tid; c < C; c += blockDim.x) { float v = x[base+c] + y[base+c]; res[base+c] = v; sum += v; ss += v*v; }\n __shared__ float sh_sum[32];\n __shared__ float sh_ss[32];\n __shared__ float sh_mean;\n __shared__ float sh_inv;\n warp_reduce_pair(sum, ss);\n if ((tid & 31) == 0) { sh_sum[tid >> 5] = sum; sh_ss[tid >> 5] = ss; }\n __syncthreads();\n sum = (tid < (blockDim.x >> 5)) ? sh_sum[tid] : 0.0f;\n ss = (tid < (blockDim.x >> 5)) ? sh_ss[tid] : 0.0f;\n if (tid < 32) warp_reduce_pair(sum, ss);\n if (tid == 0) {\n float mean = sum / (float)C;\n float var = ss / (float)C - mean * mean;\n sh_mean = mean;\n sh_inv = rsqrtf(var + eps);\n }\n __syncthreads();\n float mean = sh_mean, inv = sh_inv;\n for (int c = tid; c < C; c += blockDim.x) { float vv = res[base+c]; out[base+c] = (vv - mean) * inv * gamma[c] + beta[c]; }\n}\n\ntorch::Tensor layernorm_cuda(torch::Tensor x, torch::Tensor gamma, torch::Tensor beta, double eps) {\n auto out = torch::empty_like(x);\n int C = (int)x.size(-1); int rows = (int)(x.numel() / C);\n layernorm_kernel<<<rows, 256, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>(), rows, C, (float)eps);\n return out;\n}\n\nstd::vector<torch::Tensor> add_layernorm_cuda(torch::Tensor x, torch::Tensor y, torch::Tensor gamma, torch::Tensor beta, double eps) {\n auto res = torch::empty_like(x); auto out = torch::empty_like(x);\n int C = (int)x.size(-1); int rows = (int)(x.numel() / C);\n add_layernorm_kernel<<<rows, 256, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), res.data_ptr<float>(), out.data_ptr<float>(), rows, C, (float)eps);\n return {res, out};\n}\n\"\"\"\n\n_ext = load_inline(name=\"min_gpt_block_ext_v5\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"gelu_tanh_cuda\", \"layernorm_cuda\", \"add_layernorm_cuda\"], extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"], verbose=False)\n\nclass CausalSelfAttentionNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n assert n_embd % n_head == 0\n self.c_attn = nn.Linear(n_embd, 3 * n_embd)\n self.c_proj = nn.Linear(n_embd, n_embd)\n self.attn_dropout = nn.Dropout(attn_pdrop)\n self.resid_dropout = nn.Dropout(resid_pdrop)\n self.register_buffer(\"bias\", torch.tril(torch.ones(max_seqlen, max_seqlen)).view(1, 1, max_seqlen, max_seqlen))\n self.n_head = n_head\n self.n_embd = n_embd\n\nclass NewGELU(nn.Module):\n def __init__(self): super().__init__()\n def forward(self, x): return _ext.gelu_tanh_cuda(x)\n\nclass ModelNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n self.ln_1 = nn.LayerNorm(n_embd)\n self.attn = CausalSelfAttentionNew(n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen)\n self.ln_2 = nn.LayerNorm(n_embd)\n self.mlp = nn.ModuleDict(dict(c_fc=nn.Linear(n_embd, 4*n_embd), c_proj=nn.Linear(4*n_embd, n_embd), act=NewGELU(), dropout=nn.Dropout(resid_pdrop)))\n def forward(self, x):\n B, T, C = x.shape\n h = _ext.layernorm_cuda(x, self.ln_1.weight, self.ln_1.bias, self.ln_1.eps)\n qkv = self.attn.c_attn(h)\n q, k, v = qkv.split(C, dim=2)\n nh = self.attn.n_head; hs = C // nh\n q = q.view(B, T, nh, hs).transpose(1, 2)\n k = k.view(B, T, nh, hs).transpose(1, 2)\n v = v.view(B, T, nh, hs).transpose(1, 2)\n y = F.scaled_dot_product_attention(q, k, v, attn_mask=None, dropout_p=0.0, is_causal=True)\n y = y.transpose(1, 2).contiguous().view(B, T, C)\n y = self.attn.c_proj(y)\n pair = _ext.add_layernorm_cuda(x, y, self.ln_2.weight, self.ln_2.bias, self.ln_2.eps)\n x2 = pair[0]; m = pair[1]\n m = self.mlp.c_fc(m)\n m = _ext.gelu_tanh_cuda(m)\n m = self.mlp.c_proj(m)\n return x2 + m\n"
}
result ← static_check (ok)
okstatic_check
static_check PASSED (with warnings):
WARNING: Uses torch.nn compute layer (only containers, Parameter, init allowed)
turn 10 · FINAL · 1 tool call(s) · 34.3s turn · 34.3s LLM · 9,621 chars (click to expand)
turn 1034.3s turn · 34.3s LLM · 0.0s tools · FINAL
reasoning
**Evaluating PyTorch options**
I'm thinking about whether PyTorch will choose non-flash for FP32. If it does, that’s acceptable. On the H100, I wonder if flash attention might support FP32. However, I recall that PyTorch's FlashAttention-2 supports only FP16 and bfloat16, while the math kernel is meant for FP32. It’s a bit complex, but I’m trying to keep track of the distinctions as I consider how to work with these formats effectively.
call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n#include <vector>\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x);\ntorch::Tensor layernorm_cuda(torch::Tensor x, torch::Tensor gamma, torch::Tensor beta, double eps);\nstd::vector<torch::Tensor> add_layernorm_cuda(torch::Tensor x, torch::Tensor y, torch::Tensor gamma, torch::Tensor beta, double eps);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <vector>\n\n__global__ void gelu_tanh_kernel(const float* __restrict__ x, float* __restrict__ y, long long n) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n const float kAlpha = 0.7978845608028654f;\n const float kBeta = 0.044715f;\n for (long long i = idx; i < n; i += stride) {\n float v = x[i];\n float u = kAlpha * (v + kBeta * v * v * v);\n y[i] = 0.5f * v * (1.0f + __tanhf(u));\n }\n}\n\ntorch::Tensor gelu_tanh_cuda(torch::Tensor x) {\n auto y = torch::empty_like(x);\n long long n = x.numel();\n if (n == 0) return y;\n int threads = 256;\n int blocks = (int)((n + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n gelu_tanh_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), n);\n return y;\n}\n\n__device__ __forceinline__ void warp_reduce_pair(float &a, float &b) {\n for (int offset = 16; offset > 0; offset >>= 1) {\n a += __shfl_down_sync(0xffffffff, a, offset);\n b += __shfl_down_sync(0xffffffff, b, offset);\n }\n}\n\n__global__ void layernorm_kernel(const float* __restrict__ x, const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ out, int rows, int C, float eps) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n float sum = 0.0f, ss = 0.0f;\n const float* xr = x + (long long)row * C;\n for (int c = tid; c < C; c += blockDim.x) { float v = xr[c]; sum += v; ss += v * v; }\n __shared__ float sh_sum[32];\n __shared__ float sh_ss[32];\n __shared__ float sh_mean;\n __shared__ float sh_inv;\n warp_reduce_pair(sum, ss);\n if ((tid & 31) == 0) { sh_sum[tid >> 5] = sum; sh_ss[tid >> 5] = ss; }\n __syncthreads();\n sum = (tid < (blockDim.x >> 5)) ? sh_sum[tid] : 0.0f;\n ss = (tid < (blockDim.x >> 5)) ? sh_ss[tid] : 0.0f;\n if (tid < 32) warp_reduce_pair(sum, ss);\n if (tid == 0) {\n float mean = sum / (float)C;\n float var = ss / (float)C - mean * mean;\n sh_mean = mean;\n sh_inv = rsqrtf(var + eps);\n }\n __syncthreads();\n float mean = sh_mean, inv = sh_inv;\n float* orow = out + (long long)row * C;\n for (int c = tid; c < C; c += blockDim.x) { orow[c] = (xr[c] - mean) * inv * gamma[c] + beta[c]; }\n}\n\n__global__ void add_layernorm_kernel(const float* __restrict__ x, const float* __restrict__ y,\n const float* __restrict__ gamma, const float* __restrict__ beta,\n float* __restrict__ res, float* __restrict__ out, int rows, int C, float eps) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n const long long base = (long long)row * C;\n float sum = 0.0f, ss = 0.0f;\n for (int c = tid; c < C; c += blockDim.x) { float v = x[base+c] + y[base+c]; res[base+c] = v; sum += v; ss += v*v; }\n __shared__ float sh_sum[32];\n __shared__ float sh_ss[32];\n __shared__ float sh_mean;\n __shared__ float sh_inv;\n warp_reduce_pair(sum, ss);\n if ((tid & 31) == 0) { sh_sum[tid >> 5] = sum; sh_ss[tid >> 5] = ss; }\n __syncthreads();\n sum = (tid < (blockDim.x >> 5)) ? sh_sum[tid] : 0.0f;\n ss = (tid < (blockDim.x >> 5)) ? sh_ss[tid] : 0.0f;\n if (tid < 32) warp_reduce_pair(sum, ss);\n if (tid == 0) {\n float mean = sum / (float)C;\n float var = ss / (float)C - mean * mean;\n sh_mean = mean;\n sh_inv = rsqrtf(var + eps);\n }\n __syncthreads();\n float mean = sh_mean, inv = sh_inv;\n for (int c = tid; c < C; c += blockDim.x) { float vv = res[base+c]; out[base+c] = (vv - mean) * inv * gamma[c] + beta[c]; }\n}\n\ntorch::Tensor layernorm_cuda(torch::Tensor x, torch::Tensor gamma, torch::Tensor beta, double eps) {\n auto out = torch::empty_like(x);\n int C = (int)x.size(-1); int rows = (int)(x.numel() / C);\n layernorm_kernel<<<rows, 256, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>(), rows, C, (float)eps);\n return out;\n}\n\nstd::vector<torch::Tensor> add_layernorm_cuda(torch::Tensor x, torch::Tensor y, torch::Tensor gamma, torch::Tensor beta, double eps) {\n auto res = torch::empty_like(x); auto out = torch::empty_like(x);\n int C = (int)x.size(-1); int rows = (int)(x.numel() / C);\n add_layernorm_kernel<<<rows, 256, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), res.data_ptr<float>(), out.data_ptr<float>(), rows, C, (float)eps);\n return {res, out};\n}\n\"\"\"\n\n_ext = load_inline(name=\"min_gpt_block_ext_final\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"gelu_tanh_cuda\", \"layernorm_cuda\", \"add_layernorm_cuda\"], extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"], verbose=False)\n\nclass CausalSelfAttentionNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n assert n_embd % n_head == 0\n self.c_attn = nn.Linear(n_embd, 3 * n_embd)\n self.c_proj = nn.Linear(n_embd, n_embd)\n self.attn_dropout = nn.Dropout(attn_pdrop)\n self.resid_dropout = nn.Dropout(resid_pdrop)\n self.register_buffer(\"bias\", torch.tril(torch.ones(max_seqlen, max_seqlen)).view(1, 1, max_seqlen, max_seqlen))\n self.n_head = n_head\n self.n_embd = n_embd\n\nclass NewGELU(nn.Module):\n def __init__(self):\n super().__init__()\n def forward(self, x):\n return _ext.gelu_tanh_cuda(x)\n\nclass ModelNew(nn.Module):\n def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):\n super().__init__()\n self.ln_1 = nn.LayerNorm(n_embd)\n self.attn = CausalSelfAttentionNew(n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen)\n self.ln_2 = nn.LayerNorm(n_embd)\n self.mlp = nn.ModuleDict(dict(\n c_fc=nn.Linear(n_embd, 4*n_embd),\n c_proj=nn.Linear(4*n_embd, n_embd),\n act=NewGELU(),\n dropout=nn.Dropout(resid_pdrop),\n ))\n\n def forward(self, x):\n B, T, C = x.shape\n h = _ext.layernorm_cuda(x, self.ln_1.weight, self.ln_1.bias, self.ln_1.eps)\n qkv = self.attn.c_attn(h)\n q, k, v = qkv.split(C, dim=2)\n nh = self.attn.n_head\n hs = C // nh\n q = q.view(B, T, nh, hs).transpose(1, 2)\n k = k.view(B, T, nh, hs).transpose(1, 2)\n v = v.view(B, T, nh, hs).transpose(1, 2)\n y = F.scaled_dot_product_attention(q, k, v, attn_mask=None, dropout_p=0.0, is_causal=True)\n y = y.transpose(1, 2).contiguous().view(B, T, C)\n y = self.attn.c_proj(y)\n pair = _ext.add_layernorm_cuda(x, y, self.ln_2.weight, self.ln_2.bias, self.ln_2.eps)\n x2 = pair[0]\n m = pair[1]\n m = self.mlp.c_fc(m)\n m = _ext.gelu_tanh_cuda(m)\n m = self.mlp.c_proj(m)\n return x2 + m\n"
}
result ← submit_kernel (ok)
oksubmit_kernel
submit_kernel PASSED: (5 / 5) correctness trials all passed.
Kernel runtime: 21.50 μs
Runtime stats: mean=21.50μs median=?μs std=0.83μs
Numerical precision: max_abs_err=3.55e-06 mean_abs_err=4.34e-07 max_rel_err=1.53e+06
Memory: 3167.33 MB peak (ref: 3743.33 MB, ratio: 0.8461x)
Kernel launches: 74 (ref: 140, fusion ratio: 1.8919)
Energy: 2794.88 mJ/run (ref: 3811.64 mJ, ratio: 1.3638x)
SOL score: 1.0
final submitted kernel (177 lines, 7,559 chars) — full source, untruncated
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.cpp_extension import load_inline
_cpp_src = r"""
#include <torch/extension.h>
#include <vector>
torch::Tensor gelu_tanh_cuda(torch::Tensor x);
torch::Tensor layernorm_cuda(torch::Tensor x, torch::Tensor gamma, torch::Tensor beta, double eps);
std::vector<torch::Tensor> add_layernorm_cuda(torch::Tensor x, torch::Tensor y, torch::Tensor gamma, torch::Tensor beta, double eps);
"""
_cuda_src = r"""
#include <torch/extension.h>
#include <ATen/cuda/CUDAContext.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <vector>
__global__ void gelu_tanh_kernel(const float* __restrict__ x, float* __restrict__ y, long long n) {
long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;
long long stride = (long long)blockDim.x * gridDim.x;
const float kAlpha = 0.7978845608028654f;
const float kBeta = 0.044715f;
for (long long i = idx; i < n; i += stride) {
float v = x[i];
float u = kAlpha * (v + kBeta * v * v * v);
y[i] = 0.5f * v * (1.0f + __tanhf(u));
}
}
torch::Tensor gelu_tanh_cuda(torch::Tensor x) {
auto y = torch::empty_like(x);
long long n = x.numel();
if (n == 0) return y;
int threads = 256;
int blocks = (int)((n + threads - 1) / threads);
if (blocks > 65535) blocks = 65535;
gelu_tanh_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), n);
return y;
}
__device__ __forceinline__ void warp_reduce_pair(float &a, float &b) {
for (int offset = 16; offset > 0; offset >>= 1) {
a += __shfl_down_sync(0xffffffff, a, offset);
b += __shfl_down_sync(0xffffffff, b, offset);
}
}
__global__ void layernorm_kernel(const float* __restrict__ x, const float* __restrict__ gamma, const float* __restrict__ beta,
float* __restrict__ out, int rows, int C, float eps) {
int row = blockIdx.x;
int tid = threadIdx.x;
float sum = 0.0f, ss = 0.0f;
const float* xr = x + (long long)row * C;
for (int c = tid; c < C; c += blockDim.x) { float v = xr[c]; sum += v; ss += v * v; }
__shared__ float sh_sum[32];
__shared__ float sh_ss[32];
__shared__ float sh_mean;
__shared__ float sh_inv;
warp_reduce_pair(sum, ss);
if ((tid & 31) == 0) { sh_sum[tid >> 5] = sum; sh_ss[tid >> 5] = ss; }
__syncthreads();
sum = (tid < (blockDim.x >> 5)) ? sh_sum[tid] : 0.0f;
ss = (tid < (blockDim.x >> 5)) ? sh_ss[tid] : 0.0f;
if (tid < 32) warp_reduce_pair(sum, ss);
if (tid == 0) {
float mean = sum / (float)C;
float var = ss / (float)C - mean * mean;
sh_mean = mean;
sh_inv = rsqrtf(var + eps);
}
__syncthreads();
float mean = sh_mean, inv = sh_inv;
float* orow = out + (long long)row * C;
for (int c = tid; c < C; c += blockDim.x) { orow[c] = (xr[c] - mean) * inv * gamma[c] + beta[c]; }
}
__global__ void add_layernorm_kernel(const float* __restrict__ x, const float* __restrict__ y,
const float* __restrict__ gamma, const float* __restrict__ beta,
float* __restrict__ res, float* __restrict__ out, int rows, int C, float eps) {
int row = blockIdx.x;
int tid = threadIdx.x;
const long long base = (long long)row * C;
float sum = 0.0f, ss = 0.0f;
for (int c = tid; c < C; c += blockDim.x) { float v = x[base+c] + y[base+c]; res[base+c] = v; sum += v; ss += v*v; }
__shared__ float sh_sum[32];
__shared__ float sh_ss[32];
__shared__ float sh_mean;
__shared__ float sh_inv;
warp_reduce_pair(sum, ss);
if ((tid & 31) == 0) { sh_sum[tid >> 5] = sum; sh_ss[tid >> 5] = ss; }
__syncthreads();
sum = (tid < (blockDim.x >> 5)) ? sh_sum[tid] : 0.0f;
ss = (tid < (blockDim.x >> 5)) ? sh_ss[tid] : 0.0f;
if (tid < 32) warp_reduce_pair(sum, ss);
if (tid == 0) {
float mean = sum / (float)C;
float var = ss / (float)C - mean * mean;
sh_mean = mean;
sh_inv = rsqrtf(var + eps);
}
__syncthreads();
float mean = sh_mean, inv = sh_inv;
for (int c = tid; c < C; c += blockDim.x) { float vv = res[base+c]; out[base+c] = (vv - mean) * inv * gamma[c] + beta[c]; }
}
torch::Tensor layernorm_cuda(torch::Tensor x, torch::Tensor gamma, torch::Tensor beta, double eps) {
auto out = torch::empty_like(x);
int C = (int)x.size(-1); int rows = (int)(x.numel() / C);
layernorm_kernel<<<rows, 256, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), out.data_ptr<float>(), rows, C, (float)eps);
return out;
}
std::vector<torch::Tensor> add_layernorm_cuda(torch::Tensor x, torch::Tensor y, torch::Tensor gamma, torch::Tensor beta, double eps) {
auto res = torch::empty_like(x); auto out = torch::empty_like(x);
int C = (int)x.size(-1); int rows = (int)(x.numel() / C);
add_layernorm_kernel<<<rows, 256, 0, at::cuda::getCurrentCUDAStream()>>>(x.data_ptr<float>(), y.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), res.data_ptr<float>(), out.data_ptr<float>(), rows, C, (float)eps);
return {res, out};
}
"""
_ext = load_inline(name="min_gpt_block_ext_final", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=["gelu_tanh_cuda", "layernorm_cuda", "add_layernorm_cuda"], extra_cuda_cflags=["-O3", "--use_fast_math"], verbose=False)
class CausalSelfAttentionNew(nn.Module):
def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):
super().__init__()
assert n_embd % n_head == 0
self.c_attn = nn.Linear(n_embd, 3 * n_embd)
self.c_proj = nn.Linear(n_embd, n_embd)
self.attn_dropout = nn.Dropout(attn_pdrop)
self.resid_dropout = nn.Dropout(resid_pdrop)
self.register_buffer("bias", torch.tril(torch.ones(max_seqlen, max_seqlen)).view(1, 1, max_seqlen, max_seqlen))
self.n_head = n_head
self.n_embd = n_embd
class NewGELU(nn.Module):
def __init__(self):
super().__init__()
def forward(self, x):
return _ext.gelu_tanh_cuda(x)
class ModelNew(nn.Module):
def __init__(self, n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen):
super().__init__()
self.ln_1 = nn.LayerNorm(n_embd)
self.attn = CausalSelfAttentionNew(n_embd, n_head, attn_pdrop, resid_pdrop, max_seqlen)
self.ln_2 = nn.LayerNorm(n_embd)
self.mlp = nn.ModuleDict(dict(
c_fc=nn.Linear(n_embd, 4*n_embd),
c_proj=nn.Linear(4*n_embd, n_embd),
act=NewGELU(),
dropout=nn.Dropout(resid_pdrop),
))
def forward(self, x):
B, T, C = x.shape
h = _ext.layernorm_cuda(x, self.ln_1.weight, self.ln_1.bias, self.ln_1.eps)
qkv = self.attn.c_attn(h)
q, k, v = qkv.split(C, dim=2)
nh = self.attn.n_head
hs = C // nh
q = q.view(B, T, nh, hs).transpose(1, 2)
k = k.view(B, T, nh, hs).transpose(1, 2)
v = v.view(B, T, nh, hs).transpose(1, 2)
y = F.scaled_dot_product_attention(q, k, v, attn_mask=None, dropout_p=0.0, is_causal=True)
y = y.transpose(1, 2).contiguous().view(B, T, C)
y = self.attn.c_proj(y)
pair = _ext.add_layernorm_cuda(x, y, self.ln_2.weight, self.ln_2.bias, self.ln_2.eps)
x2 = pair[0]
m = pair[1]
m = self.mlp.c_fc(m)
m = _ext.gelu_tanh_cuda(m)
m = self.mlp.c_proj(m)
return x2 + m