grok-4.3 · popcorn · pop_l123_st_gpt
compile_fail 13_QuantVLA_SelectiveLayoutFusion.py
model
grok-4.3
turns / max
1 / 1
tool calls
1
tokens (total)
3518
wall clock
14.5s
truncated
no
backend
cuda fp32
variant
popcorn
runtime
—
ref runtime
-1.00 μs
speedup
—
started
2026-05-11T09:49:48Z
compile error: Syntax error in custom generated code or ModelNew not found
timingkernelbench.timing
kernel runtime
—
ref runtime
—
speedup
—
kernel mean / median / std
—
ref mean / median / std
—
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn

# Default ModelNew is PyTorch-only. run_and_check: use check_kernel=False with backend=cuda
# until the candidate file contains a real CUDA kernel (see kernel_static_checker).


def _fake_quant_symmetric_int8(x: torch.Tensor, scale: torch.Tensor) -> torch.Tensor:
    """Symmetric int8 fake-quant: round(x/scale) clamped to [-127, 127], times scale."""
    q = torch.clamp(torch.round(x / scale), -127.0, 127.0)
    return q * scale


class Model(nn.Module):
    """
    **QuantVLA selective layout fusion** (reference target for a fused CUDA/Triton kernel).

    Vision–language–action stacks often use **token-wise mixed precision**: some
    timesteps or modalities tolerate aggressive quantization while others stay in
    full precision. This module fuses in **one forward**:

      1. **Layout routing** — ``sigmoid(layout_logits)`` yields a per-token mix
         coefficient in ``(0, 1)`` (quant vs FP residual).
      2. **Quantitative path** — global symmetric **int8-style fake quantization**
         (scale from the tensor max, ``/ 127``).
      3. **Selective blend** — ``α · x_quant + (1 - α) · x``.
      4. **Head** — linear projection on the mixed activations.

    This matches a “quantitative selective layout” block: the layout logits (from a
    router, modality tags, or calibration) choose how strongly each position uses the
    quantized layout vs the identity layout.
    """

    def __init__(self, dim: int):
        super().__init__()
        self.dim = dim
        self.out_proj = nn.Linear(dim, dim, bias=True)

    def forward(self, x: torch.Tensor, layout_logits: torch.Tensor) -> torch.Tensor:
        """
        Args:
            x: (B, T, D) VLA token activations (fused modalities).
            layout_logits: (B, T) unbounded logits; larger → more mass on quantized path.
        Returns:
            (B, T, D) updated activations.
        """
        B, T, D = x.shape
        assert D == self.dim
        assert layout_logits.shape == (B, T)

        alpha = torch.sigmoid(layout_logits).unsqueeze(-1)
        with torch.no_grad():
            amax = x.detach().abs().max().clamp(min=1e-8)
        scale = amax / 127.0
        x_q = _fake_quant_symmetric_int8(x, scale)
        mixed = alpha * x_q + (1.0 - alpha) * x
        return self.out_proj(mixed)


class ModelNew(nn.Module):
    """KernelBench candidate entry point; default delegates to ``Model``."""

    def __init__(self, dim: int):
        super().__init__()
        self._impl = Model(dim)

    def forward(self, x: torch.Tensor, layout_logits: torch.Tensor) -> torch.Tensor:
        return self._impl(x, layout_logits)


batch_size = 8
seq_len = 64
dim = 128


def get_inputs():
    p = popcorn_pri
    x = torch.randn(p.jitter_int(batch_size), p.jitter_int(seq_len), dim)
    layout_logits = torch.randn(p.jitter_int(batch_size), p.jitter_int(seq_len))
    return [x, layout_logits]


def get_init_inputs():
    return [dim]
