gpt-5.5-priority · original · l123_single_gpt
correct 10_3D_tensor_matrix_multiplication.py
model
gpt-5.5-priority
turns / max
1 / 1
tool calls
1
tokens (total)
0
wall clock
—
truncated
no
backend
cuda fp32
variant
original
runtime
1.04 μs
ref runtime
1.04 μs
speedup
1.00x
started
2026-05-05T02:29:25Z
timingkernelbench.timing
kernel runtime
1.04 μs
ref runtime
1.04 μs
speedup
1.00x
kernel mean / median / std
1.04 / — / 8.59e-04 μs
ref mean / median / std
1.04 / — / 7.67e-04 μ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
215.00 MB
ref peak
215.00 MB
kernel / ref
1.00x
kernel launches / fusiontorch.profiler
kernel launches
1
ref launches
5
fusion ratio (ref / kernel)
5.00x
total cuda time
23 μs
SOL (speed-of-light)nsight_hardware_counters
SOL score (0–1)
0.772
dram util %
12.9%
compute util %
77.2%
bottleneck
compute-bound
dominant pipe
FP32
arithmetic intensity
—
ridge point
20.00
roofline / occupancynsight_hardware_counters
dram bandwidth
431.23 GB/s
dram util %
12.9%
fp32 tflops
—
fp32 util %
—
fp16 tflops
—
occupancy %
12.5%
bottleneck
compute-bound
dominant pipe %
77.2%
arithmetic intensity
—
ridge point
20.00
L1 hit %
—
L2 hit %
78.5%
ld sectors / req
4.00
st sectors / req
—
regs / thread
254
smem / block
68608 B
block size
256
peak bw
3350.00 GB/s
peak fp32 tflops
67.00
peak fp16 tflops
1979.00
warp stalls (top 5)nsight
short_scoreboard
20.4%
long_scoreboard
4.7%
mio_throttle
0.3%
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn

class Model(nn.Module):
    """
    Performs 3D tensor-matrix multiplication.
    """
    def __init__(self):
        super(Model, self).__init__()
    
    def forward(self, A, B):
        """
        Performs 3D tensor-matrix multiplication.

        Args:
            A (torch.Tensor): Input 3D tensor of shape (N, M, K).
            B (torch.Tensor): Input matrix of shape (K, L).

        Returns:
            torch.Tensor: Output tensor of shape (N, M, L), resulting from the multiplication of A and B along the last dimension of A.
        """
        return torch.matmul(A, B)

N = 16
M = 1024
K = 2048
L = 768

def get_inputs():
    A = torch.rand(N, M, K)
    B = torch.rand(K, L)
    return [A, B]

def get_init_inputs():
    return []  # No special initialization inputs needed
