correct
45_Gemm_Sigmoid_LogSumExp.py
started
2026-05-02T18:41:09Z
timingkernelbench.timing
kernel mean / median / std
8.50 / — / 0.30 μs
ref mean / median / std
8.57 / — / 0.25 μs
numerical precisioneval_kernel_against_ref
gpu memoryextended_metrics.measure_memory
kernel launches / fusiontorch.profiler
fusion ratio (ref / kernel)
3.44x
energyNVML (pynvml)
ratio (ref / kernel)
1.00x
SOL (speed-of-light)nsight_hardware_counters
roofline / occupancynsight_hardware_counters
dram bandwidth
4872.11 GB/s
warp stalls (top 5)nsight
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn
class Model(nn.Module):
"""
Model that performs a matrix multiplication (Gemm), applies Sigmoid,
another Gemm, and computes LogSumExp over features.
"""
def __init__(self, input_size, hidden_size, output_size):
super(Model, self).__init__()
self.linear1 = nn.Linear(input_size, hidden_size)
self.linear2 = nn.Linear(hidden_size, output_size)
def forward(self, x):
x = self.linear1(x)
x = torch.sigmoid(x)
x = self.linear2(x)
x = torch.logsumexp(x, dim=1) # compute LogSumExp over features per sample
return x
batch_size = 16384
input_size = 2048
hidden_size = 4096
output_size = 1024
def get_inputs():
return [torch.rand(batch_size, input_size)]
def get_init_inputs():
return [input_size, hidden_size, output_size]
turn 08.9s turn · 8.9s 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 124.3s turn · 24.3s LLM · 0.0s tools
reasoning
**Exploring C++ Linear Functions**
I'm trying to figure out how to use at::linear in C++. Should I include <torch/extension.h>? Also, is using `torch::linear` the correct approach? From what I see in the C++ API, at::linear(input, weight, bias) might be defined in ATen/ops/linear.h. I want to make sure I have all the correct details for working with linear functions in the PyTorch C++ API. Let’s see what else I can uncover!
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_src = r'''\n#include <torch/extension.h>\n\ntorch::Tensor forward_cuda(torch::Tensor x, torch::Tensor w1, torch::Tensor b1, torch::Tensor w2, torch::Tensor b2);\n'''\n\ncuda_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 sigmoid_inplace_kernel(float* __restrict__ data, int64_t n) {\n int64_t idx = (int64_t)blockIdx.x * blockDim.x + threadIdx.x;\n int64_t stride = (int64_t)blockDim.x * gridDim.x;\n for (int64_t i = idx; i < n; i += stride) {\n float v = data[i];\n data[i] = 1.0f / (1.0f + expf(-v));\n }\n}\n\n__inline__ __device__ float warp_reduce_max(float v) {\n for (int offset = 16; offset > 0; offset >>= 1) v = fmaxf(v, __shfl_down_sync(0xffffffff, v, offset));\n return v;\n}\n__inline__ __device__ float warp_reduce_sum(float v) {\n for (int offset = 16; offset > 0; offset >>= 1) v += __shfl_down_sync(0xffffffff, v, offset);\n return v;\n}\n\n__global__ void logsumexp_kernel(const float* __restrict__ input, float* __restrict__ output, int rows, int cols) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n const float* rowptr = input + (int64_t)row * cols;\n float m = -INFINITY;\n for (int c = tid; c < cols; c += blockDim.x) {\n m = fmaxf(m, rowptr[c]);\n }\n m = warp_reduce_max(m);\n __shared__ float smem[32];\n int lane = tid & 31;\n int warp = tid >> 5;\n if (lane == 0) smem[warp] = m;\n __syncthreads();\n float bm = -INFINITY;\n if (tid < (blockDim.x >> 5)) bm = smem[tid];\n bm = warp_reduce_max(bm);\n bm = __shfl_sync(0xffffffff, bm, 0);\n\n float s = 0.0f;\n for (int c = tid; c < cols; c += blockDim.x) {\n s += expf(rowptr[c] - bm);\n }\n s = warp_reduce_sum(s);\n if (lane == 0) smem[warp] = s;\n __syncthreads();\n float bs = 0.0f;\n if (tid < (blockDim.x >> 5)) bs = smem[tid];\n bs = warp_reduce_sum(bs);\n if (tid == 0) output[row] = logf(bs) + bm;\n}\n\ntorch::Tensor forward_cuda(torch::Tensor x, torch::Tensor w1, torch::Tensor b1, torch::Tensor w2, torch::Tensor b2) {\n // h = x @ w1.T + b1\n auto h = at::addmm(b1, x, w1.t());\n int64_t hn = h.numel();\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n int threads = 256;\n int blocks = (int)std::min<int64_t>((hn + threads - 1) / threads, 65535);\n sigmoid_inplace_kernel<<<blocks, threads, 0, stream>>>(h.data_ptr<float>(), hn);\n auto y = at::addmm(b2, h, w2.t());\n auto out = torch::empty({y.size(0)}, y.options());\n logsumexp_kernel<<<(int)y.size(0), 256, 0, stream>>>(y.data_ptr<float>(), out.data_ptr<float>(), (int)y.size(0), (int)y.size(1));\n return out;\n}\n'''\n\n_ext = load_inline(name='gemm_sigmoid_gemm_lse_ext_v1', cpp_sources=cpp_src, cuda_sources=cuda_src,\n functions=['forward_cuda'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, input_size, hidden_size, output_size):\n super(ModelNew, self).__init__()\n self.linear1 = nn.Linear(input_size, hidden_size)\n self.linear2 = nn.Linear(hidden_size, output_size)\n def forward(self, x):\n return _ext.forward_cuda(x, self.linear1.weight, self.linear1.bias, self.linear2.weight, self.linear2.bias)\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 28.9s turn · 8.9s LLM · 0.0s tools
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_src = r'''\n#include <torch/extension.h>\n\ntorch::Tensor forward_cuda(torch::Tensor x, torch::Tensor w1, torch::Tensor b1, torch::Tensor w2, torch::Tensor b2);\n'''\n\ncuda_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 sigmoid_inplace_kernel(float* __restrict__ data, int64_t n) {\n int64_t idx = (int64_t)blockIdx.x * blockDim.x + threadIdx.x;\n int64_t stride = (int64_t)blockDim.x * gridDim.x;\n for (int64_t i = idx; i < n; i += stride) {\n float v = data[i];\n data[i] = 1.0f / (1.0f + expf(-v));\n }\n}\n\n__inline__ __device__ float warp_reduce_max(float v) {\n for (int offset = 16; offset > 0; offset >>= 1) v = fmaxf(v, __shfl_down_sync(0xffffffff, v, offset));\n return v;\n}\n__inline__ __device__ float warp_reduce_sum(float v) {\n for (int offset = 16; offset > 0; offset >>= 1) v += __shfl_down_sync(0xffffffff, v, offset);\n return v;\n}\n\n__global__ void logsumexp_kernel(const float* __restrict__ input, float* __restrict__ output, int rows, int cols) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n const float* rowptr = input + (int64_t)row * cols;\n float m = -INFINITY;\n for (int c = tid; c < cols; c += blockDim.x) {\n m = fmaxf(m, rowptr[c]);\n }\n m = warp_reduce_max(m);\n __shared__ float smem[32];\n int lane = tid & 31;\n int warp = tid >> 5;\n if (lane == 0) smem[warp] = m;\n __syncthreads();\n float bm = -INFINITY;\n if (tid < (blockDim.x >> 5)) bm = smem[tid];\n bm = warp_reduce_max(bm);\n bm = __shfl_sync(0xffffffff, bm, 0);\n\n float s = 0.0f;\n for (int c = tid; c < cols; c += blockDim.x) {\n s += expf(rowptr[c] - bm);\n }\n s = warp_reduce_sum(s);\n if (lane == 0) smem[warp] = s;\n __syncthreads();\n float bs = 0.0f;\n if (tid < (blockDim.x >> 5)) bs = smem[tid];\n bs = warp_reduce_sum(bs);\n if (tid == 0) output[row] = logf(bs) + bm;\n}\n\ntorch::Tensor forward_cuda(torch::Tensor x, torch::Tensor w1, torch::Tensor b1, torch::Tensor w2, torch::Tensor b2) {\n auto h = at::addmm(b1, x, w1.t());\n int64_t hn = h.numel();\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n int threads = 256;\n int blocks = (int)std::min<int64_t>((hn + threads - 1) / threads, 65535);\n sigmoid_inplace_kernel<<<blocks, threads, 0, stream>>>(h.data_ptr<float>(), hn);\n auto y = at::addmm(b2, h, w2.t());\n auto out = torch::empty({y.size(0)}, y.options());\n logsumexp_kernel<<<(int)y.size(0), 256, 0, stream>>>(y.data_ptr<float>(), out.data_ptr<float>(), (int)y.size(0), (int)y.size(1));\n return out;\n}\n'''\n\n_ext = load_inline(name='gemm_sigmoid_gemm_lse_ext_v1', cpp_sources=cpp_src, cuda_sources=cuda_src,\n functions=['forward_cuda'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, input_size, hidden_size, output_size):\n super(ModelNew, self).__init__()\n self.linear1 = nn.Linear(input_size, hidden_size)\n self.linear2 = nn.Linear(hidden_size, output_size)\n def forward(self, x):\n return _ext.forward_cuda(x, self.linear1.weight, self.linear1.bias, self.linear2.weight, self.linear2.bias)\n"
}
result ← run_correctness (fail)
failrun_correctness
run_correctness FAILED: (0 / 5) trials did not all match.
correctness_issue: Output mismatch
max_difference: ['inf', 'inf', 'inf', 'inf', 'inf']
avg_difference: ['inf', 'inf', 'inf', 'inf', 'inf']
turn 310.8s turn · 10.8s LLM · 0.0s tools
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_src = r'''\n#include <torch/extension.h>\n\ntorch::Tensor forward_cuda(torch::Tensor x, torch::Tensor w1, torch::Tensor b1, torch::Tensor w2, torch::Tensor b2);\n'''\n\ncuda_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 sigmoid_inplace_kernel(float* __restrict__ data, int64_t n) {\n int64_t idx = (int64_t)blockIdx.x * blockDim.x + threadIdx.x;\n int64_t stride = (int64_t)blockDim.x * gridDim.x;\n for (int64_t i = idx; i < n; i += stride) {\n float v = data[i];\n data[i] = 1.0f / (1.0f + expf(-v));\n }\n}\n\n__inline__ __device__ float warp_reduce_max(float v) {\n for (int offset = 16; offset > 0; offset >>= 1) v = fmaxf(v, __shfl_down_sync(0xffffffff, v, offset));\n return v;\n}\n__inline__ __device__ float warp_reduce_sum(float v) {\n for (int offset = 16; offset > 0; offset >>= 1) v += __shfl_down_sync(0xffffffff, v, offset);\n return v;\n}\n\n__global__ void logsumexp_kernel(const float* __restrict__ input, float* __restrict__ output, int rows, int cols) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n const float* rowptr = input + (int64_t)row * cols;\n __shared__ float smem[32];\n int lane = tid & 31;\n int warp = tid >> 5;\n\n float m = -INFINITY;\n for (int c = tid; c < cols; c += blockDim.x) m = fmaxf(m, rowptr[c]);\n m = warp_reduce_max(m);\n if (lane == 0) smem[warp] = m;\n __syncthreads();\n float bm = -INFINITY;\n if (tid < (blockDim.x >> 5)) bm = smem[tid];\n bm = warp_reduce_max(bm);\n if (tid == 0) smem[0] = bm;\n __syncthreads();\n bm = smem[0];\n\n float s = 0.0f;\n for (int c = tid; c < cols; c += blockDim.x) s += expf(rowptr[c] - bm);\n s = warp_reduce_sum(s);\n if (lane == 0) smem[warp] = s;\n __syncthreads();\n float bs = 0.0f;\n if (tid < (blockDim.x >> 5)) bs = smem[tid];\n bs = warp_reduce_sum(bs);\n if (tid == 0) output[row] = logf(bs) + bm;\n}\n\ntorch::Tensor forward_cuda(torch::Tensor x, torch::Tensor w1, torch::Tensor b1, torch::Tensor w2, torch::Tensor b2) {\n auto h = at::addmm(b1, x, w1.t());\n int64_t hn = h.numel();\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n int threads = 256;\n int blocks = (int)std::min<int64_t>((hn + threads - 1) / threads, 65535);\n sigmoid_inplace_kernel<<<blocks, threads, 0, stream>>>(h.data_ptr<float>(), hn);\n auto y = at::addmm(b2, h, w2.t());\n auto out = torch::empty({y.size(0)}, y.options());\n logsumexp_kernel<<<(int)y.size(0), 256, 0, stream>>>(y.data_ptr<float>(), out.data_ptr<float>(), (int)y.size(0), (int)y.size(1));\n return out;\n}\n'''\n\n_ext = load_inline(name='gemm_sigmoid_gemm_lse_ext_v2', cpp_sources=cpp_src, cuda_sources=cuda_src,\n functions=['forward_cuda'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, input_size, hidden_size, output_size):\n super(ModelNew, self).__init__()\n self.linear1 = nn.Linear(input_size, hidden_size)\n self.linear2 = nn.Linear(hidden_size, output_size)\n def forward(self, x):\n return _ext.forward_cuda(x, self.linear1.weight, self.linear1.bias, self.linear2.weight, self.linear2.bias)\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=9.54e-07 mean_abs_err=2.41e-08 max_rel_err=1.37e-07
turn 414.8s turn · 14.8s LLM · 0.0s tools
reasoning
**Optimizing performance**
I’m considering how to improve performance by possibly using static checks or submitting directly. While I could run a submit, exploring alternatives like `at::sigmoid` in-place could be beneficial. I wonder if a custom sigmoid would be faster, and the logsumexp could also enhance speed. However, I need to ensure that my custom implementations don’t have unnecessary allocations. It seems that using in-place methods might save significant time and memory, so I'll optimize further on this. Custom solutions could work well!
**Exploring optimization options**
I’m thinking about combining sigmoid functions and possibly adding the bias with `at::addmm`. I wonder if allowing TF32 would help since it respects PyTorch's global settings. There could be an issue with inputs not being contiguous, but using `torch.rand` keeps them that way. I could also optimize logsumexp for fixed columns by tweaking threads. Additionally, utilizing CUDAGraph for repeated evaluations could be tricky since parameters may have the same addresses. I need to explore static checks further.
call → static_check
callstatic_check
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_src = r'''\n#include <torch/extension.h>\n\ntorch::Tensor forward_cuda(torch::Tensor x, torch::Tensor w1, torch::Tensor b1, torch::Tensor w2, torch::Tensor b2);\n'''\n\ncuda_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 sigmoid_inplace_kernel(float* __restrict__ data, int64_t n) {\n int64_t idx = (int64_t)blockIdx.x * blockDim.x + threadIdx.x;\n int64_t stride = (int64_t)blockDim.x * gridDim.x;\n for (int64_t i = idx; i < n; i += stride) {\n float v = data[i];\n data[i] = 1.0f / (1.0f + expf(-v));\n }\n}\n\n__inline__ __device__ float warp_reduce_max(float v) {\n for (int offset = 16; offset > 0; offset >>= 1) v = fmaxf(v, __shfl_down_sync(0xffffffff, v, offset));\n return v;\n}\n__inline__ __device__ float warp_reduce_sum(float v) {\n for (int offset = 16; offset > 0; offset >>= 1) v += __shfl_down_sync(0xffffffff, v, offset);\n return v;\n}\n\n__global__ void logsumexp_kernel(const float* __restrict__ input, float* __restrict__ output, int rows, int cols) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n const float* rowptr = input + (int64_t)row * cols;\n __shared__ float smem[32];\n int lane = tid & 31;\n int warp = tid >> 5;\n\n float m = -INFINITY;\n for (int c = tid; c < cols; c += blockDim.x) m = fmaxf(m, rowptr[c]);\n m = warp_reduce_max(m);\n if (lane == 0) smem[warp] = m;\n __syncthreads();\n float bm = -INFINITY;\n if (tid < (blockDim.x >> 5)) bm = smem[tid];\n bm = warp_reduce_max(bm);\n if (tid == 0) smem[0] = bm;\n __syncthreads();\n bm = smem[0];\n\n float s = 0.0f;\n for (int c = tid; c < cols; c += blockDim.x) s += expf(rowptr[c] - bm);\n s = warp_reduce_sum(s);\n if (lane == 0) smem[warp] = s;\n __syncthreads();\n float bs = 0.0f;\n if (tid < (blockDim.x >> 5)) bs = smem[tid];\n bs = warp_reduce_sum(bs);\n if (tid == 0) output[row] = logf(bs) + bm;\n}\n\ntorch::Tensor forward_cuda(torch::Tensor x, torch::Tensor w1, torch::Tensor b1, torch::Tensor w2, torch::Tensor b2) {\n auto h = at::addmm(b1, x, w1.t());\n int64_t hn = h.numel();\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n int threads = 256;\n int blocks = (int)std::min<int64_t>((hn + threads - 1) / threads, 65535);\n sigmoid_inplace_kernel<<<blocks, threads, 0, stream>>>(h.data_ptr<float>(), hn);\n auto y = at::addmm(b2, h, w2.t());\n auto out = torch::empty({y.size(0)}, y.options());\n logsumexp_kernel<<<(int)y.size(0), 256, 0, stream>>>(y.data_ptr<float>(), out.data_ptr<float>(), (int)y.size(0), (int)y.size(1));\n return out;\n}\n'''\n\n_ext = load_inline(name='gemm_sigmoid_gemm_lse_ext_v2', cpp_sources=cpp_src, cuda_sources=cuda_src,\n functions=['forward_cuda'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, input_size, hidden_size, output_size):\n super(ModelNew, self).__init__()\n self.linear1 = nn.Linear(input_size, hidden_size)\n self.linear2 = nn.Linear(hidden_size, output_size)\n def forward(self, x):\n return _ext.forward_cuda(x, self.linear1.weight, self.linear1.bias, self.linear2.weight, self.linear2.bias)\n"
}
result ← static_check (ok)
okstatic_check
static_check PASSED: no violations or warnings detected.
turn 57.7s turn · 7.7s LLM · 0.0s tools · FINAL
reasoning
**Deciding on submission**
I'm considering whether I need to submit something now. It might just be code, but actually, I should use the submission tool to finalize things. I think testing the timing through submission now could be helpful, though. I'm feeling a bit uncertain, but I suppose I should just go ahead and do it! It's better to take action than to hesitate too long. So, I'll submit!
call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_src = r'''\n#include <torch/extension.h>\n\ntorch::Tensor forward_cuda(torch::Tensor x, torch::Tensor w1, torch::Tensor b1, torch::Tensor w2, torch::Tensor b2);\n'''\n\ncuda_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 sigmoid_inplace_kernel(float* __restrict__ data, int64_t n) {\n int64_t idx = (int64_t)blockIdx.x * blockDim.x + threadIdx.x;\n int64_t stride = (int64_t)blockDim.x * gridDim.x;\n for (int64_t i = idx; i < n; i += stride) {\n float v = data[i];\n data[i] = 1.0f / (1.0f + expf(-v));\n }\n}\n\n__inline__ __device__ float warp_reduce_max(float v) {\n for (int offset = 16; offset > 0; offset >>= 1) v = fmaxf(v, __shfl_down_sync(0xffffffff, v, offset));\n return v;\n}\n__inline__ __device__ float warp_reduce_sum(float v) {\n for (int offset = 16; offset > 0; offset >>= 1) v += __shfl_down_sync(0xffffffff, v, offset);\n return v;\n}\n\n__global__ void logsumexp_kernel(const float* __restrict__ input, float* __restrict__ output, int rows, int cols) {\n int row = blockIdx.x;\n int tid = threadIdx.x;\n const float* rowptr = input + (int64_t)row * cols;\n __shared__ float smem[32];\n int lane = tid & 31;\n int warp = tid >> 5;\n\n float m = -INFINITY;\n for (int c = tid; c < cols; c += blockDim.x) m = fmaxf(m, rowptr[c]);\n m = warp_reduce_max(m);\n if (lane == 0) smem[warp] = m;\n __syncthreads();\n float bm = -INFINITY;\n if (tid < (blockDim.x >> 5)) bm = smem[tid];\n bm = warp_reduce_max(bm);\n if (tid == 0) smem[0] = bm;\n __syncthreads();\n bm = smem[0];\n\n float s = 0.0f;\n for (int c = tid; c < cols; c += blockDim.x) s += expf(rowptr[c] - bm);\n s = warp_reduce_sum(s);\n if (lane == 0) smem[warp] = s;\n __syncthreads();\n float bs = 0.0f;\n if (tid < (blockDim.x >> 5)) bs = smem[tid];\n bs = warp_reduce_sum(bs);\n if (tid == 0) output[row] = logf(bs) + bm;\n}\n\ntorch::Tensor forward_cuda(torch::Tensor x, torch::Tensor w1, torch::Tensor b1, torch::Tensor w2, torch::Tensor b2) {\n auto h = at::addmm(b1, x, w1.t());\n int64_t hn = h.numel();\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n int threads = 256;\n int blocks = (int)std::min<int64_t>((hn + threads - 1) / threads, 65535);\n sigmoid_inplace_kernel<<<blocks, threads, 0, stream>>>(h.data_ptr<float>(), hn);\n auto y = at::addmm(b2, h, w2.t());\n auto out = torch::empty({y.size(0)}, y.options());\n logsumexp_kernel<<<(int)y.size(0), 256, 0, stream>>>(y.data_ptr<float>(), out.data_ptr<float>(), (int)y.size(0), (int)y.size(1));\n return out;\n}\n'''\n\n_ext = load_inline(name='gemm_sigmoid_gemm_lse_ext_final', cpp_sources=cpp_src, cuda_sources=cuda_src,\n functions=['forward_cuda'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, input_size, hidden_size, output_size):\n super(ModelNew, self).__init__()\n self.linear1 = nn.Linear(input_size, hidden_size)\n self.linear2 = nn.Linear(hidden_size, output_size)\n def forward(self, x):\n return _ext.forward_cuda(x, self.linear1.weight, self.linear1.bias, self.linear2.weight, self.linear2.bias)\n"
}
result ← submit_kernel (ok)
oksubmit_kernel
submit_kernel PASSED: (5 / 5) correctness trials all passed.
Kernel runtime: 8.50 μs
Runtime stats: mean=8.50μs median=?μs std=0.30μs
Numerical precision: max_abs_err=9.54e-07 mean_abs_err=2.41e-08 max_rel_err=1.37e-07
Memory: 577.1 MB peak (ref: 769.04 MB, ratio: 0.7504x)
Kernel launches: 9 (ref: 31, fusion ratio: 3.4444)
Energy: 965.86 mJ/run (ref: 965.66 mJ, ratio: 0.9998x)
SOL score: 1.0
final submitted kernel (91 lines, 3,351 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 forward_cuda(torch::Tensor x, torch::Tensor w1, torch::Tensor b1, torch::Tensor w2, torch::Tensor b2);
'''
cuda_src = r'''
#include <torch/extension.h>
#include <ATen/cuda/CUDAContext.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <cmath>
__global__ void sigmoid_inplace_kernel(float* __restrict__ data, int64_t n) {
int64_t idx = (int64_t)blockIdx.x * blockDim.x + threadIdx.x;
int64_t stride = (int64_t)blockDim.x * gridDim.x;
for (int64_t i = idx; i < n; i += stride) {
float v = data[i];
data[i] = 1.0f / (1.0f + expf(-v));
}
}
__inline__ __device__ float warp_reduce_max(float v) {
for (int offset = 16; offset > 0; offset >>= 1) v = fmaxf(v, __shfl_down_sync(0xffffffff, v, offset));
return v;
}
__inline__ __device__ float warp_reduce_sum(float v) {
for (int offset = 16; offset > 0; offset >>= 1) v += __shfl_down_sync(0xffffffff, v, offset);
return v;
}
__global__ void logsumexp_kernel(const float* __restrict__ input, float* __restrict__ output, int rows, int cols) {
int row = blockIdx.x;
int tid = threadIdx.x;
const float* rowptr = input + (int64_t)row * cols;
__shared__ float smem[32];
int lane = tid & 31;
int warp = tid >> 5;
float m = -INFINITY;
for (int c = tid; c < cols; c += blockDim.x) m = fmaxf(m, rowptr[c]);
m = warp_reduce_max(m);
if (lane == 0) smem[warp] = m;
__syncthreads();
float bm = -INFINITY;
if (tid < (blockDim.x >> 5)) bm = smem[tid];
bm = warp_reduce_max(bm);
if (tid == 0) smem[0] = bm;
__syncthreads();
bm = smem[0];
float s = 0.0f;
for (int c = tid; c < cols; c += blockDim.x) s += expf(rowptr[c] - bm);
s = warp_reduce_sum(s);
if (lane == 0) smem[warp] = s;
__syncthreads();
float bs = 0.0f;
if (tid < (blockDim.x >> 5)) bs = smem[tid];
bs = warp_reduce_sum(bs);
if (tid == 0) output[row] = logf(bs) + bm;
}
torch::Tensor forward_cuda(torch::Tensor x, torch::Tensor w1, torch::Tensor b1, torch::Tensor w2, torch::Tensor b2) {
auto h = at::addmm(b1, x, w1.t());
int64_t hn = h.numel();
cudaStream_t stream = at::cuda::getCurrentCUDAStream();
int threads = 256;
int blocks = (int)std::min<int64_t>((hn + threads - 1) / threads, 65535);
sigmoid_inplace_kernel<<<blocks, threads, 0, stream>>>(h.data_ptr<float>(), hn);
auto y = at::addmm(b2, h, w2.t());
auto out = torch::empty({y.size(0)}, y.options());
logsumexp_kernel<<<(int)y.size(0), 256, 0, stream>>>(y.data_ptr<float>(), out.data_ptr<float>(), (int)y.size(0), (int)y.size(1));
return out;
}
'''
_ext = load_inline(name='gemm_sigmoid_gemm_lse_ext_final', cpp_sources=cpp_src, cuda_sources=cuda_src,
functions=['forward_cuda'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)
class ModelNew(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(ModelNew, self).__init__()
self.linear1 = nn.Linear(input_size, hidden_size)
self.linear2 = nn.Linear(hidden_size, output_size)
def forward(self, x):
return _ext.forward_cuda(x, self.linear1.weight, self.linear1.bias, self.linear2.weight, self.linear2.bias)