gpt-5.5-priority · original · l12_default_gpt
correct 12_Gemm_Multiply_LeakyReLU.py
model
gpt-5.5-priority
turns / max
10 / 10
tool calls
10
tokens (total)
0
wall clock
—
truncated
no
backend
cuda fp32
variant
original
runtime
2.78 μs
ref runtime
2.73 μs
speedup
0.98x
started
2026-05-02T20:47:39Z
timingkernelbench.timing
kernel runtime
2.78 μs
ref runtime
2.73 μs
speedup
0.98x
kernel mean / median / std
2.78 / — / 0.00 μs
ref mean / median / std
2.73 / — / 0.01 μs
numerical precisioneval_kernel_against_ref
max abs error
0.00
mean abs error
0.00
max rel error
0.00
mean rel error
0.00
gpu memoryextended_metrics.measure_memory
kernel peak
609.06 MB
ref peak
641.06 MB
kernel / ref
0.95x
kernel launches / fusiontorch.profiler
kernel launches
6
ref launches
7
fusion ratio (ref / kernel)
1.17x
total cuda time
2922 μs
energyNVML (pynvml)
kernel mJ / run
322.22
ref mJ / run
645.16
ratio (ref / kernel)
2.00x
avg power
115.80 W
ref avg power
236.35 W
SOL (speed-of-light)nsight_hardware_counters
SOL score (0–1)
1.000
dram util %
83.7%
compute util %
100.0%
bottleneck
compute-bound
dominant pipe
FP32
arithmetic intensity
—
ridge point
20.00
roofline / occupancynsight_hardware_counters
dram bandwidth
2803.74 GB/s
dram util %
83.7%
fp32 tflops
—
fp32 util %
—
fp16 tflops
—
occupancy %
121.3%
bottleneck
compute-bound
dominant pipe %
103.8%
arithmetic intensity
—
ridge point
20.00
L1 hit %
—
L2 hit %
243.5%
ld sectors / req
24.00
st sectors / req
—
regs / thread
301
smem / block
36352 B
block size
512
peak bw
3350.00 GB/s
peak fp32 tflops
67.00
peak fp16 tflops
1979.00
warp stalls (top 5)nsight
long_scoreboard
2720.8%
short_scoreboard
180.3%
mio_throttle
51.1%
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn

class Model(nn.Module):
    """
    Simple model that performs a Gemm, multiplies the result, and applies LeakyReLU.
    """
    def __init__(self, in_features, out_features, multiplier, negative_slope):
        super(Model, self).__init__()
        self.gemm = nn.Linear(in_features, out_features)
        self.multiplier = multiplier
        self.leaky_relu = nn.LeakyReLU(negative_slope)

    def forward(self, x):
        x = self.gemm(x)
        x = x * self.multiplier
        x = self.leaky_relu(x)
        return x

batch_size = 1024
in_features  = 8192  
out_features = 8192
multiplier = 2.0
negative_slope = 0.1

def get_inputs():
    return [torch.rand(batch_size, in_features)]

def get_init_inputs():
    return [in_features, out_features, multiplier, negative_slope]
