gpt-5.5-priority · popcorn · l123_single_gpt
incorrect 20_RotaryPositionEmbeddingBio.py
model
gpt-5.5-priority
turns / max
1 / 1
tool calls
1
tokens (total)
0
wall clock
—
truncated
no
backend
cuda fp32
variant
popcorn
runtime
—
ref runtime
0.10 μs
speedup
—
started
2026-05-05T00:03:45Z
correctness issue: Output mismatch
timingkernelbench.timing
kernel runtime
—
ref runtime
0.10 μs
speedup
—
kernel mean / median / std
—
ref mean / median / std
0.10 / — / 0.01 μs
SOL (speed-of-light)nsight_hardware_counters
SOL score (0–1)
0.225
dram util %
22.5%
compute util %
11.9%
bottleneck
memory-bound
dominant pipe
FP32
arithmetic intensity
—
ridge point
20.00
roofline / occupancynsight_hardware_counters
dram bandwidth
754.57 GB/s
dram util %
22.5%
fp32 tflops
—
fp32 util %
—
fp16 tflops
—
occupancy %
68.1%
bottleneck
memory-bound
dominant pipe %
11.9%
arithmetic intensity
—
ridge point
20.00
L1 hit %
—
L2 hit %
56.3%
ld sectors / req
4.00
st sectors / req
—
regs / thread
22
smem / block
1024 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
long_scoreboard
1226.0%
mio_throttle
386.0%
short_scoreboard
198.0%
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn
import math


class Model(nn.Module):
    """
    Rotary Position Embedding (RoPE) applied to protein residue sequences.
    Used in ESM-2 and similar protein language models.  Encodes absolute
    position via rotation of query/key pairs in 2-D subspaces, preserving
    relative-position information in dot-product attention.
    """

    def __init__(self, dim, max_seq_len=2048, base=10000.0):
        super().__init__()
        inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))
        self.register_buffer("inv_freq", inv_freq)
        self.max_seq_len = max_seq_len
        self.dim = dim

    def _build_cos_sin(self, seq_len: int, device: torch.device):
        t = torch.arange(seq_len, device=device, dtype=self.inv_freq.dtype)
        freqs = torch.outer(t, self.inv_freq)
        emb = torch.cat([freqs, freqs], dim=-1)
        return emb.cos(), emb.sin()

    @staticmethod
    def _rotate_half(x: torch.Tensor) -> torch.Tensor:
        x1, x2 = x.chunk(2, dim=-1)
        return torch.cat([-x2, x1], dim=-1)

    def forward(self, q: torch.Tensor, k: torch.Tensor) -> tuple:
        """
        Args:
            q: (B, H, N, D)  – queries
            k: (B, H, N, D)  – keys
        Returns:
            (q_rot, k_rot) each (B, H, N, D) with RoPE applied
        """
        N = q.shape[2]
        cos, sin = self._build_cos_sin(N, q.device)  # (N, D)
        cos = cos.unsqueeze(0).unsqueeze(0)
        sin = sin.unsqueeze(0).unsqueeze(0)
        q_rot = q * cos + self._rotate_half(q) * sin
        k_rot = k * cos + self._rotate_half(k) * sin
        return q_rot, k_rot


dim = 64
num_heads = 8
seq_len = 256
batch_size = 4


def get_inputs():
    p = popcorn_pri
    bs = p.jitter_int(batch_size)
    nh = p.jitter_int(num_heads)
    sl = p.jitter_int(seq_len)
    q = torch.randn(bs, nh, sl, dim)
    k = torch.randn(bs, nh, sl, dim)
    return [q, k]


def get_init_inputs():
    return [dim]