turn 039.8s turn · 39.8s LLM · 0.0s tools · FINAL
reasoning
**Evaluating TF32 settings** I'm looking into reference tolerances and noticing that the TF32 error seems too high, which might indicate it's disabled. In PyTorch, I found that the default allows TF32 but matmul may have a modern default that's set to false. I need to make sure the math mode is controlled properly and set to CUBLAS_DEFAULT_MATH to avoid TF32. I wonder if setting a global handle could impact results. Ultimately, it's crucial to ensure the evaluation aligns with the reference outputs for accuracy. **Considering cublas settings** It might be that the settings are similar but perhaps slightly faster. I’m wondering about the timing and whether there’s overhead with setting the cublas math mode for every call. Maybe it’s better to configure it just once instead of every single time? I could call cublasSetMathMode for each small call, but I need to think about PyTorch's handling of this—like if it defaults to not using TF32 for correctness. **Considering cublas options** I’m thinking about using `cublasGemmEx` with the `CUBLAS_GEMM_DEFAULT` algorithm. I wonder if `cublasSgemm` would also work. There's the option to utilize split-K as well for optimization. I’m a bit concerned about potential correctness issues since `cublas` can be non-deterministic, and I want to keep the precision within 1e-4. It looks like I’m ready to submit this approach!
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 matmul3d_forward(torch::Tensor A, torch::Tensor B);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAGuard.h>\n#include <cublas_v2.h>\n\nstatic inline void check_cublas_status(cublasStatus_t status) {\n TORCH_CHECK(status == CUBLAS_STATUS_SUCCESS, \"cuBLAS call failed\");\n}\n\ntorch::Tensor matmul3d_forward(torch::Tensor A, torch::Tensor B) {\n c10::cuda::CUDAGuard device_guard(A.device());\n\n const int64_t N = A.size(0);\n const int64_t M = A.size(1);\n const int64_t K = A.size(2);\n const int64_t L = B.size(1);\n const int64_t rows = N * M;\n\n auto C = torch::empty({N, M, L}, A.options());\n\n // Row-major C[rows,L] = A[rows,K] @ B[K,L].\n // Interpreting the same buffers as column-major gives:\n // C_col[L,rows] = B_col[L,K] * A_col[K,rows]\n // which is exactly the transpose view of the desired row-major result.\n const float alpha = 1.0f;\n const float beta = 0.0f;\n\n cublasHandle_t handle = at::cuda::getCurrentCUDABlasHandle();\n auto stream = at::cuda::getCurrentCUDAStream();\n check_cublas_status(cublasSetStream(handle, stream.stream()));\n\n check_cublas_status(cublasSgemm(\n handle,\n CUBLAS_OP_N, CUBLAS_OP_N,\n static_cast<int>(L), static_cast<int>(rows), static_cast<int>(K),\n &alpha,\n B.data_ptr<float>(), static_cast<int>(L),\n A.data_ptr<float>(), static_cast<int>(K),\n &beta,\n C.data_ptr<float>(), static_cast<int>(L)\n ));\n\n return C;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"matmul3d_cublas_ext\",\n cpp_sources=[_cpp_src],\n cuda_sources=[_cuda_src],\n functions=[\"matmul3d_forward\"],\n extra_cflags=[\"-O3\"],\n extra_cuda_cflags=[\"-O3\"],\n extra_ldflags=[\"-lcublas\"],\n with_cuda=True,\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super(ModelNew, self).__init__()\n\n def forward(self, A, B):\n return _ext.matmul3d_forward(A, B)\n" }
result ← submit_kernel (ok)
oksubmit_kernel submit_kernel PASSED: (5 / 5) correctness trials all passed. Kernel runtime: 1.04 μs Runtime stats: mean=1.04μ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: 215.0 MB peak (ref: 215.0 MB, ratio: 1.0x) Kernel launches: 1 (ref: 5, fusion ratio: 5.0) SOL score: 0.7721
final submitted kernel (76 lines, 2,112 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 matmul3d_forward(torch::Tensor A, torch::Tensor B);
"""

_cuda_src = r"""
#include <torch/extension.h>
#include <ATen/cuda/CUDAContext.h>
#include <c10/cuda/CUDAGuard.h>
#include <cublas_v2.h>

static inline void check_cublas_status(cublasStatus_t status) {
    TORCH_CHECK(status == CUBLAS_STATUS_SUCCESS, "cuBLAS call failed");
}

torch::Tensor matmul3d_forward(torch::Tensor A, torch::Tensor B) {
    c10::cuda::CUDAGuard device_guard(A.device());

    const int64_t N = A.size(0);
    const int64_t M = A.size(1);
    const int64_t K = A.size(2);
    const int64_t L = B.size(1);
    const int64_t rows = N * M;

    auto C = torch::empty({N, M, L}, A.options());

    // Row-major C[rows,L] = A[rows,K] @ B[K,L].
    // Interpreting the same buffers as column-major gives:
    //   C_col[L,rows] = B_col[L,K] * A_col[K,rows]
    // which is exactly the transpose view of the desired row-major result.
    const float alpha = 1.0f;
    const float beta  = 0.0f;

    cublasHandle_t handle = at::cuda::getCurrentCUDABlasHandle();
    auto stream = at::cuda::getCurrentCUDAStream();
    check_cublas_status(cublasSetStream(handle, stream.stream()));

    check_cublas_status(cublasSgemm(
        handle,
        CUBLAS_OP_N, CUBLAS_OP_N,
        static_cast<int>(L), static_cast<int>(rows), static_cast<int>(K),
        &alpha,
        B.data_ptr<float>(), static_cast<int>(L),
        A.data_ptr<float>(), static_cast<int>(K),
        &beta,
        C.data_ptr<float>(), static_cast<int>(L)
    ));

    return C;
}
"""

_ext = load_inline(
    name="matmul3d_cublas_ext",
    cpp_sources=[_cpp_src],
    cuda_sources=[_cuda_src],
    functions=["matmul3d_forward"],
    extra_cflags=["-O3"],
    extra_cuda_cflags=["-O3"],
    extra_ldflags=["-lcublas"],
    with_cuda=True,
    verbose=False,
)

class ModelNew(nn.Module):
    def __init__(self):
        super(ModelNew, self).__init__()

    def forward(self, A, B):
        return _ext.matmul3d_forward(A, B)