turn 012.4s turn · 12.4s LLM · 0.0s tools
reasoning
**Developing a Python module** I need to craft a Python module and understand how eval instantiates ModelNew, particularly if it copies weights. Usually, we compare it to a reference with the same seed. I'm wondering if ModelNew should use the same constructor that includes nn.Linear and if I need to expose specific parameter names. The operation involves a large GEMM, and writing a custom matmul faster than PyTorch seems almost impossible. But could using a fused kernel with cuBLAS give us a slight edge? It seems I need a custom CUDA kernel for better performance. **Implementing CUDA kernel** I'm considering using torch.nn.functional.linear(x, w, b) combined with a custom CUDA kernel for multiply and leaky operations. This might help fuse two elementwise kernels, making it faster by reducing kernel count and memory passes. I wonder if the reference LeakyReLU being non-inplace affects performance. The GEMM part is significant, around 137 GFLOPs, while elementwise is minor. I might also implement an epilogue kernel and consider using a C++ wrapper for the extension. Maybe I can call at::matmul/addmm for additional simplification, but I need to verify how it all fits together. **Considering task requirements** The task specifies using a custom CUDA kernel, but it doesn’t explicitly prohibit using torch operations, which is something I’m considering. Speed might still be acceptable with torch operations, but I need to ensure that the constructor initializes in the same way as the Model and that there's compatibility with the state dictionary. It's essential to maintain consistency throughout the implementation while aligning with the task requirements. I’ll keep this in mind as I work through the details.
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 114.0s turn · 14.0s LLM · 0.0s tools
call → compile_kernel
callcompile_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 linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/ATen.h>\n#include <ATen/ops/linear.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda_runtime.h>\n\n__global__ void fused_mul_lrelu_kernel(float* __restrict__ y, long long n, float multiplier, float negative_slope) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n for (long long i = idx; i < n; i += stride) {\n float v = y[i] * multiplier;\n y[i] = (v > 0.0f) ? v : v * negative_slope;\n }\n}\n\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope) {\n auto y = at::linear(x, weight, bias);\n const long long n = y.numel();\n if (n > 0) {\n int threads = 256;\n int blocks = (int)((n + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n fused_mul_lrelu_kernel<<<blocks, threads, 0, stream>>>(y.data_ptr<float>(), n, (float)multiplier, (float)negative_slope);\n }\n return y;\n}\n'''\n\n_ext = load_inline(\n name='linear_act_ext_v1',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['linear_act'],\n extra_cflags=['-O3'],\n extra_cuda_cflags=['-O3'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, multiplier, negative_slope):\n super(ModelNew, self).__init__()\n self.gemm = nn.Linear(in_features, out_features)\n self.multiplier = float(multiplier)\n self.negative_slope = float(negative_slope)\n\n def forward(self, x):\n return _ext.linear_act(x, self.gemm.weight, self.gemm.bias, self.multiplier, self.negative_slope)\n" }
result ← compile_kernel (ok)
okcompile_kernel compile_kernel PASSED: kernel compiled without errors.
turn 24.5s turn · 4.5s 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\n_cpp_src = r'''\n#include <torch/extension.h>\n\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/ATen.h>\n#include <ATen/ops/linear.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda_runtime.h>\n\n__global__ void fused_mul_lrelu_kernel(float* __restrict__ y, long long n, float multiplier, float negative_slope) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n for (long long i = idx; i < n; i += stride) {\n float v = y[i] * multiplier;\n y[i] = (v > 0.0f) ? v : v * negative_slope;\n }\n}\n\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope) {\n auto y = at::linear(x, weight, bias);\n const long long n = y.numel();\n if (n > 0) {\n int threads = 256;\n int blocks = (int)((n + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n fused_mul_lrelu_kernel<<<blocks, threads, 0, stream>>>(y.data_ptr<float>(), n, (float)multiplier, (float)negative_slope);\n }\n return y;\n}\n'''\n\n_ext = load_inline(\n name='linear_act_ext_v1',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['linear_act'],\n extra_cflags=['-O3'],\n extra_cuda_cflags=['-O3'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, multiplier, negative_slope):\n super(ModelNew, self).__init__()\n self.gemm = nn.Linear(in_features, out_features)\n self.multiplier = float(multiplier)\n self.negative_slope = float(negative_slope)\n\n def forward(self, x):\n return _ext.linear_act(x, self.gemm.weight, self.gemm.bias, self.multiplier, self.negative_slope)\n" }
result ← run_correctness (ok)
okrun_correctness run_correctness PASSED: (5 / 5) trials all matched the reference. Numerical precision: max_abs_err=0.00e+00 mean_abs_err=0.00e+00 max_rel_err=0.00e+00
turn 311.1s turn · 11.1s LLM · 0.0s tools
reasoning
**Optimizing matrix operations** I need to look at optimizing matrix operations with potential strategies. I can submit the timing for the final result but might run a static check first. Maybe I can try cublasLt with a fused epilogue mul + leaky. While cuBLASLt supports bias and ReLU/GELU, it doesn’t support leaky relu nor multiplication directly. If I set alpha and beta for GEMM, I could combine them efficiently. Using PyTorch's addmm might help me achieve this without a separate multiply, saving time! **Exploring linear implementation** I'm considering how the at::linear implementation might utilize addmm with a beta value of 1. I need to use the transpose view for this. In C++, I can set it up like this: auto wt = weight.t(); then execute y= at::addmm(bias, x, wt, multiplier, multiplier). I'll also check if including ATen/ops/addmm.h avoids any overhead with at::linear. I should also test for correctness, especially when using a negative multiplier. And what about potential issues with broadcasting bias? I need to verify if it efficiently uses cublasLt bias. Let’s see how it works!
call → compile_kernel
callcompile_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>\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope);\n'''\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/ATen.h>\n#include <ATen/ops/addmm.h>\n#include <ATen/ops/t.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda_runtime.h>\n\n__global__ void lrelu_kernel(float* __restrict__ y, long long n, float negative_slope) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n for (long long i = idx; i < n; i += stride) {\n float v = y[i];\n y[i] = (v > 0.0f) ? v : v * negative_slope;\n }\n}\n\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope) {\n auto wt = weight.t();\n auto y = at::addmm(bias, x, wt, at::Scalar(multiplier), at::Scalar(multiplier));\n const long long n = y.numel();\n if (n > 0) {\n constexpr int threads = 256;\n int blocks = (int)((n + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n lrelu_kernel<<<blocks, threads, 0, stream>>>(y.data_ptr<float>(), n, (float)negative_slope);\n }\n return y;\n}\n'''\n_ext = load_inline(name='linear_act_ext_v2', cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=['linear_act'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, multiplier, negative_slope):\n super(ModelNew, self).__init__()\n self.gemm = nn.Linear(in_features, out_features)\n self.multiplier = float(multiplier)\n self.negative_slope = float(negative_slope)\n def forward(self, x):\n return _ext.linear_act(x, self.gemm.weight, self.gemm.bias, self.multiplier, self.negative_slope)\n" }
result ← compile_kernel (ok)
okcompile_kernel compile_kernel PASSED: kernel compiled without errors.
turn 44.4s turn · 4.4s 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\n_cpp_src = r'''\n#include <torch/extension.h>\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope);\n'''\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/ATen.h>\n#include <ATen/ops/addmm.h>\n#include <ATen/ops/t.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda_runtime.h>\n\n__global__ void lrelu_kernel(float* __restrict__ y, long long n, float negative_slope) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n for (long long i = idx; i < n; i += stride) {\n float v = y[i];\n y[i] = (v > 0.0f) ? v : v * negative_slope;\n }\n}\n\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope) {\n auto wt = weight.t();\n auto y = at::addmm(bias, x, wt, at::Scalar(multiplier), at::Scalar(multiplier));\n const long long n = y.numel();\n if (n > 0) {\n constexpr int threads = 256;\n int blocks = (int)((n + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n lrelu_kernel<<<blocks, threads, 0, stream>>>(y.data_ptr<float>(), n, (float)negative_slope);\n }\n return y;\n}\n'''\n_ext = load_inline(name='linear_act_ext_v2', cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=['linear_act'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, multiplier, negative_slope):\n super(ModelNew, self).__init__()\n self.gemm = nn.Linear(in_features, out_features)\n self.multiplier = float(multiplier)\n self.negative_slope = float(negative_slope)\n def forward(self, x):\n return _ext.linear_act(x, self.gemm.weight, self.gemm.bias, self.multiplier, self.negative_slope)\n" }
result ← run_correctness (ok)
okrun_correctness run_correctness PASSED: (5 / 5) trials all matched the reference. Numerical precision: max_abs_err=0.00e+00 mean_abs_err=0.00e+00 max_rel_err=0.00e+00
turn 522.0s turn · 22.0s 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\n_cpp_src = r'''\n#include <torch/extension.h>\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope);\n'''\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/ATen.h>\n#include <ATen/ops/addmm.h>\n#include <ATen/ops/t.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda_runtime.h>\n\n__device__ __forceinline__ float act(float v, float s) { return (v > 0.0f) ? v : v * s; }\n\n__global__ void lrelu_vec4_kernel(float* __restrict__ y, long long n, float s) {\n long long tid = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n long long n4 = n >> 2;\n float4* __restrict__ y4 = reinterpret_cast<float4*>(y);\n for (long long i = tid; i < n4; i += stride) {\n float4 v = y4[i];\n v.x = act(v.x, s); v.y = act(v.y, s); v.z = act(v.z, s); v.w = act(v.w, s);\n y4[i] = v;\n }\n // handle leftover elements if any\n for (long long i = (n4 << 2) + tid; i < n; i += stride) {\n float v = y[i];\n y[i] = act(v, s);\n }\n}\n\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope) {\n auto wt = weight.t();\n auto y = at::addmm(bias, x, wt, at::Scalar(multiplier), at::Scalar(multiplier));\n const long long n = y.numel();\n if (n > 0) {\n constexpr int threads = 256;\n int blocks = (int)(((n >> 2) + threads - 1) / threads);\n if (blocks < 1) blocks = 1;\n if (blocks > 65535) blocks = 65535;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n lrelu_vec4_kernel<<<blocks, threads, 0, stream>>>(y.data_ptr<float>(), n, (float)negative_slope);\n }\n return y;\n}\n'''\n_ext = load_inline(name='linear_act_ext_v3', cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=['linear_act'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, multiplier, negative_slope):\n super(ModelNew, self).__init__()\n self.gemm = nn.Linear(in_features, out_features)\n self.multiplier = float(multiplier)\n self.negative_slope = float(negative_slope)\n def forward(self, x):\n return _ext.linear_act(x, self.gemm.weight, self.gemm.bias, self.multiplier, self.negative_slope)\n" }
result ← run_correctness (ok)
okrun_correctness run_correctness PASSED: (5 / 5) trials all matched the reference. Numerical precision: max_abs_err=0.00e+00 mean_abs_err=0.00e+00 max_rel_err=0.00e+00
turn 6 · 1 tool call(s) · 34.2s turn · 34.2s LLM · 6,410 chars (click to expand)
turn 634.2s turn · 34.2s LLM · 0.0s tools
call → compile_kernel
callcompile_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>\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope);\n'''\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAException.h>\n#include <cuda_runtime.h>\n#include <cublasLt.h>\n#include <mutex>\n\n#define CUBLAS_CHECK(cmd) do { cublasStatus_t s = (cmd); if (s != CUBLAS_STATUS_SUCCESS) { TORCH_CHECK(false, \"cuBLASLt error: \", (int)s); } } while(0)\n\nstatic cublasLtHandle_t get_lt_handle() {\n static cublasLtHandle_t handle = nullptr;\n static std::once_flag flag;\n std::call_once(flag, [](){ CUBLAS_CHECK(cublasLtCreate(&handle)); });\n return handle;\n}\n\n__device__ __forceinline__ float lact(float v, float s) { return (v > 0.0f) ? v : v * s; }\n\n__global__ void add_bias_lrelu_vec4(float* __restrict__ y, const float* __restrict__ bias,\n long long n4, int N, float mult, float slope) {\n long long tid = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n const float4* __restrict__ b4 = reinterpret_cast<const float4*>(bias);\n float4* __restrict__ y4 = reinterpret_cast<float4*>(y);\n int N4 = N >> 2;\n for (long long i = tid; i < n4; i += stride) {\n float4 v = y4[i];\n float4 b = b4[(int)(i % N4)];\n v.x = lact(v.x + mult * b.x, slope);\n v.y = lact(v.y + mult * b.y, slope);\n v.z = lact(v.z + mult * b.z, slope);\n v.w = lact(v.w + mult * b.w, slope);\n y4[i] = v;\n }\n}\n\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope) {\n TORCH_CHECK(x.is_cuda() && weight.is_cuda() && bias.is_cuda(), \"CUDA tensors required\");\n TORCH_CHECK(x.scalar_type() == at::kFloat && weight.scalar_type() == at::kFloat && bias.scalar_type() == at::kFloat, \"float32 only\");\n const int64_t M64 = x.size(0), K64 = x.size(1), N64 = weight.size(0);\n auto y = torch::empty({M64, N64}, x.options());\n int M = (int)M64, K = (int)K64, N = (int)N64;\n\n cublasLtHandle_t handle = get_lt_handle();\n cublasLtMatmulDesc_t opDesc;\n cublasLtMatrixLayout_t aDesc, bDesc, cDesc;\n CUBLAS_CHECK(cublasLtMatmulDescCreate(&opDesc, CUBLAS_COMPUTE_32F, CUDA_R_32F));\n cublasOperation_t transa = CUBLAS_OP_T;\n cublasOperation_t transb = CUBLAS_OP_N;\n CUBLAS_CHECK(cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_TRANSA, &transa, sizeof(transa)));\n CUBLAS_CHECK(cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_TRANSB, &transb, sizeof(transb)));\n CUBLAS_CHECK(cublasLtMatrixLayoutCreate(&aDesc, CUDA_R_32F, K, N, K));\n CUBLAS_CHECK(cublasLtMatrixLayoutCreate(&bDesc, CUDA_R_32F, K, M, K));\n CUBLAS_CHECK(cublasLtMatrixLayoutCreate(&cDesc, CUDA_R_32F, N, M, N));\n\n float alpha = (float)multiplier;\n float beta = 0.0f;\n cublasLtMatmulPreference_t pref;\n CUBLAS_CHECK(cublasLtMatmulPreferenceCreate(&pref));\n size_t workspaceSize = 0;\n CUBLAS_CHECK(cublasLtMatmulPreferenceSetAttribute(pref, CUBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES, &workspaceSize, sizeof(workspaceSize)));\n cublasLtMatmulHeuristicResult_t heuristic;\n int returned = 0;\n CUBLAS_CHECK(cublasLtMatmulAlgoGetHeuristic(handle, opDesc, aDesc, bDesc, cDesc, cDesc, pref, 1, &heuristic, &returned));\n TORCH_CHECK(returned > 0, \"no cublasLt algo\");\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n CUBLAS_CHECK(cublasLtMatmul(handle, opDesc, &alpha,\n weight.data_ptr<float>(), aDesc,\n x.data_ptr<float>(), bDesc,\n &beta,\n y.data_ptr<float>(), cDesc,\n y.data_ptr<float>(), cDesc,\n &heuristic.algo, nullptr, 0, stream));\n CUBLAS_CHECK(cublasLtMatmulPreferenceDestroy(pref));\n CUBLAS_CHECK(cublasLtMatrixLayoutDestroy(aDesc));\n CUBLAS_CHECK(cublasLtMatrixLayoutDestroy(bDesc));\n CUBLAS_CHECK(cublasLtMatrixLayoutDestroy(cDesc));\n CUBLAS_CHECK(cublasLtMatmulDescDestroy(opDesc));\n\n long long n = y.numel();\n if (n > 0) {\n long long n4 = n >> 2;\n int threads = 256;\n int blocks = (int)((n4 + threads - 1) / threads);\n if (blocks < 1) blocks = 1;\n if (blocks > 65535) blocks = 65535;\n add_bias_lrelu_vec4<<<blocks, threads, 0, stream>>>(y.data_ptr<float>(), bias.data_ptr<float>(), n4, N, (float)multiplier, (float)negative_slope);\n }\n return y;\n}\n'''\n_ext = load_inline(name='linear_act_ext_lt1', cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=['linear_act'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], extra_ldflags=['-lcublasLt','-lcublas'], verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, multiplier, negative_slope):\n super(ModelNew, self).__init__()\n self.gemm = nn.Linear(in_features, out_features)\n self.multiplier = float(multiplier)\n self.negative_slope = float(negative_slope)\n def forward(self, x):\n return _ext.linear_act(x, self.gemm.weight, self.gemm.bias, self.multiplier, self.negative_slope)\n" }
result ← compile_kernel (ok)
okcompile_kernel compile_kernel PASSED: kernel compiled without errors.
turn 7 · 1 tool call(s) · 10.3s turn · 10.3s LLM · 6,512 chars (click to expand)
turn 710.3s turn · 10.3s 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\n_cpp_src = r'''\n#include <torch/extension.h>\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope);\n'''\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAException.h>\n#include <cuda_runtime.h>\n#include <cublasLt.h>\n#include <mutex>\n\n#define CUBLAS_CHECK(cmd) do { cublasStatus_t s = (cmd); if (s != CUBLAS_STATUS_SUCCESS) { TORCH_CHECK(false, \"cuBLASLt error: \", (int)s); } } while(0)\n\nstatic cublasLtHandle_t get_lt_handle() {\n static cublasLtHandle_t handle = nullptr;\n static std::once_flag flag;\n std::call_once(flag, [](){ CUBLAS_CHECK(cublasLtCreate(&handle)); });\n return handle;\n}\n\n__device__ __forceinline__ float lact(float v, float s) { return (v > 0.0f) ? v : v * s; }\n\n__global__ void add_bias_lrelu_vec4(float* __restrict__ y, const float* __restrict__ bias,\n long long n4, int N, float mult, float slope) {\n long long tid = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n const float4* __restrict__ b4 = reinterpret_cast<const float4*>(bias);\n float4* __restrict__ y4 = reinterpret_cast<float4*>(y);\n int N4 = N >> 2;\n for (long long i = tid; i < n4; i += stride) {\n float4 v = y4[i];\n float4 b = b4[(int)(i % N4)];\n v.x = lact(v.x + mult * b.x, slope);\n v.y = lact(v.y + mult * b.y, slope);\n v.z = lact(v.z + mult * b.z, slope);\n v.w = lact(v.w + mult * b.w, slope);\n y4[i] = v;\n }\n}\n\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope) {\n TORCH_CHECK(x.is_cuda() && weight.is_cuda() && bias.is_cuda(), \"CUDA tensors required\");\n TORCH_CHECK(x.scalar_type() == at::kFloat && weight.scalar_type() == at::kFloat && bias.scalar_type() == at::kFloat, \"float32 only\");\n const int64_t M64 = x.size(0), K64 = x.size(1), N64 = weight.size(0);\n auto y = torch::empty({M64, N64}, x.options());\n int M = (int)M64, K = (int)K64, N = (int)N64;\n\n cublasLtHandle_t handle = get_lt_handle();\n cublasLtMatmulDesc_t opDesc;\n cublasLtMatrixLayout_t aDesc, bDesc, cDesc;\n CUBLAS_CHECK(cublasLtMatmulDescCreate(&opDesc, CUBLAS_COMPUTE_32F, CUDA_R_32F));\n cublasOperation_t transa = CUBLAS_OP_T;\n cublasOperation_t transb = CUBLAS_OP_N;\n CUBLAS_CHECK(cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_TRANSA, &transa, sizeof(transa)));\n CUBLAS_CHECK(cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_TRANSB, &transb, sizeof(transb)));\n CUBLAS_CHECK(cublasLtMatrixLayoutCreate(&aDesc, CUDA_R_32F, K, N, K));\n CUBLAS_CHECK(cublasLtMatrixLayoutCreate(&bDesc, CUDA_R_32F, K, M, K));\n CUBLAS_CHECK(cublasLtMatrixLayoutCreate(&cDesc, CUDA_R_32F, N, M, N));\n\n float alpha = (float)multiplier;\n float beta = 0.0f;\n cublasLtMatmulPreference_t pref;\n CUBLAS_CHECK(cublasLtMatmulPreferenceCreate(&pref));\n size_t workspaceSize = 0;\n CUBLAS_CHECK(cublasLtMatmulPreferenceSetAttribute(pref, CUBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES, &workspaceSize, sizeof(workspaceSize)));\n cublasLtMatmulHeuristicResult_t heuristic;\n int returned = 0;\n CUBLAS_CHECK(cublasLtMatmulAlgoGetHeuristic(handle, opDesc, aDesc, bDesc, cDesc, cDesc, pref, 1, &heuristic, &returned));\n TORCH_CHECK(returned > 0, \"no cublasLt algo\");\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n CUBLAS_CHECK(cublasLtMatmul(handle, opDesc, &alpha,\n weight.data_ptr<float>(), aDesc,\n x.data_ptr<float>(), bDesc,\n &beta,\n y.data_ptr<float>(), cDesc,\n y.data_ptr<float>(), cDesc,\n &heuristic.algo, nullptr, 0, stream));\n CUBLAS_CHECK(cublasLtMatmulPreferenceDestroy(pref));\n CUBLAS_CHECK(cublasLtMatrixLayoutDestroy(aDesc));\n CUBLAS_CHECK(cublasLtMatrixLayoutDestroy(bDesc));\n CUBLAS_CHECK(cublasLtMatrixLayoutDestroy(cDesc));\n CUBLAS_CHECK(cublasLtMatmulDescDestroy(opDesc));\n\n long long n = y.numel();\n if (n > 0) {\n long long n4 = n >> 2;\n int threads = 256;\n int blocks = (int)((n4 + threads - 1) / threads);\n if (blocks < 1) blocks = 1;\n if (blocks > 65535) blocks = 65535;\n add_bias_lrelu_vec4<<<blocks, threads, 0, stream>>>(y.data_ptr<float>(), bias.data_ptr<float>(), n4, N, (float)multiplier, (float)negative_slope);\n }\n return y;\n}\n'''\n_ext = load_inline(name='linear_act_ext_lt1', cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=['linear_act'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], extra_ldflags=['-lcublasLt','-lcublas'], verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, multiplier, negative_slope):\n super(ModelNew, self).__init__()\n self.gemm = nn.Linear(in_features, out_features)\n self.multiplier = float(multiplier)\n self.negative_slope = float(negative_slope)\n def forward(self, x):\n return _ext.linear_act(x, self.gemm.weight, self.gemm.bias, self.multiplier, self.negative_slope)\n" }
result ← run_correctness (ok)
okrun_correctness run_correctness PASSED: (5 / 5) trials all matched the reference. Numerical precision: max_abs_err=0.00e+00 mean_abs_err=0.00e+00 max_rel_err=0.00e+00
turn 812.1s turn · 12.1s LLM · 0.0s tools
call → static_check
callstatic_check { "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>\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope);\n'''\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/ATen.h>\n#include <ATen/ops/addmm.h>\n#include <ATen/ops/t.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda_runtime.h>\n\n__device__ __forceinline__ float act(float v, float s) { return (v > 0.0f) ? v : v * s; }\n\n__global__ void lrelu_vec4_kernel(float* __restrict__ y, long long n, float s) {\n long long tid = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n long long n4 = n >> 2;\n float4* __restrict__ y4 = reinterpret_cast<float4*>(y);\n for (long long i = tid; i < n4; i += stride) {\n float4 v = y4[i];\n v.x = act(v.x, s); v.y = act(v.y, s); v.z = act(v.z, s); v.w = act(v.w, s);\n y4[i] = v;\n }\n for (long long i = (n4 << 2) + tid; i < n; i += stride) {\n float v = y[i];\n y[i] = act(v, s);\n }\n}\n\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope) {\n auto wt = weight.t();\n auto y = at::addmm(bias, x, wt, at::Scalar(multiplier), at::Scalar(multiplier));\n const long long n = y.numel();\n if (n > 0) {\n constexpr int threads = 256;\n int blocks = (int)(((n >> 2) + threads - 1) / threads);\n if (blocks < 1) blocks = 1;\n if (blocks > 65535) blocks = 65535;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n lrelu_vec4_kernel<<<blocks, threads, 0, stream>>>(y.data_ptr<float>(), n, (float)negative_slope);\n }\n return y;\n}\n'''\n_ext = load_inline(name='linear_act_ext_final', cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=['linear_act'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, multiplier, negative_slope):\n super(ModelNew, self).__init__()\n self.gemm = nn.Linear(in_features, out_features)\n self.multiplier = float(multiplier)\n self.negative_slope = float(negative_slope)\n def forward(self, x):\n return _ext.linear_act(x, self.gemm.weight, self.gemm.bias, self.multiplier, self.negative_slope)\n" }
result ← static_check (ok)
okstatic_check static_check PASSED: no violations or warnings detected.
turn 96.9s turn · 6.9s 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>\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/ATen.h>\n#include <ATen/ops/addmm.h>\n#include <ATen/ops/t.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda_runtime.h>\n\n__device__ __forceinline__ float act(float v, float s) {\n return (v > 0.0f) ? v : v * s;\n}\n\n__global__ void lrelu_vec4_kernel(float* __restrict__ y, long long n, float s) {\n long long tid = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n long long n4 = n >> 2;\n float4* __restrict__ y4 = reinterpret_cast<float4*>(y);\n\n for (long long i = tid; i < n4; i += stride) {\n float4 v = y4[i];\n v.x = act(v.x, s);\n v.y = act(v.y, s);\n v.z = act(v.z, s);\n v.w = act(v.w, s);\n y4[i] = v;\n }\n for (long long i = (n4 << 2) + tid; i < n; i += stride) {\n float v = y[i];\n y[i] = act(v, s);\n }\n}\n\ntorch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope) {\n auto wt = weight.t();\n // (x @ weight.T + bias) * multiplier == addmm(bias, x, weight.T, beta=multiplier, alpha=multiplier)\n auto y = at::addmm(bias, x, wt, at::Scalar(multiplier), at::Scalar(multiplier));\n\n const long long n = y.numel();\n if (n > 0) {\n constexpr int threads = 256;\n int blocks = (int)(((n >> 2) + threads - 1) / threads);\n if (blocks < 1) blocks = 1;\n if (blocks > 65535) blocks = 65535;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n lrelu_vec4_kernel<<<blocks, threads, 0, stream>>>(y.data_ptr<float>(), n, (float)negative_slope);\n }\n return y;\n}\n'''\n\n_ext = load_inline(\n name='linear_act_ext_submit',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['linear_act'],\n extra_cflags=['-O3'],\n extra_cuda_cflags=['-O3'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, multiplier, negative_slope):\n super(ModelNew, self).__init__()\n self.gemm = nn.Linear(in_features, out_features)\n self.multiplier = float(multiplier)\n self.negative_slope = float(negative_slope)\n\n def forward(self, x):\n return _ext.linear_act(x, self.gemm.weight, self.gemm.bias, self.multiplier, self.negative_slope)\n" }
result ← submit_kernel (ok)
oksubmit_kernel submit_kernel PASSED: (5 / 5) correctness trials all passed. Kernel runtime: 2.78 μs Runtime stats: mean=2.78μs median=?μs std=0.00μs Numerical precision: max_abs_err=0.00e+00 mean_abs_err=0.00e+00 max_rel_err=0.00e+00 Memory: 609.06 MB peak (ref: 641.06 MB, ratio: 0.9501x) Kernel launches: 6 (ref: 7, fusion ratio: 1.1667) Energy: 322.22 mJ/run (ref: 645.16 mJ, ratio: 2.0022x) SOL score: 1.0
final submitted kernel (79 lines, 2,595 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 linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope);
'''

_cuda_src = r'''
#include <torch/extension.h>
#include <ATen/ATen.h>
#include <ATen/ops/addmm.h>
#include <ATen/ops/t.h>
#include <ATen/cuda/CUDAContext.h>
#include <cuda_runtime.h>

