correct
49_sum_gelu_across_virtual_ranks.py
started
2026-05-05T02:31:26Z
timingkernelbench.timing
kernel mean / median / std
0.01 / — / 1.86e-04 μs
ref mean / median / std
0.01 / — / 5.56e-04 μs
numerical precisioneval_kernel_against_ref
gpu memoryextended_metrics.measure_memory
kernel launches / fusiontorch.profiler
fusion ratio (ref / kernel)
3.00x
SOL (speed-of-light)nsight_hardware_counters
roofline / occupancynsight_hardware_counters
warp stalls (top 5)nsight
reference PyTorch source (the prompt the agent sees)
"""
Order-sensitive virtual collective: out = sum_r GELU(x_r), same shape as one rank slice (B, D).
Note: this is not equal to GELU(sum_r x_r).
"""
import torch
import torch.nn as nn
import torch.nn.functional as F
from kernelbench.distributed_collectives import default_device
R = 4
B = 14
D = 40
class Model(nn.Module):
def __init__(self):
super().__init__()
def forward(self, x: torch.Tensor) -> torch.Tensor:
return F.gelu(x).sum(dim=0)
def get_inputs():
dev = default_device()
p = popcorn_pri
return [torch.randn(p.jitter_int(R), p.jitter_int(B), p.jitter_int(D, align=8), device=dev)]
def get_init_inputs():
return []
turn 015.4s turn · 15.4s LLM · 0.0s tools · FINAL
call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n\ntorch::Tensor gelu_sum_forward(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\n__device__ __forceinline__ float gelu_exact_f32(float v) {\n // PyTorch F.gelu default (approximate='none'): 0.5*x*(1+erf(x/sqrt(2))).\n return 0.5f * v * (1.0f + erff(v * 0.70710678118654752440f));\n}\n\n__global__ void gelu_sum_kernel_4(const float* __restrict__ x, float* __restrict__ y) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (idx < 560) { // B*D = 14*40 for this benchmark\n float s = 0.0f;\n s += gelu_exact_f32(x[idx]);\n s += gelu_exact_f32(x[560 + idx]);\n s += gelu_exact_f32(x[1120 + idx]);\n s += gelu_exact_f32(x[1680 + idx]);\n y[idx] = s;\n }\n}\n\n__global__ void gelu_sum_kernel_generic(const float* __restrict__ x, float* __restrict__ y,\n int R, int N) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (idx < N) {\n float s = 0.0f;\n for (int r = 0; r < R; ++r) {\n s += gelu_exact_f32(x[r * N + idx]);\n }\n y[idx] = s;\n }\n}\n\ntorch::Tensor gelu_sum_forward(torch::Tensor x) {\n const int64_t R = x.size(0);\n const int64_t B = x.size(1);\n const int64_t D = x.size(2);\n auto y = torch::empty({B, D}, x.options());\n const int N = (int)(B * D);\n const int threads = 256;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n if (R == 4 && N == 560 && x.scalar_type() == at::ScalarType::Float) {\n gelu_sum_kernel_4<<<3, threads, 0, stream>>>(x.data_ptr<float>(), y.data_ptr<float>());\n } else {\n int blocks = (N + threads - 1) / threads;\n gelu_sum_kernel_generic<<<blocks, threads, 0, stream>>>(x.data_ptr<float>(), y.data_ptr<float>(), (int)R, N);\n }\n return y;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"gelu_sum_r4_b14_d40_ext\",\n cpp_sources=[_cpp_src],\n cuda_sources=[_cuda_src],\n functions=[\"gelu_sum_forward\"],\n extra_cuda_cflags=[\"-O3\"],\n extra_cflags=[\"-O3\"],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.gelu_sum_forward(x)\n"
}
result ← submit_kernel (ok)
oksubmit_kernel
submit_kernel PASSED: (5 / 5) correctness trials all passed.
Kernel runtime: 0.01 μs
Runtime stats: mean=0.01μs median=?μs std=0.00μs
Numerical precision: max_abs_err=4.77e-07 mean_abs_err=2.90e-08 max_rel_err=2.91e-05
Memory: 33.01 MB peak (ref: 33.02 MB, ratio: 0.9997x)
Kernel launches: 1 (ref: 3, fusion ratio: 3.0)
SOL score: 0.0013
final submitted kernel (80 lines, 2,406 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline
_cpp_src = r"""
#include <torch/extension.h>
torch::Tensor gelu_sum_forward(torch::Tensor x);
"""
_cuda_src = r"""
#include <torch/extension.h>
#include <ATen/cuda/CUDAContext.h>
#include <cuda.h>
#include <cuda_runtime.h>
__device__ __forceinline__ float gelu_exact_f32(float v) {
// PyTorch F.gelu default (approximate='none'): 0.5*x*(1+erf(x/sqrt(2))).
return 0.5f * v * (1.0f + erff(v * 0.70710678118654752440f));
}
__global__ void gelu_sum_kernel_4(const float* __restrict__ x, float* __restrict__ y) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < 560) { // B*D = 14*40 for this benchmark
float s = 0.0f;
s += gelu_exact_f32(x[idx]);
s += gelu_exact_f32(x[560 + idx]);
s += gelu_exact_f32(x[1120 + idx]);
s += gelu_exact_f32(x[1680 + idx]);
y[idx] = s;
}
}
__global__ void gelu_sum_kernel_generic(const float* __restrict__ x, float* __restrict__ y,
int R, int N) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < N) {
float s = 0.0f;
for (int r = 0; r < R; ++r) {
s += gelu_exact_f32(x[r * N + idx]);
}
y[idx] = s;
}
}
torch::Tensor gelu_sum_forward(torch::Tensor x) {
const int64_t R = x.size(0);
const int64_t B = x.size(1);
const int64_t D = x.size(2);
auto y = torch::empty({B, D}, x.options());
const int N = (int)(B * D);
const int threads = 256;
cudaStream_t stream = at::cuda::getCurrentCUDAStream();
if (R == 4 && N == 560 && x.scalar_type() == at::ScalarType::Float) {
gelu_sum_kernel_4<<<3, threads, 0, stream>>>(x.data_ptr<float>(), y.data_ptr<float>());
} else {
int blocks = (N + threads - 1) / threads;
gelu_sum_kernel_generic<<<blocks, threads, 0, stream>>>(x.data_ptr<float>(), y.data_ptr<float>(), (int)R, N);
}
return y;
}
"""
_ext = load_inline(
name="gelu_sum_r4_b14_d40_ext",
cpp_sources=[_cpp_src],
cuda_sources=[_cuda_src],
functions=["gelu_sum_forward"],
extra_cuda_cflags=["-O3"],
extra_cflags=["-O3"],
verbose=False,
)
class ModelNew(nn.Module):
def __init__(self):
super().__init__()
def forward(self, x: torch.Tensor) -> torch.Tensor:
return _ext.gelu_sum_forward(x)