turn 0 · FINAL · 1 tool call(s) · 14.5s turn · 14.5s LLM · tokens in=1,588 · out=1,350 · total=3,518 · 6,897 chars (click to expand)
turn 014.5s turn · 14.5s LLM · 0.0s tools · tokens in=1,588 · out=1,350 · total=3,518 · FINAL
reasoning
The task is to replace the forward computation of the PyTorch model with a custom CUDA kernel. The ModelNew class must match the constructor and forward signature, produce equivalent outputs, and run ...I need to implement a custom CUDA kernel for the forward pass of a PyTorch model, replacing the existing computation with a faster version. The ModelNew class should match the original constructor and forward signature, produce equivalent outputs, and run faster.
assistant```python import torch import torch.nn as nn from torch.utils.cpp_extension import load_inline cuda_source = ''' #include <torch/extension.h> #include <cuda.h> #include <cuda_runtime.h> #include <cmath> __global__ void compute_mixed_kernel(const float* __restrict__ x, const float* __restrict__ logits, float* __restrict__ mixed, int B, int T, int D, float scale) { int idx = blockIdx.x * blockDim.x + threadIdx.x; int total_tokens = B * T; if (idx >= total_tokens) return; float alpha = 1.0f / (1.0f + __expf(-logits[idx])); float one_minus_alpha = 1.0f - alpha; const float* x_row = x + idx * D; float* mixed_row = mixed + idx * D; for (int d = 0; d < D; d++) { float val = x_row[d]; float q = roundf(val / scale); q = fmaxf(fminf(q, 127.0f), -127.0f); float xq = q * scale; mixed_row[d] = alpha * xq + one_minus_alpha * val; } } torch::Tensor compute_mixed_cuda(torch::Tensor x, torch::Tensor logits, float scale) { auto B = x.size(0); auto T = x.size(1); auto D = x.size(2); auto mixed = torch::empty_like(x); int total_tokens = B * T; int threads = 256; int blocks = (total_tokens + threads - 1) / threads; compute_mixed_kernel<<<blocks, threads>>>( x.data_ptr<float>(), logits.data_ptr<float>(), mixed.data_ptr<float>(), B, T, D, scale ); return mixed; } ''' cpp_source = ''' torch::Tensor compute_mixed_cuda(torch::Tensor x, torch::Tensor logits, float scale); ''' # Compile the extension custom_ops = load_inline( name='custom_mixed_op', cpp_sources=cpp_source, cuda_sources=cuda_source, functions=['compute_mixed_cuda'], verbose=False, extra_cuda_cflags=['-O3'] ) class ModelNew(nn.Module): def __init__(self, dim: int): super().__init__() self.dim = dim self.out_proj = nn.Linear(dim, dim, bias=True) def forward(self, x: torch.Tensor, layout_logits: torch.Tensor) -> torch.Tensor: B, T, D = x.shape assert D == self.dim assert layout_logits.shape == (B, T) with torch.no_grad(): amax = x.detach().abs().max().clamp(min=1e-8) scale = amax / 127.0 mixed = custom_ops.compute_mixed_cuda(x, layout_logits, scale.item()) return self.out_proj(mixed) ``` The kernel is submitted. It fuses the sigmoid, fake-quant, and mixing into a single CUDA kernel, followed by the standard linear projection. This should be numerically equivalent and faster due to reduced memory traffic and kernel launch overhead for the custom operations.
call → submit_kernel
callsubmit_kernel { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = '''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cmath>\n\n__global__ void compute_mixed_kernel(const float* __restrict__ x,\n const float* __restrict__ logits,\n float* __restrict__ mixed,\n int B, int T, int D, float scale) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total_tokens = B * T;\n if (idx >= total_tokens) return;\n\n float alpha = 1.0f / (1.0f + __expf(-logits[idx]));\n float one_minus_alpha = 1.0f - alpha;\n const float* x_row = x + idx * D;\n float* mixed_row = mixed + idx * D;\n\n for (int d = 0; d < D; d++) {\n float val = x_row[d];\n float q = roundf(val / scale);\n q = fmaxf(fminf(q, 127.0f), -127.0f);\n float xq = q * scale;\n mixed_row[d] = alpha * xq + one_minus_alpha * val;\n }\n}\n\ntorch::Tensor compute_mixed_cuda(torch::Tensor x, torch::Tensor logits, float scale) {\n auto B = x.size(0);\n auto T = x.size(1);\n auto D = x.size(2);\n auto mixed = torch::empty_like(x);\n\n int total_tokens = B * T;\n int threads = 256;\n int blocks = (total_tokens + threads - 1) / threads;\n\n compute_mixed_kernel<<<blocks, threads>>>(\n x.data_ptr<float>(),\n logits.data_ptr<float>(),\n mixed.data_ptr<float>(),\n B, T, D, scale\n );\n\n return mixed;\n}\n'''\n\ncpp_source = '''\ntorch::Tensor compute_mixed_cuda(torch::Tensor x, torch::Tensor logits, float scale);\n'''\n\n# Compile the extension\ncustom_ops = load_inline(\n name='custom_mixed_op',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['compute_mixed_cuda'],\n verbose=False,\n extra_cuda_cflags=['-O3']\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, dim: int):\n super().__init__()\n self.dim = dim\n self.out_proj = nn.Linear(dim, dim, bias=True)\n\n def forward(self, x: torch.Tensor, layout_logits: torch.Tensor) -> torch.Tensor:\n B, T, D = x.shape\n assert D == self.dim\n assert layout_logits.shape == (B, T)\n\n with torch.no_grad():\n amax = x.detach().abs().max().clamp(min=1e-8)\n scale = amax / 127.0\n\n mixed = custom_ops.compute_mixed_cuda(x, layout_logits, scale.item())\n return self.out_proj(mixed)\n```" }
result ← submit_kernel (fail)
failsubmit_kernel submit_kernel FAILED: kernel did not compile. Syntax error in custom generated code or ModelNew not found
final submitted kernel (85 lines, 2,445 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline

cuda_source = '''
#include <torch/extension.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <cmath>

__global__ void compute_mixed_kernel(const float* __restrict__ x,
                                     const float* __restrict__ logits,
                                     float* __restrict__ mixed,
                                     int B, int T, int D, float scale) {
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    int total_tokens = B * T;
    if (idx >= total_tokens) return;

    float alpha = 1.0f / (1.0f + __expf(-logits[idx]));
    float one_minus_alpha = 1.0f - alpha;
    const float* x_row = x + idx * D;
    float* mixed_row = mixed + idx * D;

    for (int d = 0; d < D; d++) {
        float val = x_row[d];
        float q = roundf(val / scale);
        q = fmaxf(fminf(q, 127.0f), -127.0f);
        float xq = q * scale;
        mixed_row[d] = alpha * xq + one_minus_alpha * val;
    }
}

torch::Tensor compute_mixed_cuda(torch::Tensor x, torch::Tensor logits, float scale) {
    auto B = x.size(0);
    auto T = x.size(1);
    auto D = x.size(2);
    auto mixed = torch::empty_like(x);

    int total_tokens = B * T;
    int threads = 256;
    int blocks = (total_tokens + threads - 1) / threads;

    compute_mixed_kernel<<<blocks, threads>>>(
        x.data_ptr<float>(),
        logits.data_ptr<float>(),
        mixed.data_ptr<float>(),
        B, T, D, scale
    );

    return mixed;
}
'''

cpp_source = '''
torch::Tensor compute_mixed_cuda(torch::Tensor x, torch::Tensor logits, float scale);
'''

# Compile the extension
custom_ops = load_inline(
    name='custom_mixed_op',
    cpp_sources=cpp_source,
    cuda_sources=cuda_source,
    functions=['compute_mixed_cuda'],
    verbose=False,
    extra_cuda_cflags=['-O3']
)

class ModelNew(nn.Module):
    def __init__(self, dim: int):
        super().__init__()
        self.dim = dim
        self.out_proj = nn.Linear(dim, dim, bias=True)

    def forward(self, x: torch.Tensor, layout_logits: torch.Tensor) -> torch.Tensor:
        B, T, D = x.shape
        assert D == self.dim
        assert layout_logits.shape == (B, T)

        with torch.no_grad():
            amax = x.detach().abs().max().clamp(min=1e-8)
        scale = amax / 127.0

        mixed = custom_ops.compute_mixed_cuda(x, layout_logits, scale.item())
        return self.out_proj(mixed)
```