__device__ __forceinline__ float act(float v, float s) {
    return (v > 0.0f) ? v : v * s;
}

__global__ void lrelu_vec4_kernel(float* __restrict__ y, long long n, float s) {
    long long tid = (long long)blockIdx.x * blockDim.x + threadIdx.x;
    long long stride = (long long)blockDim.x * gridDim.x;
    long long n4 = n >> 2;
    float4* __restrict__ y4 = reinterpret_cast<float4*>(y);

    for (long long i = tid; i < n4; i += stride) {
        float4 v = y4[i];
        v.x = act(v.x, s);
        v.y = act(v.y, s);
        v.z = act(v.z, s);
        v.w = act(v.w, s);
        y4[i] = v;
    }
    for (long long i = (n4 << 2) + tid; i < n; i += stride) {
        float v = y[i];
        y[i] = act(v, s);
    }
}

torch::Tensor linear_act(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double multiplier, double negative_slope) {
    auto wt = weight.t();
    // (x @ weight.T + bias) * multiplier  == addmm(bias, x, weight.T, beta=multiplier, alpha=multiplier)
    auto y = at::addmm(bias, x, wt, at::Scalar(multiplier), at::Scalar(multiplier));

    const long long n = y.numel();
    if (n > 0) {
        constexpr int threads = 256;
        int blocks = (int)(((n >> 2) + threads - 1) / threads);
        if (blocks < 1) blocks = 1;
        if (blocks > 65535) blocks = 65535;
        cudaStream_t stream = at::cuda::getCurrentCUDAStream();
        lrelu_vec4_kernel<<<blocks, threads, 0, stream>>>(y.data_ptr<float>(), n, (float)negative_slope);
    }
    return y;
}
'''

_ext = load_inline(
    name='linear_act_ext_submit',
    cpp_sources=_cpp_src,
    cuda_sources=_cuda_src,
    functions=['linear_act'],
    extra_cflags=['-O3'],
    extra_cuda_cflags=['-O3'],
    verbose=False,
)

class ModelNew(nn.Module):
    def __init__(self, in_features, out_features, multiplier, negative_slope):
        super(ModelNew, self).__init__()
        self.gemm = nn.Linear(in_features, out_features)
        self.multiplier = float(multiplier)
        self.negative_slope = float(negative_slope)

    def forward(self, x):
        return _ext.linear_act(x, self.gemm.weight, self.gemm.bias, self.multiplier, self.negative_slope)