turn 0147.1s turn · 147.1s LLM · 0.0s tools · FINAL
reasoning
**Evaluating CUDA sources** I’m thinking about the host function definition in `cuda_sources`. If it’s only symbol linked, that could be alright, but I need to ensure that the declaration in `cpp_sources` is okay as well. It seems like autogenerated definitions need to have their declarations visible for proper access. There’s a lot to consider here about visibility and linking! I want to make sure everything is set up correctly.
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#include <vector>\n\nstd::vector<torch::Tensor> rope_forward(torch::Tensor q, torch::Tensor k, double base);\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#include <math.h>\n\n__global__ void rope_f32_kernel(const float* __restrict__ q,\n const float* __restrict__ k,\n float* __restrict__ qo,\n float* __restrict__ ko,\n long total_pairs,\n int Dhalf,\n int N,\n int D,\n float log_base_over_D) {\n long idx = (long)blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total_pairs) return;\n\n int j = (int)(idx % Dhalf);\n long t = idx / Dhalf;\n int n = (int)(t % N);\n long base_idx = (t / N) * (long)N * D + (long)n * D + j;\n\n // inv_freq[j] = exp(-(2*j/dim)*log(base)); angle = n * inv_freq[j]\n float invf = __expf(-((float)j) * log_base_over_D);\n float angle = (float)n * invf;\n float s, c;\n __sincosf(angle, &s, &c);\n\n long i1 = base_idx;\n long i2 = base_idx + Dhalf;\n\n float q1 = q[i1];\n float q2 = q[i2];\n float k1 = k[i1];\n float k2 = k[i2];\n\n qo[i1] = q1 * c - q2 * s;\n qo[i2] = q2 * c + q1 * s;\n ko[i1] = k1 * c - k2 * s;\n ko[i2] = k2 * c + k1 * s;\n}\n\nstd::vector<torch::Tensor> rope_forward(torch::Tensor q, torch::Tensor k, double base) {\n auto qo = torch::empty_like(q);\n auto ko = torch::empty_like(k);\n\n const int D = (int)q.size(3);\n const int Dhalf = D >> 1;\n const int N = (int)q.size(2);\n const long B = q.size(0);\n const long H = q.size(1);\n const long total_pairs = B * H * (long)N * Dhalf;\n\n if (total_pairs > 0) {\n const int threads = 256;\n const int blocks = (int)((total_pairs + threads - 1) / threads);\n float log_base_over_D = (float)(2.0 * log(base) / (double)D);\n rope_f32_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(\n q.data_ptr<float>(), k.data_ptr<float>(), qo.data_ptr<float>(), ko.data_ptr<float>(),\n total_pairs, Dhalf, N, D, log_base_over_D);\n }\n return {qo, ko};\n}\n'''\n\n_ext = load_inline(\n name='rope_inline_ext_fast_v1',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['rope_forward'],\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n extra_cflags=['-O3'],\n with_cuda=True,\n verbose=False,\n)\n\n\nclass ModelNew(nn.Module):\n def __init__(self, dim, max_seq_len=2048, base=10000.0):\n super().__init__()\n self.dim = dim\n self.max_seq_len = max_seq_len\n self.base = float(base)\n inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))\n self.register_buffer('inv_freq', inv_freq)\n\n def forward(self, q: torch.Tensor, k: torch.Tensor) -> tuple:\n out = _ext.rope_forward(q, k, self.base)\n return out[0], out[1]\n" }
result ← submit_kernel (fail)
failsubmit_kernel submit_kernel FAILED: correctness check did not pass ((2 / 5) trials). correctness_issue: Output mismatch max_difference: ['0.000121', '0.000127', '0.000113'] avg_difference: ['0.000002', '0.000002', '0.000002']
final submitted kernel (104 lines, 3,181 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>
#include <vector>

std::vector<torch::Tensor> rope_forward(torch::Tensor q, torch::Tensor k, double base);
'''

_cuda_src = r'''
#include <torch/extension.h>
#include <ATen/cuda/CUDAContext.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <vector>
#include <math.h>

__global__ void rope_f32_kernel(const float* __restrict__ q,
                                const float* __restrict__ k,
                                float* __restrict__ qo,
                                float* __restrict__ ko,
                                long total_pairs,
                                int Dhalf,
                                int N,
                                int D,
                                float log_base_over_D) {
    long idx = (long)blockIdx.x * blockDim.x + threadIdx.x;
    if (idx >= total_pairs) return;

    int j = (int)(idx % Dhalf);
    long t = idx / Dhalf;
    int n = (int)(t % N);
    long base_idx = (t / N) * (long)N * D + (long)n * D + j;

    // inv_freq[j] = exp(-(2*j/dim)*log(base));  angle = n * inv_freq[j]
    float invf = __expf(-((float)j) * log_base_over_D);
    float angle = (float)n * invf;
    float s, c;
    __sincosf(angle, &s, &c);

    long i1 = base_idx;
    long i2 = base_idx + Dhalf;

    float q1 = q[i1];
    float q2 = q[i2];
    float k1 = k[i1];
    float k2 = k[i2];

    qo[i1] = q1 * c - q2 * s;
    qo[i2] = q2 * c + q1 * s;
    ko[i1] = k1 * c - k2 * s;
    ko[i2] = k2 * c + k1 * s;
}

std::vector<torch::Tensor> rope_forward(torch::Tensor q, torch::Tensor k, double base) {
    auto qo = torch::empty_like(q);
    auto ko = torch::empty_like(k);

    const int D = (int)q.size(3);
    const int Dhalf = D >> 1;
    const int N = (int)q.size(2);
    const long B = q.size(0);
    const long H = q.size(1);
    const long total_pairs = B * H * (long)N * Dhalf;

    if (total_pairs > 0) {
        const int threads = 256;
        const int blocks = (int)((total_pairs + threads - 1) / threads);
        float log_base_over_D = (float)(2.0 * log(base) / (double)D);
        rope_f32_kernel<<<blocks, threads, 0, at::cuda::getCurrentCUDAStream()>>>(
            q.data_ptr<float>(), k.data_ptr<float>(), qo.data_ptr<float>(), ko.data_ptr<float>(),
            total_pairs, Dhalf, N, D, log_base_over_D);
    }
    return {qo, ko};
}
'''

_ext = load_inline(
    name='rope_inline_ext_fast_v1',
    cpp_sources=_cpp_src,
    cuda_sources=_cuda_src,
    functions=['rope_forward'],
    extra_cuda_cflags=['-O3', '--use_fast_math'],
    extra_cflags=['-O3'],
    with_cuda=True,
    verbose=False,
)


class ModelNew(nn.Module):
    def __init__(self, dim, max_seq_len=2048, base=10000.0):
        super().__init__()
        self.dim = dim
        self.max_seq_len = max_seq_len
        self.base = float(base)
        inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))
        self.register_buffer('inv_freq', inv_freq)

    def forward(self, q: torch.Tensor, k: torch.Tensor) -> tuple:
        out = _ext.rope_forward(q, k, self.base)
        return out[0], out[1]