gpt-5.5-priority · popcorn · l3_all_gpt
correct 4_MambaBlock.py
model
gpt-5.5-priority
turns / max
13 / 15
tool calls
13
tokens (total)
0
wall clock
—
truncated
no
backend
cuda fp32
variant
popcorn
runtime
3.83 μs
ref runtime
160.00 μs
speedup
41.78x
started
2026-05-04T17:00:45Z
timingkernelbench.timing
kernel runtime
3.83 μs
ref runtime
160.00 μs
speedup
41.78x
kernel mean / median / std
3.83 / — / 0.08 μs
ref mean / median / std
160.00 / — / 358.00 μs
numerical precisioneval_kernel_against_ref
max abs error
4.77e-07
mean abs error
2.12e-09
max rel error
0.16
mean rel error
3.20e-08
gpu memoryextended_metrics.measure_memory
kernel peak
522.22 MB
ref peak
3690.75 MB
kernel / ref
0.14x
kernel launches / fusiontorch.profiler
kernel launches
53
ref launches
26754
fusion ratio (ref / kernel)
504.79x
total cuda time
3817 μs
energyNVML (pynvml)
kernel mJ / run
2100.26
ref mJ / run
15288.64
ratio (ref / kernel)
7.28x
avg power
546.53 W
ref avg power
173.19 W
SOL (speed-of-light)nsight_hardware_counters
SOL score (0–1)
1.000
dram util %
100.0%
compute util %
100.0%
bottleneck
compute-bound
dominant pipe
FP32
arithmetic intensity
—
ridge point
20.00
roofline / occupancynsight_hardware_counters
dram bandwidth
12044.49 GB/s
dram util %
100.0%
fp32 tflops
—
fp32 util %
—
fp16 tflops
—
occupancy %
317.7%
bottleneck
compute-bound
dominant pipe %
362.8%
arithmetic intensity
—
ridge point
20.00
L1 hit %
—
L2 hit %
497.7%
ld sectors / req
64.35
st sectors / req
—
regs / thread
1183
smem / block
140800 B
block size
1216
peak bw
3350.00 GB/s
peak fp32 tflops
67.00
peak fp16 tflops
1979.00
warp stalls (top 5)nsight
long_scoreboard
23097.2%
short_scoreboard
2415.2%
mio_throttle
2254.5%
flagssubmit_kernel guard
excessive speedup
flagged
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn

class Model(nn.Module):
    """
    Full Mamba block: RMSNorm -> linear expansion into two branches -> causal depthwise Conv1d ->
    SiLU -> selective scan (input-dependent SSM) -> elementwise gate -> linear projection -> residual.
    This is the complete Mamba architecture block as described in Gu & Dao (2023), used in Mamba,
    Caduceus (bidirectional DNA), and various protein/genomic language models.

    Args:
        d_model (int): Model dimension.
        d_state (int): SSM state dimension (N).
        d_conv (int): Causal convolution kernel size.
        expand (int): Expansion factor for inner dimension.
    """
    def __init__(self, d_model: int, d_state: int, d_conv: int, expand: int):
        super(Model, self).__init__()
        self.d_model = d_model
        self.d_inner = d_model * expand
        self.d_state = d_state
        self.d_conv = d_conv

        self.norm = nn.RMSNorm(d_model)
        self.in_proj = nn.Linear(d_model, self.d_inner * 2, bias=False)
        self.conv1d = nn.Conv1d(self.d_inner, self.d_inner, d_conv,
                                padding=d_conv - 1, groups=self.d_inner, bias=True)
        self.activation = nn.SiLU()

        self.A_log = nn.Parameter(torch.randn(self.d_inner, d_state))
        self.proj_B = nn.Linear(self.d_inner, d_state, bias=False)
        self.proj_C = nn.Linear(self.d_inner, d_state, bias=False)
        self.proj_delta = nn.Linear(self.d_inner, self.d_inner, bias=True)
        self.D = nn.Parameter(torch.ones(self.d_inner))

        self.out_proj = nn.Linear(self.d_inner, d_model, bias=False)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        B, L, D = x.shape
        residual = x
        x = self.norm(x)

        xz = self.in_proj(x)
        x_branch, z = xz.chunk(2, dim=-1)

        x_branch = x_branch.transpose(1, 2)
        x_branch = self.conv1d(x_branch)[..., :L]
        x_branch = x_branch.transpose(1, 2)
        x_branch = self.activation(x_branch)

        N = self.d_state
        delta = torch.nn.functional.softplus(self.proj_delta(x_branch))
        B_t = self.proj_B(x_branch)
        C_t = self.proj_C(x_branch)

        A = -torch.exp(self.A_log)
        dA = torch.exp(delta.unsqueeze(-1) * A.unsqueeze(0).unsqueeze(0))
        dB = delta.unsqueeze(-1) * B_t.unsqueeze(2)
        x_db = x_branch.unsqueeze(-1) * dB

        h = torch.zeros(B, self.d_inner, N, device=x.device, dtype=x.dtype)
        outputs = []
        for t in range(L):
            h = dA[:, t] * h + x_db[:, t]
            y_t = (h * C_t[:, t].unsqueeze(1)).sum(dim=-1)
            outputs.append(y_t)
        y = torch.stack(outputs, dim=1)
        y = y + x_branch * self.D.unsqueeze(0).unsqueeze(0)

        z = self.activation(z)
        y = y * z
        y = self.out_proj(y)
        y = y + residual
        return y

batch_size = 16
d_model = 256
d_state = 16
d_conv = 4
expand = 2
seq_len = 2048

def get_inputs():
    return [torch.randn(popcorn_pri.jitter_int(batch_size), popcorn_pri.jitter_int(seq_len), d_model)]

def get_init_inputs():
    return [d_model, d_state, d_conv, expand]
turn 09.1s turn · 9.1s 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 1 · 1 tool call(s) · 38.5s turn · 38.5s LLM · 7,802 chars (click to expand)
turn 138.5s turn · 38.5s 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 = r'''\n#include <torch/extension.h>\n\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);\nvoid scan_launcher(torch::Tensor xb, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);\n\ntorch::Tensor conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) {\n TORCH_CHECK(xz.is_cuda(), \"xz must be CUDA\");\n auto B = xz.size(0);\n auto L = xz.size(1);\n auto twoI = xz.size(2);\n auto I = twoI / 2;\n auto xb = torch::empty({B, L, I}, xz.options());\n auto z = torch::empty({B, L, I}, xz.options());\n conv_silu_z_launcher(xz, weight, bias, xb, z);\n return torch::stack({xb, z}, 0);\n}\n\ntorch::Tensor selective_scan(torch::Tensor xb, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) {\n TORCH_CHECK(xb.is_cuda(), \"xb must be CUDA\");\n auto y = torch::empty_like(xb);\n scan_launcher(xb, delta_pre, Bt, Ct, A_log, D, y);\n return y;\n}\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\n__device__ __forceinline__ float silu_f(float x) {\n return x / (1.0f + expf(-x));\n}\n\n__device__ __forceinline__ float softplus_f(float x) {\n return (x > 20.0f) ? x : log1pf(expf(x));\n}\n\n__global__ void conv_silu_z_kernel(const float* __restrict__ xz,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ xb,\n float* __restrict__ z,\n int B, int L, int I, int K) {\n long long total = (long long)B * L * I;\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int i = idx % I;\n int t = (idx / I) % L;\n int b = idx / ((long long)L * I);\n const int twoI = 2 * I;\n float acc = bias[i];\n // Conv1d with padding K-1, cross-correlation, cropped to first L outputs.\n #pragma unroll\n for (int k = 0; k < 4; ++k) {\n int tt = t + k - (K - 1);\n if (k < K && tt >= 0 && tt < L) {\n acc += xz[((long long)b * L + tt) * twoI + i] * w[(long long)i * K + k];\n }\n }\n xb[idx] = silu_f(acc);\n float zv = xz[((long long)b * L + t) * twoI + (I + i)];\n z[idx] = silu_f(zv);\n}\n\n__global__ void scan_kernel(const float* __restrict__ xb,\n const float* __restrict__ delta_pre,\n const float* __restrict__ Bt,\n const float* __restrict__ Ct,\n const float* __restrict__ A_log,\n const float* __restrict__ Dv,\n float* __restrict__ y,\n int B, int L, int I, int N) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = B * I;\n if (idx >= total) return;\n int i = idx % I;\n int b = idx / I;\n float h[16];\n float A[16];\n #pragma unroll\n for (int n = 0; n < 16; ++n) {\n h[n] = 0.0f;\n if (n < N) A[n] = -expf(A_log[(long long)i * N + n]);\n }\n float Dval = Dv[i];\n for (int t = 0; t < L; ++t) {\n long long xi = ((long long)b * L + t) * I + i;\n long long bn = ((long long)b * L + t) * N;\n float xval = xb[xi];\n float delta = softplus_f(delta_pre[xi]);\n float sum = 0.0f;\n #pragma unroll\n for (int n = 0; n < 16; ++n) {\n if (n < N) {\n float da = expf(delta * A[n]);\n float hv = da * h[n] + (xval * delta) * Bt[bn + n];\n h[n] = hv;\n sum += hv * Ct[bn + n];\n }\n }\n y[xi] = sum + xval * Dval;\n }\n}\n\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z) {\n int B = (int)xz.size(0), L = (int)xz.size(1), I = (int)(xz.size(2) / 2), K = (int)weight.size(2);\n int threads = 256;\n long long total = (long long)B * L * I;\n int blocks = (int)((total + threads - 1) / threads);\n conv_silu_z_kernel<<<blocks, threads>>>(xz.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), xb.data_ptr<float>(), z.data_ptr<float>(), B, L, I, K);\n}\n\nvoid scan_launcher(torch::Tensor xb, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y) {\n int B = (int)xb.size(0), L = (int)xb.size(1), I = (int)xb.size(2), N = (int)Bt.size(2);\n int threads = 128;\n int total = B * I;\n int blocks = (total + threads - 1) / threads;\n scan_kernel<<<blocks, threads>>>(xb.data_ptr<float>(), delta_pre.data_ptr<float>(), Bt.data_ptr<float>(), Ct.data_ptr<float>(), A_log.data_ptr<float>(), D.data_ptr<float>(), y.data_ptr<float>(), B, L, I, N);\n}\n'''\n\n_ext = load_inline(name='mamba_block_ext_v1', cpp_sources=_cpp, cuda_sources=_cuda,\n functions=['conv_silu_z', 'selective_scan'],\n extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, d_model: int, d_state: int, d_conv: int, expand: int):\n super(ModelNew, self).__init__()\n self.d_model = d_model\n self.d_inner = d_model * expand\n self.d_state = d_state\n self.d_conv = d_conv\n self.norm = nn.RMSNorm(d_model)\n self.in_proj = nn.Linear(d_model, self.d_inner * 2, bias=False)\n self.conv1d = nn.Conv1d(self.d_inner, self.d_inner, d_conv,\n padding=d_conv - 1, groups=self.d_inner, bias=True)\n self.activation = nn.SiLU()\n self.A_log = nn.Parameter(torch.randn(self.d_inner, d_state))\n self.proj_B = nn.Linear(self.d_inner, d_state, bias=False)\n self.proj_C = nn.Linear(self.d_inner, d_state, bias=False)\n self.proj_delta = nn.Linear(self.d_inner, self.d_inner, bias=True)\n self.D = nn.Parameter(torch.ones(self.d_inner))\n self.out_proj = nn.Linear(self.d_inner, d_model, bias=False)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n residual = x\n x_norm = self.norm(x)\n xz = self.in_proj(x_norm)\n packed = _ext.conv_silu_z(xz, self.conv1d.weight, self.conv1d.bias)\n x_branch = packed[0]\n z = packed[1]\n delta_pre = self.proj_delta(x_branch)\n B_t = self.proj_B(x_branch)\n C_t = self.proj_C(x_branch)\n y = _ext.selective_scan(x_branch, delta_pre, B_t, C_t, self.A_log, self.D)\n y = y * z\n y = self.out_proj(y)\n return y + residual\n" }
result ← compile_kernel (ok)
okcompile_kernel compile_kernel PASSED: kernel compiled without errors.
turn 2 · 1 tool call(s) · 12.7s turn · 12.7s LLM · 7,904 chars (click to expand)
turn 212.7s turn · 12.7s 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 = r'''\n#include <torch/extension.h>\n\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);\nvoid scan_launcher(torch::Tensor xb, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);\n\ntorch::Tensor conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) {\n TORCH_CHECK(xz.is_cuda(), \"xz must be CUDA\");\n auto B = xz.size(0);\n auto L = xz.size(1);\n auto twoI = xz.size(2);\n auto I = twoI / 2;\n auto xb = torch::empty({B, L, I}, xz.options());\n auto z = torch::empty({B, L, I}, xz.options());\n conv_silu_z_launcher(xz, weight, bias, xb, z);\n return torch::stack({xb, z}, 0);\n}\n\ntorch::Tensor selective_scan(torch::Tensor xb, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) {\n TORCH_CHECK(xb.is_cuda(), \"xb must be CUDA\");\n auto y = torch::empty_like(xb);\n scan_launcher(xb, delta_pre, Bt, Ct, A_log, D, y);\n return y;\n}\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\n__device__ __forceinline__ float silu_f(float x) {\n return x / (1.0f + expf(-x));\n}\n\n__device__ __forceinline__ float softplus_f(float x) {\n return (x > 20.0f) ? x : log1pf(expf(x));\n}\n\n__global__ void conv_silu_z_kernel(const float* __restrict__ xz,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ xb,\n float* __restrict__ z,\n int B, int L, int I, int K) {\n long long total = (long long)B * L * I;\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int i = idx % I;\n int t = (idx / I) % L;\n int b = idx / ((long long)L * I);\n const int twoI = 2 * I;\n float acc = bias[i];\n // Conv1d with padding K-1, cross-correlation, cropped to first L outputs.\n #pragma unroll\n for (int k = 0; k < 4; ++k) {\n int tt = t + k - (K - 1);\n if (k < K && tt >= 0 && tt < L) {\n acc += xz[((long long)b * L + tt) * twoI + i] * w[(long long)i * K + k];\n }\n }\n xb[idx] = silu_f(acc);\n float zv = xz[((long long)b * L + t) * twoI + (I + i)];\n z[idx] = silu_f(zv);\n}\n\n__global__ void scan_kernel(const float* __restrict__ xb,\n const float* __restrict__ delta_pre,\n const float* __restrict__ Bt,\n const float* __restrict__ Ct,\n const float* __restrict__ A_log,\n const float* __restrict__ Dv,\n float* __restrict__ y,\n int B, int L, int I, int N) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = B * I;\n if (idx >= total) return;\n int i = idx % I;\n int b = idx / I;\n float h[16];\n float A[16];\n #pragma unroll\n for (int n = 0; n < 16; ++n) {\n h[n] = 0.0f;\n if (n < N) A[n] = -expf(A_log[(long long)i * N + n]);\n }\n float Dval = Dv[i];\n for (int t = 0; t < L; ++t) {\n long long xi = ((long long)b * L + t) * I + i;\n long long bn = ((long long)b * L + t) * N;\n float xval = xb[xi];\n float delta = softplus_f(delta_pre[xi]);\n float sum = 0.0f;\n #pragma unroll\n for (int n = 0; n < 16; ++n) {\n if (n < N) {\n float da = expf(delta * A[n]);\n float hv = da * h[n] + (xval * delta) * Bt[bn + n];\n h[n] = hv;\n sum += hv * Ct[bn + n];\n }\n }\n y[xi] = sum + xval * Dval;\n }\n}\n\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z) {\n int B = (int)xz.size(0), L = (int)xz.size(1), I = (int)(xz.size(2) / 2), K = (int)weight.size(2);\n int threads = 256;\n long long total = (long long)B * L * I;\n int blocks = (int)((total + threads - 1) / threads);\n conv_silu_z_kernel<<<blocks, threads>>>(xz.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), xb.data_ptr<float>(), z.data_ptr<float>(), B, L, I, K);\n}\n\nvoid scan_launcher(torch::Tensor xb, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y) {\n int B = (int)xb.size(0), L = (int)xb.size(1), I = (int)xb.size(2), N = (int)Bt.size(2);\n int threads = 128;\n int total = B * I;\n int blocks = (total + threads - 1) / threads;\n scan_kernel<<<blocks, threads>>>(xb.data_ptr<float>(), delta_pre.data_ptr<float>(), Bt.data_ptr<float>(), Ct.data_ptr<float>(), A_log.data_ptr<float>(), D.data_ptr<float>(), y.data_ptr<float>(), B, L, I, N);\n}\n'''\n\n_ext = load_inline(name='mamba_block_ext_v1', cpp_sources=_cpp, cuda_sources=_cuda,\n functions=['conv_silu_z', 'selective_scan'],\n extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, d_model: int, d_state: int, d_conv: int, expand: int):\n super(ModelNew, self).__init__()\n self.d_model = d_model\n self.d_inner = d_model * expand\n self.d_state = d_state\n self.d_conv = d_conv\n self.norm = nn.RMSNorm(d_model)\n self.in_proj = nn.Linear(d_model, self.d_inner * 2, bias=False)\n self.conv1d = nn.Conv1d(self.d_inner, self.d_inner, d_conv,\n padding=d_conv - 1, groups=self.d_inner, bias=True)\n self.activation = nn.SiLU()\n self.A_log = nn.Parameter(torch.randn(self.d_inner, d_state))\n self.proj_B = nn.Linear(self.d_inner, d_state, bias=False)\n self.proj_C = nn.Linear(self.d_inner, d_state, bias=False)\n self.proj_delta = nn.Linear(self.d_inner, self.d_inner, bias=True)\n self.D = nn.Parameter(torch.ones(self.d_inner))\n self.out_proj = nn.Linear(self.d_inner, d_model, bias=False)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n residual = x\n x_norm = self.norm(x)\n xz = self.in_proj(x_norm)\n packed = _ext.conv_silu_z(xz, self.conv1d.weight, self.conv1d.bias)\n x_branch = packed[0]\n z = packed[1]\n delta_pre = self.proj_delta(x_branch)\n B_t = self.proj_B(x_branch)\n C_t = self.proj_C(x_branch)\n y = _ext.selective_scan(x_branch, delta_pre, B_t, C_t, self.A_log, self.D)\n y = y * z\n y = self.out_proj(y)\n return y + residual\n" }
result ← run_correctness (ok)
okrun_correctness run_correctness PASSED: (5 / 5) trials all matched the reference. Numerical precision: max_abs_err=4.77e-07 mean_abs_err=2.12e-09 max_rel_err=1.58e-01
turn 3 · 1 tool call(s) · 14.1s turn · 14.1s LLM · 9,314 chars (click to expand)
turn 314.1s turn · 14.1s LLM · 0.0s tools
call → profile_kernel
callprofile_kernel { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp = r'''\n#include <torch/extension.h>\n\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);\nvoid scan_launcher(torch::Tensor xb, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);\n\ntorch::Tensor conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) {\n TORCH_CHECK(xz.is_cuda(), \"xz must be CUDA\");\n auto B = xz.size(0);\n auto L = xz.size(1);\n auto twoI = xz.size(2);\n auto I = twoI / 2;\n auto xb = torch::empty({B, L, I}, xz.options());\n auto z = torch::empty({B, L, I}, xz.options());\n conv_silu_z_launcher(xz, weight, bias, xb, z);\n return torch::stack({xb, z}, 0);\n}\n\ntorch::Tensor selective_scan(torch::Tensor xb, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) {\n TORCH_CHECK(xb.is_cuda(), \"xb must be CUDA\");\n auto y = torch::empty_like(xb);\n scan_launcher(xb, delta_pre, Bt, Ct, A_log, D, y);\n return y;\n}\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\n__device__ __forceinline__ float silu_f(float x) {\n return x / (1.0f + expf(-x));\n}\n\n__device__ __forceinline__ float softplus_f(float x) {\n return (x > 20.0f) ? x : log1pf(expf(x));\n}\n\n__global__ void conv_silu_z_kernel(const float* __restrict__ xz,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ xb,\n float* __restrict__ z,\n int B, int L, int I, int K) {\n long long total = (long long)B * L * I;\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n if (idx >= total) return;\n int i = idx % I;\n int t = (idx / I) % L;\n int b = idx / ((long long)L * I);\n const int twoI = 2 * I;\n float acc = bias[i];\n // Conv1d with padding K-1, cross-correlation, cropped to first L outputs.\n #pragma unroll\n for (int k = 0; k < 4; ++k) {\n int tt = t + k - (K - 1);\n if (k < K && tt >= 0 && tt < L) {\n acc += xz[((long long)b * L + tt) * twoI + i] * w[(long long)i * K + k];\n }\n }\n xb[idx] = silu_f(acc);\n float zv = xz[((long long)b * L + t) * twoI + (I + i)];\n z[idx] = silu_f(zv);\n}\n\n__global__ void scan_kernel(const float* __restrict__ xb,\n const float* __restrict__ delta_pre,\n const float* __restrict__ Bt,\n const float* __restrict__ Ct,\n const float* __restrict__ A_log,\n const float* __restrict__ Dv,\n float* __restrict__ y,\n int B, int L, int I, int N) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = B * I;\n if (idx >= total) return;\n int i = idx % I;\n int b = idx / I;\n float h[16];\n float A[16];\n #pragma unroll\n for (int n = 0; n < 16; ++n) {\n h[n] = 0.0f;\n if (n < N) A[n] = -expf(A_log[(long long)i * N + n]);\n }\n float Dval = Dv[i];\n for (int t = 0; t < L; ++t) {\n long long xi = ((long long)b * L + t) * I + i;\n long long bn = ((long long)b * L + t) * N;\n float xval = xb[xi];\n float delta = softplus_f(delta_pre[xi]);\n float sum = 0.0f;\n #pragma unroll\n for (int n = 0; n < 16; ++n) {\n if (n < N) {\n float da = expf(delta * A[n]);\n float hv = da * h[n] + (xval * delta) * Bt[bn + n];\n h[n] = hv;\n sum += hv * Ct[bn + n];\n }\n }\n y[xi] = sum + xval * Dval;\n }\n}\n\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z) {\n int B = (int)xz.size(0), L = (int)xz.size(1), I = (int)(xz.size(2) / 2), K = (int)weight.size(2);\n int threads = 256;\n long long total = (long long)B * L * I;\n int blocks = (int)((total + threads - 1) / threads);\n conv_silu_z_kernel<<<blocks, threads>>>(xz.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), xb.data_ptr<float>(), z.data_ptr<float>(), B, L, I, K);\n}\n\nvoid scan_launcher(torch::Tensor xb, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y) {\n int B = (int)xb.size(0), L = (int)xb.size(1), I = (int)xb.size(2), N = (int)Bt.size(2);\n int threads = 128;\n int total = B * I;\n int blocks = (total + threads - 1) / threads;\n scan_kernel<<<blocks, threads>>>(xb.data_ptr<float>(), delta_pre.data_ptr<float>(), Bt.data_ptr<float>(), Ct.data_ptr<float>(), A_log.data_ptr<float>(), D.data_ptr<float>(), y.data_ptr<float>(), B, L, I, N);\n}\n'''\n\n_ext = load_inline(name='mamba_block_ext_v1', cpp_sources=_cpp, cuda_sources=_cuda,\n functions=['conv_silu_z', 'selective_scan'],\n extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, d_model: int, d_state: int, d_conv: int, expand: int):\n super(ModelNew, self).__init__()\n self.d_model = d_model\n self.d_inner = d_model * expand\n self.d_state = d_state\n self.d_conv = d_conv\n self.norm = nn.RMSNorm(d_model)\n self.in_proj = nn.Linear(d_model, self.d_inner * 2, bias=False)\n self.conv1d = nn.Conv1d(self.d_inner, self.d_inner, d_conv,\n padding=d_conv - 1, groups=self.d_inner, bias=True)\n self.activation = nn.SiLU()\n self.A_log = nn.Parameter(torch.randn(self.d_inner, d_state))\n self.proj_B = nn.Linear(self.d_inner, d_state, bias=False)\n self.proj_C = nn.Linear(self.d_inner, d_state, bias=False)\n self.proj_delta = nn.Linear(self.d_inner, self.d_inner, bias=True)\n self.D = nn.Parameter(torch.ones(self.d_inner))\n self.out_proj = nn.Linear(self.d_inner, d_model, bias=False)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n residual = x\n x_norm = self.norm(x)\n xz = self.in_proj(x_norm)\n packed = _ext.conv_silu_z(xz, self.conv1d.weight, self.conv1d.bias)\n x_branch = packed[0]\n z = packed[1]\n delta_pre = self.proj_delta(x_branch)\n B_t = self.proj_B(x_branch)\n C_t = self.proj_C(x_branch)\n y = _ext.selective_scan(x_branch, delta_pre, B_t, C_t, self.A_log, self.D)\n y = y * z\n y = self.out_proj(y)\n return y + residual\n" }
result ← profile_kernel (ok)
okprofile_kernel profile_kernel PASSED: profiling complete. === Kernel Profile Summary === --- Kernel Breakdown (by GPU time) --- #1: aten::linear 76348.0μs (27%) calls=1 #2: aten::matmul 76257.0μs (27%) calls=1 #3: aten::mm 76213.0μs (27%) calls=1 #4: aten::rms_norm 8537.0μs (3%) calls=1 #5: aten::_fused_rms_norm 8473.0μs (3%) calls=1 ... +56 more kernels --- Timing --- GPU time: 4160.74 μs --- Memory Bandwidth --- DRAM BW: 17667.2/3350 GB/s (100.0%) read=13161.9 write=4505.3 GB/s Hit rates: L2=593.2% --- Compute Throughput --- Dominant pipe: tensor-core util=5.0% Pipe util: FMA=369.8%, Tensor=5.0% --- Roofline Analysis --- Ridge point (tensor-core): 295.22 FLOPs/byte Classification: MEMORY-BOUND --- Occupancy --- Achieved: 493.3% Eligible warps/cycle: 12.47 Launch: regs/thread=1228, smem/blk=142720B, block=1536, grid=135488 --- Memory Access Quality --- Global ld coalescing: 93.98 sectors/req (94.0x wasted BW) --- Warp Stall Reasons (% of issue cycles) --- long_scoreboard 81714.9% #################### short_scoreboard 5036.0% #################### mio_throttle 4713.2% #################### --- Optimization Hints --- -> 81715% stalls: global memory latency (waiting for DRAM/L2). + sectors/req=94.0 -> uncoalesced global loads, restructure access pattern or use __ldg Try shared-memory tiling, prefetching, or reducing working set. -> Global load coalescing=94.0x (ideal=1.0) -> 94x wasted DRAM BW. Make per-warp accesses contiguous.
turn 4 · 1 tool call(s) · 26.6s turn · 26.6s LLM · 8,107 chars (click to expand)
turn 426.6s turn · 26.6s LLM · 0.0s tools
reasoning
**Evaluating occupancy limits** I’m considering occupancy in terms of threads and blocks. It seems I have 32 floats affecting around 64 registers, leading to 64 total blocks — but I'm thinking that might not be enough. With 16 bytes multiplied by 4 blocks, that gives me 64 blocks total, and if each block has 128 threads, that’s 8192 threads over 132 SMs. It looks like occupancy is low, especially with each thread running a long loop. I see the current blocks are also capped at 64.
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 = r'''\n#include <torch/extension.h>\n#include <vector>\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);\n\nstd::vector<torch::Tensor> conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) {\n auto B = xz.size(0), L = xz.size(1), I = xz.size(2) / 2;\n auto xb = torch::empty({B, L, I}, xz.options());\n auto z = torch::empty({B, L, I}, xz.options());\n conv_silu_z_launcher(xz, weight, bias, xb, z);\n return {xb, z};\n}\n\ntorch::Tensor selective_scan_gated(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) {\n auto y = torch::empty_like(xb);\n scan_launcher(xb, z, delta_pre, Bt, Ct, A_log, D, y);\n return y;\n}\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\n__device__ __forceinline__ float silu_f(float x) { return x / (1.0f + expf(-x)); }\n__device__ __forceinline__ float softplus_f(float x) { return (x > 20.0f) ? x : log1pf(expf(x)); }\n\n__global__ void conv_silu_z_kernel(const float* __restrict__ xz, const float* __restrict__ w,\n const float* __restrict__ bias, float* __restrict__ xb,\n float* __restrict__ z, int B, int L, int I, int K) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)B * L * I;\n if (idx >= total) return;\n int i = idx % I;\n int t = (idx / I) % L;\n int b = idx / ((long long)L * I);\n int twoI = I << 1;\n float acc = bias[i];\n #pragma unroll\n for (int k = 0; k < 4; ++k) {\n int tt = t + k - (K - 1);\n if (tt >= 0 && tt < L && k < K)\n acc += xz[((long long)b * L + tt) * twoI + i] * w[(long long)i * K + k];\n }\n xb[idx] = silu_f(acc);\n z[idx] = silu_f(xz[((long long)b * L + t) * twoI + I + i]);\n}\n\n__global__ void scan_shared_kernel(const float* __restrict__ xb,\n const float* __restrict__ z,\n const float* __restrict__ delta_pre,\n const float* __restrict__ Bt,\n const float* __restrict__ Ct,\n const float* __restrict__ A_log,\n const float* __restrict__ Dv,\n float* __restrict__ y,\n int B, int L, int I, int N) {\n __shared__ float Bs[16];\n __shared__ float Cs[16];\n int b = blockIdx.y;\n int i = blockIdx.x * blockDim.x + threadIdx.x;\n bool valid = (i < I);\n float h[16];\n float A[16];\n #pragma unroll\n for (int n=0; n<16; ++n) {\n h[n] = 0.0f;\n A[n] = (valid && n < N) ? -expf(A_log[(long long)i * N + n]) : 0.0f;\n }\n float Dval = valid ? Dv[i] : 0.0f;\n for (int t=0; t<L; ++t) {\n if (threadIdx.x < 16) {\n Bs[threadIdx.x] = Bt[((long long)b * L + t) * N + threadIdx.x];\n Cs[threadIdx.x] = Ct[((long long)b * L + t) * N + threadIdx.x];\n }\n __syncthreads();\n if (valid) {\n long long xi = ((long long)b * L + t) * I + i;\n float xval = xb[xi];\n float delta = softplus_f(delta_pre[xi]);\n float xd = xval * delta;\n float sum = 0.0f;\n #pragma unroll\n for (int n=0; n<16; ++n) {\n float hv = expf(delta * A[n]) * h[n] + xd * Bs[n];\n h[n] = hv;\n sum += hv * Cs[n];\n }\n y[xi] = (sum + xval * Dval) * z[xi];\n }\n __syncthreads();\n }\n}\n\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z) {\n int B=(int)xz.size(0), L=(int)xz.size(1), I=(int)(xz.size(2)/2), K=(int)weight.size(2);\n int threads=256; long long total=(long long)B*L*I; int blocks=(int)((total+threads-1)/threads);\n conv_silu_z_kernel<<<blocks,threads>>>(xz.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), xb.data_ptr<float>(), z.data_ptr<float>(), B,L,I,K);\n}\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y) {\n int B=(int)xb.size(0), L=(int)xb.size(1), I=(int)xb.size(2), N=(int)Bt.size(2);\n dim3 block(64); dim3 grid((I+63)/64, B);\n scan_shared_kernel<<<grid,block>>>(xb.data_ptr<float>(), z.data_ptr<float>(), delta_pre.data_ptr<float>(), Bt.data_ptr<float>(), Ct.data_ptr<float>(), A_log.data_ptr<float>(), D.data_ptr<float>(), y.data_ptr<float>(), B,L,I,N);\n}\n'''\n\n_ext = load_inline(name='mamba_block_ext_v2', cpp_sources=_cpp, cuda_sources=_cuda,\n functions=['conv_silu_z','selective_scan_gated'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, d_model: int, d_state: int, d_conv: int, expand: int):\n super(ModelNew, self).__init__()\n self.d_model=d_model; self.d_inner=d_model*expand; self.d_state=d_state; self.d_conv=d_conv\n self.norm=nn.RMSNorm(d_model)\n self.in_proj=nn.Linear(d_model,self.d_inner*2,bias=False)\n self.conv1d=nn.Conv1d(self.d_inner,self.d_inner,d_conv,padding=d_conv-1,groups=self.d_inner,bias=True)\n self.activation=nn.SiLU()\n self.A_log=nn.Parameter(torch.randn(self.d_inner,d_state))\n self.proj_B=nn.Linear(self.d_inner,d_state,bias=False)\n self.proj_C=nn.Linear(self.d_inner,d_state,bias=False)\n self.proj_delta=nn.Linear(self.d_inner,self.d_inner,bias=True)\n self.D=nn.Parameter(torch.ones(self.d_inner))\n self.out_proj=nn.Linear(self.d_inner,d_model,bias=False)\n def forward(self,x:torch.Tensor)->torch.Tensor:\n residual=x\n xz=self.in_proj(self.norm(x))\n x_branch,z=_ext.conv_silu_z(xz,self.conv1d.weight,self.conv1d.bias)\n delta_pre=self.proj_delta(x_branch)\n B_t=self.proj_B(x_branch)\n C_t=self.proj_C(x_branch)\n y=_ext.selective_scan_gated(x_branch,z,delta_pre,B_t,C_t,self.A_log,self.D)\n return self.out_proj(y)+residual\n" }
result ← compile_kernel (ok)
okcompile_kernel compile_kernel PASSED: kernel compiled without errors.
turn 5 · 1 tool call(s) · 18.4s turn · 18.4s LLM · 7,630 chars (click to expand)
turn 518.4s turn · 18.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 = r'''\n#include <torch/extension.h>\n#include <vector>\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);\n\nstd::vector<torch::Tensor> conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) {\n auto B = xz.size(0), L = xz.size(1), I = xz.size(2) / 2;\n auto xb = torch::empty({B, L, I}, xz.options());\n auto z = torch::empty({B, L, I}, xz.options());\n conv_silu_z_launcher(xz, weight, bias, xb, z);\n return {xb, z};\n}\n\ntorch::Tensor selective_scan_gated(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) {\n auto y = torch::empty_like(xb);\n scan_launcher(xb, z, delta_pre, Bt, Ct, A_log, D, y);\n return y;\n}\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\n__device__ __forceinline__ float silu_f(float x) { return x / (1.0f + expf(-x)); }\n__device__ __forceinline__ float softplus_f(float x) { return (x > 20.0f) ? x : log1pf(expf(x)); }\n\n__global__ void conv_silu_z_kernel(const float* __restrict__ xz, const float* __restrict__ w,\n const float* __restrict__ bias, float* __restrict__ xb,\n float* __restrict__ z, int B, int L, int I, int K) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)B * L * I;\n if (idx >= total) return;\n int i = idx % I;\n int t = (idx / I) % L;\n int b = idx / ((long long)L * I);\n int twoI = I << 1;\n float acc = bias[i];\n #pragma unroll\n for (int k = 0; k < 4; ++k) {\n int tt = t + k - (K - 1);\n if (tt >= 0 && tt < L && k < K)\n acc += xz[((long long)b * L + tt) * twoI + i] * w[(long long)i * K + k];\n }\n xb[idx] = silu_f(acc);\n z[idx] = silu_f(xz[((long long)b * L + t) * twoI + I + i]);\n}\n\n__global__ void scan_shared_kernel(const float* __restrict__ xb,\n const float* __restrict__ z,\n const float* __restrict__ delta_pre,\n const float* __restrict__ Bt,\n const float* __restrict__ Ct,\n const float* __restrict__ A_log,\n const float* __restrict__ Dv,\n float* __restrict__ y,\n int B, int L, int I, int N) {\n __shared__ float Bs[16];\n __shared__ float Cs[16];\n int b = blockIdx.y;\n int i = blockIdx.x * blockDim.x + threadIdx.x;\n bool valid = (i < I);\n float h[16];\n float A[16];\n #pragma unroll\n for (int n=0; n<16; ++n) {\n h[n] = 0.0f;\n A[n] = (valid && n < N) ? -expf(A_log[(long long)i * N + n]) : 0.0f;\n }\n float Dval = valid ? Dv[i] : 0.0f;\n for (int t=0; t<L; ++t) {\n if (threadIdx.x < 16) {\n Bs[threadIdx.x] = Bt[((long long)b * L + t) * N + threadIdx.x];\n Cs[threadIdx.x] = Ct[((long long)b * L + t) * N + threadIdx.x];\n }\n __syncthreads();\n if (valid) {\n long long xi = ((long long)b * L + t) * I + i;\n float xval = xb[xi];\n float delta = softplus_f(delta_pre[xi]);\n float xd = xval * delta;\n float sum = 0.0f;\n #pragma unroll\n for (int n=0; n<16; ++n) {\n float hv = expf(delta * A[n]) * h[n] + xd * Bs[n];\n h[n] = hv;\n sum += hv * Cs[n];\n }\n y[xi] = (sum + xval * Dval) * z[xi];\n }\n __syncthreads();\n }\n}\n\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z) {\n int B=(int)xz.size(0), L=(int)xz.size(1), I=(int)(xz.size(2)/2), K=(int)weight.size(2);\n int threads=256; long long total=(long long)B*L*I; int blocks=(int)((total+threads-1)/threads);\n conv_silu_z_kernel<<<blocks,threads>>>(xz.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), xb.data_ptr<float>(), z.data_ptr<float>(), B,L,I,K);\n}\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y) {\n int B=(int)xb.size(0), L=(int)xb.size(1), I=(int)xb.size(2), N=(int)Bt.size(2);\n dim3 block(64); dim3 grid((I+63)/64, B);\n scan_shared_kernel<<<grid,block>>>(xb.data_ptr<float>(), z.data_ptr<float>(), delta_pre.data_ptr<float>(), Bt.data_ptr<float>(), Ct.data_ptr<float>(), A_log.data_ptr<float>(), D.data_ptr<float>(), y.data_ptr<float>(), B,L,I,N);\n}\n'''\n\n_ext = load_inline(name='mamba_block_ext_v2', cpp_sources=_cpp, cuda_sources=_cuda,\n functions=['conv_silu_z','selective_scan_gated'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, d_model: int, d_state: int, d_conv: int, expand: int):\n super(ModelNew, self).__init__()\n self.d_model=d_model; self.d_inner=d_model*expand; self.d_state=d_state; self.d_conv=d_conv\n self.norm=nn.RMSNorm(d_model)\n self.in_proj=nn.Linear(d_model,self.d_inner*2,bias=False)\n self.conv1d=nn.Conv1d(self.d_inner,self.d_inner,d_conv,padding=d_conv-1,groups=self.d_inner,bias=True)\n self.activation=nn.SiLU()\n self.A_log=nn.Parameter(torch.randn(self.d_inner,d_state))\n self.proj_B=nn.Linear(self.d_inner,d_state,bias=False)\n self.proj_C=nn.Linear(self.d_inner,d_state,bias=False)\n self.proj_delta=nn.Linear(self.d_inner,self.d_inner,bias=True)\n self.D=nn.Parameter(torch.ones(self.d_inner))\n self.out_proj=nn.Linear(self.d_inner,d_model,bias=False)\n def forward(self,x:torch.Tensor)->torch.Tensor:\n residual=x\n xz=self.in_proj(self.norm(x))\n x_branch,z=_ext.conv_silu_z(xz,self.conv1d.weight,self.conv1d.bias)\n delta_pre=self.proj_delta(x_branch)\n B_t=self.proj_B(x_branch)\n C_t=self.proj_C(x_branch)\n y=_ext.selective_scan_gated(x_branch,z,delta_pre,B_t,C_t,self.A_log,self.D)\n return self.out_proj(y)+residual\n" }
result ← run_correctness (ok)
okrun_correctness run_correctness PASSED: (5 / 5) trials all matched the reference. Numerical precision: max_abs_err=4.77e-07 mean_abs_err=2.12e-09 max_rel_err=1.58e-01
turn 6 · 1 tool call(s) · 15.3s turn · 15.3s LLM · 9,494 chars (click to expand)
turn 615.3s turn · 15.3s LLM · 0.0s tools
call → profile_kernel
callprofile_kernel { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp = r'''\n#include <torch/extension.h>\n#include <vector>\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);\n\nstd::vector<torch::Tensor> conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) {\n auto B = xz.size(0), L = xz.size(1), I = xz.size(2) / 2;\n auto xb = torch::empty({B, L, I}, xz.options());\n auto z = torch::empty({B, L, I}, xz.options());\n conv_silu_z_launcher(xz, weight, bias, xb, z);\n return {xb, z};\n}\n\ntorch::Tensor selective_scan_gated(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) {\n auto y = torch::empty_like(xb);\n scan_launcher(xb, z, delta_pre, Bt, Ct, A_log, D, y);\n return y;\n}\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\n__device__ __forceinline__ float silu_f(float x) { return x / (1.0f + expf(-x)); }\n__device__ __forceinline__ float softplus_f(float x) { return (x > 20.0f) ? x : log1pf(expf(x)); }\n\n__global__ void conv_silu_z_kernel(const float* __restrict__ xz, const float* __restrict__ w,\n const float* __restrict__ bias, float* __restrict__ xb,\n float* __restrict__ z, int B, int L, int I, int K) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)B * L * I;\n if (idx >= total) return;\n int i = idx % I;\n int t = (idx / I) % L;\n int b = idx / ((long long)L * I);\n int twoI = I << 1;\n float acc = bias[i];\n #pragma unroll\n for (int k = 0; k < 4; ++k) {\n int tt = t + k - (K - 1);\n if (tt >= 0 && tt < L && k < K)\n acc += xz[((long long)b * L + tt) * twoI + i] * w[(long long)i * K + k];\n }\n xb[idx] = silu_f(acc);\n z[idx] = silu_f(xz[((long long)b * L + t) * twoI + I + i]);\n}\n\n__global__ void scan_shared_kernel(const float* __restrict__ xb,\n const float* __restrict__ z,\n const float* __restrict__ delta_pre,\n const float* __restrict__ Bt,\n const float* __restrict__ Ct,\n const float* __restrict__ A_log,\n const float* __restrict__ Dv,\n float* __restrict__ y,\n int B, int L, int I, int N) {\n __shared__ float Bs[16];\n __shared__ float Cs[16];\n int b = blockIdx.y;\n int i = blockIdx.x * blockDim.x + threadIdx.x;\n bool valid = (i < I);\n float h[16];\n float A[16];\n #pragma unroll\n for (int n=0; n<16; ++n) {\n h[n] = 0.0f;\n A[n] = (valid && n < N) ? -expf(A_log[(long long)i * N + n]) : 0.0f;\n }\n float Dval = valid ? Dv[i] : 0.0f;\n for (int t=0; t<L; ++t) {\n if (threadIdx.x < 16) {\n Bs[threadIdx.x] = Bt[((long long)b * L + t) * N + threadIdx.x];\n Cs[threadIdx.x] = Ct[((long long)b * L + t) * N + threadIdx.x];\n }\n __syncthreads();\n if (valid) {\n long long xi = ((long long)b * L + t) * I + i;\n float xval = xb[xi];\n float delta = softplus_f(delta_pre[xi]);\n float xd = xval * delta;\n float sum = 0.0f;\n #pragma unroll\n for (int n=0; n<16; ++n) {\n float hv = expf(delta * A[n]) * h[n] + xd * Bs[n];\n h[n] = hv;\n sum += hv * Cs[n];\n }\n y[xi] = (sum + xval * Dval) * z[xi];\n }\n __syncthreads();\n }\n}\n\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z) {\n int B=(int)xz.size(0), L=(int)xz.size(1), I=(int)(xz.size(2)/2), K=(int)weight.size(2);\n int threads=256; long long total=(long long)B*L*I; int blocks=(int)((total+threads-1)/threads);\n conv_silu_z_kernel<<<blocks,threads>>>(xz.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), xb.data_ptr<float>(), z.data_ptr<float>(), B,L,I,K);\n}\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y) {\n int B=(int)xb.size(0), L=(int)xb.size(1), I=(int)xb.size(2), N=(int)Bt.size(2);\n dim3 block(64); dim3 grid((I+63)/64, B);\n scan_shared_kernel<<<grid,block>>>(xb.data_ptr<float>(), z.data_ptr<float>(), delta_pre.data_ptr<float>(), Bt.data_ptr<float>(), Ct.data_ptr<float>(), A_log.data_ptr<float>(), D.data_ptr<float>(), y.data_ptr<float>(), B,L,I,N);\n}\n'''\n\n_ext = load_inline(name='mamba_block_ext_v2', cpp_sources=_cpp, cuda_sources=_cuda,\n functions=['conv_silu_z','selective_scan_gated'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, d_model: int, d_state: int, d_conv: int, expand: int):\n super(ModelNew, self).__init__()\n self.d_model=d_model; self.d_inner=d_model*expand; self.d_state=d_state; self.d_conv=d_conv\n self.norm=nn.RMSNorm(d_model)\n self.in_proj=nn.Linear(d_model,self.d_inner*2,bias=False)\n self.conv1d=nn.Conv1d(self.d_inner,self.d_inner,d_conv,padding=d_conv-1,groups=self.d_inner,bias=True)\n self.activation=nn.SiLU()\n self.A_log=nn.Parameter(torch.randn(self.d_inner,d_state))\n self.proj_B=nn.Linear(self.d_inner,d_state,bias=False)\n self.proj_C=nn.Linear(self.d_inner,d_state,bias=False)\n self.proj_delta=nn.Linear(self.d_inner,self.d_inner,bias=True)\n self.D=nn.Parameter(torch.ones(self.d_inner))\n self.out_proj=nn.Linear(self.d_inner,d_model,bias=False)\n def forward(self,x:torch.Tensor)->torch.Tensor:\n residual=x\n xz=self.in_proj(self.norm(x))\n x_branch,z=_ext.conv_silu_z(xz,self.conv1d.weight,self.conv1d.bias)\n delta_pre=self.proj_delta(x_branch)\n B_t=self.proj_B(x_branch)\n C_t=self.proj_C(x_branch)\n y=_ext.selective_scan_gated(x_branch,z,delta_pre,B_t,C_t,self.A_log,self.D)\n return self.out_proj(y)+residual\n" }
result ← profile_kernel (ok)
okprofile_kernel profile_kernel PASSED: profiling complete. === Kernel Profile Summary === --- Kernel Breakdown (by GPU time) --- #1: aten::linear 648955.0μs (31%) calls=1 #2: aten::matmul 648832.0μs (31%) calls=1 #3: aten::mm 648778.0μs (31%) calls=1 #4: aten::empty 35775.0μs (2%) calls=1 #5: aten::rms_norm 29355.0μs (1%) calls=1 ... +48 more kernels --- Timing --- GPU time: 3795.90 μs [↓364.8μs ok] --- Memory Bandwidth --- DRAM BW: 12093.5/3350 GB/s (100.0%) read=9602.5 write=2491.0 GB/s Hit rates: L2=498.1% --- Compute Throughput --- Dominant pipe: FP32 util=363.6% [↑358.6% ok] Pipe util: FMA=363.6%, Tensor=4.4% --- Roofline Analysis --- Ridge point (FP32): 20.00 FLOPs/byte Classification: COMPUTE-BOUND --- Occupancy --- Achieved: 318.0% [↓175.3% REGRESSED] Eligible warps/cycle: 12.45 Launch: regs/thread=1183, smem/blk=140800B, block=1216, grid=110720 --- Memory Access Quality --- Global ld coalescing: 64.35 sectors/req (64.4x wasted BW) --- Warp Stall Reasons (% of issue cycles) --- long_scoreboard 22975.4% #################### short_scoreboard 2426.7% #################### mio_throttle 2260.8% #################### --- Optimization Hints --- -> 22975% stalls: global memory latency (waiting for DRAM/L2). + sectors/req=64.4 -> uncoalesced global loads, restructure access pattern or use __ldg Try shared-memory tiling, prefetching, or reducing working set. -> Global load coalescing=64.4x (ideal=1.0) -> 64x wasted DRAM BW. Make per-warp accesses contiguous. -> Compute-bound but NOT using tensor cores. If applicable, use FP16/BF16 with torch.matmul or WMMA intrinsics. --- Delta vs Previous Iteration --- GPU time: 4160.74→3795.90μs (↓364.83) ok Compute%: 5.03→363.65% (↑358.61) ok Occupancy: 493.34→318.03% (↓175.31) REGRESSED Eligible warps/cyc: 12.47→12.45 (↓0.02) REGRESSED Ld sectors/req: 93.98→64.35 (↓29.63) ok L2 hit%: 593.19→498.12% (↓95.07) REGRESSED
turn 7 · 1 tool call(s) · 18.9s turn · 18.9s LLM · 6,143 chars (click to expand)
turn 718.9s turn · 18.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\n_cpp = r'''\n#include <torch/extension.h>\n#include <vector>\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);\nstd::vector<torch::Tensor> conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) { auto B=xz.size(0),L=xz.size(1),I=xz.size(2)/2; auto xb=torch::empty({B,L,I},xz.options()); auto z=torch::empty({B,L,I},xz.options()); conv_silu_z_launcher(xz,weight,bias,xb,z); return {xb,z}; }\ntorch::Tensor selective_scan_gated(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) { auto y=torch::empty_like(xb); scan_launcher(xb,z,delta_pre,Bt,Ct,A_log,D,y); return y; }\n'''\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n__device__ __forceinline__ float silu_f(float x){return x/(1.0f+expf(-x));}\n__device__ __forceinline__ float softplus_f(float x){return (x>20.0f)?x:log1pf(expf(x));}\n__global__ void conv_silu_z_kernel(const float* __restrict__ xz,const float* __restrict__ w,const float* __restrict__ bias,float* __restrict__ xb,float* __restrict__ z,int B,int L,int I,int K){long long idx=(long long)blockIdx.x*blockDim.x+threadIdx.x,total=(long long)B*L*I; if(idx>=total)return; int i=idx%I,t=(idx/I)%L,b=idx/((long long)L*I),twoI=I<<1; float acc=bias[i]; #pragma unroll\n for(int k=0;k<4;++k){int tt=t+k-(K-1); if(tt>=0&&tt<L&&k<K) acc+=xz[((long long)b*L+tt)*twoI+i]*w[(long long)i*K+k];} xb[idx]=silu_f(acc); z[idx]=silu_f(xz[((long long)b*L+t)*twoI+I+i]);}\n__global__ void scan_shared_kernel(const float* __restrict__ xb,const float* __restrict__ z,const float* __restrict__ delta_pre,const float* __restrict__ Bt,const float* __restrict__ Ct,const float* __restrict__ A_log,const float* __restrict__ Dv,float* __restrict__ y,int B,int L,int I,int N){__shared__ float Bs[16]; __shared__ float Cs[16]; int b=blockIdx.y; int i=blockIdx.x*blockDim.x+threadIdx.x; bool valid=i<I; float h[16]; float A[16]; #pragma unroll\n for(int n=0;n<16;++n){h[n]=0.0f; A[n]=(valid&&n<N)?-expf(A_log[(long long)i*N+n]):0.0f;} float Dval=valid?Dv[i]:0.0f; for(int t=0;t<L;++t){ if(threadIdx.x<16){Bs[threadIdx.x]=Bt[((long long)b*L+t)*N+threadIdx.x]; Cs[threadIdx.x]=Ct[((long long)b*L+t)*N+threadIdx.x];} __syncthreads(); if(valid){long long xi=((long long)b*L+t)*I+i; float xval=xb[xi]; float delta=softplus_f(delta_pre[xi]); float xd=xval*delta; float sum=0.0f; #pragma unroll\n for(int n=0;n<16;++n){float hv=expf(delta*A[n])*h[n]+xd*Bs[n]; h[n]=hv; sum+=hv*Cs[n];} y[xi]=(sum+xval*Dval)*z[xi];} __syncthreads();}}\nvoid conv_silu_z_launcher(torch::Tensor xz,torch::Tensor weight,torch::Tensor bias,torch::Tensor xb,torch::Tensor z){int B=xz.size(0),L=xz.size(1),I=xz.size(2)/2,K=weight.size(2); int threads=256; long long total=(long long)B*L*I; int blocks=(total+threads-1)/threads; conv_silu_z_kernel<<<blocks,threads>>>(xz.data_ptr<float>(),weight.data_ptr<float>(),bias.data_ptr<float>(),xb.data_ptr<float>(),z.data_ptr<float>(),B,L,I,K);}\nvoid scan_launcher(torch::Tensor xb,torch::Tensor z,torch::Tensor delta_pre,torch::Tensor Bt,torch::Tensor Ct,torch::Tensor A_log,torch::Tensor D,torch::Tensor y){int B=xb.size(0),L=xb.size(1),I=xb.size(2),N=Bt.size(2); dim3 block(64); dim3 grid((I+63)/64,B); scan_shared_kernel<<<grid,block>>>(xb.data_ptr<float>(),z.data_ptr<float>(),delta_pre.data_ptr<float>(),Bt.data_ptr<float>(),Ct.data_ptr<float>(),A_log.data_ptr<float>(),D.data_ptr<float>(),y.data_ptr<float>(),B,L,I,N);}\n'''\n_ext=load_inline(name='mamba_block_ext_fastmath',cpp_sources=_cpp,cuda_sources=_cuda,functions=['conv_silu_z','selective_scan_gated'],extra_cflags=['-O3'],extra_cuda_cflags=['-O3','--use_fast_math'],verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self,d_model:int,d_state:int,d_conv:int,expand:int):\n super(ModelNew,self).__init__(); self.d_model=d_model; self.d_inner=d_model*expand; self.d_state=d_state; self.d_conv=d_conv; self.norm=nn.RMSNorm(d_model); self.in_proj=nn.Linear(d_model,self.d_inner*2,bias=False); self.conv1d=nn.Conv1d(self.d_inner,self.d_inner,d_conv,padding=d_conv-1,groups=self.d_inner,bias=True); self.activation=nn.SiLU(); self.A_log=nn.Parameter(torch.randn(self.d_inner,d_state)); self.proj_B=nn.Linear(self.d_inner,d_state,bias=False); self.proj_C=nn.Linear(self.d_inner,d_state,bias=False); self.proj_delta=nn.Linear(self.d_inner,self.d_inner,bias=True); self.D=nn.Parameter(torch.ones(self.d_inner)); self.out_proj=nn.Linear(self.d_inner,d_model,bias=False)\n def forward(self,x:torch.Tensor)->torch.Tensor:\n residual=x; xz=self.in_proj(self.norm(x)); x_branch,z=_ext.conv_silu_z(xz,self.conv1d.weight,self.conv1d.bias); delta_pre=self.proj_delta(x_branch); B_t=self.proj_B(x_branch); C_t=self.proj_C(x_branch); y=_ext.selective_scan_gated(x_branch,z,delta_pre,B_t,C_t,self.A_log,self.D); return self.out_proj(y)+residual\n" }
result ← run_correctness (fail)
failrun_correctness run_correctness FAILED: persistent build/lock contention after retries. Please try a different kernel.
turn 8 · 1 tool call(s) · 17.7s turn · 17.7s LLM · 7,564 chars (click to expand)
turn 817.7s turn · 17.7s 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 = r'''\n#include <torch/extension.h>\n#include <vector>\nvoid rmsnorm_launcher(torch::Tensor x, torch::Tensor weight, torch::Tensor out);\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);\n\ntorch::Tensor rms_norm_cuda(torch::Tensor x, torch::Tensor weight) { auto out=torch::empty_like(x); rmsnorm_launcher(x,weight,out); return out; }\nstd::vector<torch::Tensor> conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) { auto B=xz.size(0),L=xz.size(1),I=xz.size(2)/2; auto xb=torch::empty({B,L,I},xz.options()); auto z=torch::empty({B,L,I},xz.options()); conv_silu_z_launcher(xz,weight,bias,xb,z); return {xb,z}; }\ntorch::Tensor selective_scan_gated(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) { auto y=torch::empty_like(xb); scan_launcher(xb,z,delta_pre,Bt,Ct,A_log,D,y); return y; }\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n__device__ __forceinline__ float silu_f(float x) { return x / (1.0f + expf(-x)); }\n__device__ __forceinline__ float softplus_f(float x) { return (x > 20.0f) ? x : log1pf(expf(x)); }\n\n__global__ void rmsnorm_kernel(const float* __restrict__ x, const float* __restrict__ w, float* __restrict__ out, int rows, int D) {\n int row=blockIdx.x; if(row>=rows) return;\n float sum=0.0f; long long base=(long long)row*D;\n for(int d=threadIdx.x; d<D; d+=blockDim.x){ float v=x[base+d]; sum += v*v; }\n __shared__ float smem[256]; smem[threadIdx.x]=sum; __syncthreads();\n for(int s=blockDim.x/2; s>0; s>>=1){ if(threadIdx.x<s) smem[threadIdx.x]+=smem[threadIdx.x+s]; __syncthreads(); }\n float r=rsqrtf(smem[0]/(float)D + 1.1920928955078125e-7f);\n for(int d=threadIdx.x; d<D; d+=blockDim.x) out[base+d]=x[base+d]*r*w[d];\n}\n\n__global__ void conv_silu_z_kernel(const float* __restrict__ xz, const float* __restrict__ w, const float* __restrict__ bias, float* __restrict__ xb, float* __restrict__ z, int B, int L, int I, int K) {\n long long idx=(long long)blockIdx.x*blockDim.x+threadIdx.x; long long total=(long long)B*L*I; if(idx>=total) return;\n int i=idx%I; int t=(idx/I)%L; int b=idx/((long long)L*I); int twoI=I<<1; float acc=bias[i];\n #pragma unroll\n for(int k=0;k<4;++k){ int tt=t+k-(K-1); if(tt>=0 && tt<L && k<K) acc += xz[((long long)b*L+tt)*twoI+i] * w[(long long)i*K+k]; }\n xb[idx]=silu_f(acc); z[idx]=silu_f(xz[((long long)b*L+t)*twoI+I+i]);\n}\n\n__global__ void scan_shared_kernel(const float* __restrict__ xb, const float* __restrict__ z, const float* __restrict__ delta_pre, const float* __restrict__ Bt, const float* __restrict__ Ct, const float* __restrict__ A_log, const float* __restrict__ Dv, float* __restrict__ y, int B, int L, int I, int N) {\n __shared__ float Bs[16]; __shared__ float Cs[16];\n int b=blockIdx.y; int i=blockIdx.x*blockDim.x+threadIdx.x; bool valid=(i<I);\n float h[16]; float A[16];\n #pragma unroll\n for(int n=0;n<16;++n){ h[n]=0.0f; A[n]=(valid && n<N) ? -expf(A_log[(long long)i*N+n]) : 0.0f; }\n float Dval=valid ? Dv[i] : 0.0f;\n for(int t=0;t<L;++t){\n if(threadIdx.x<16){ Bs[threadIdx.x]=Bt[((long long)b*L+t)*N+threadIdx.x]; Cs[threadIdx.x]=Ct[((long long)b*L+t)*N+threadIdx.x]; }\n __syncthreads();\n if(valid){ long long xi=((long long)b*L+t)*I+i; float xval=xb[xi]; float delta=softplus_f(delta_pre[xi]); float xd=xval*delta; float sum=0.0f;\n #pragma unroll\n for(int n=0;n<16;++n){ float hv=expf(delta*A[n])*h[n]+xd*Bs[n]; h[n]=hv; sum += hv*Cs[n]; }\n y[xi]=(sum+xval*Dval)*z[xi]; }\n __syncthreads();\n }\n}\nvoid rmsnorm_launcher(torch::Tensor x, torch::Tensor weight, torch::Tensor out){ int rows=x.size(0)*x.size(1), D=x.size(2); rmsnorm_kernel<<<rows,256>>>(x.data_ptr<float>(),weight.data_ptr<float>(),out.data_ptr<float>(),rows,D); }\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z){ int B=xz.size(0),L=xz.size(1),I=xz.size(2)/2,K=weight.size(2); int threads=256; long long total=(long long)B*L*I; int blocks=(total+threads-1)/threads; conv_silu_z_kernel<<<blocks,threads>>>(xz.data_ptr<float>(),weight.data_ptr<float>(),bias.data_ptr<float>(),xb.data_ptr<float>(),z.data_ptr<float>(),B,L,I,K); }\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y){ int B=xb.size(0),L=xb.size(1),I=xb.size(2),N=Bt.size(2); dim3 block(64); dim3 grid((I+63)/64,B); scan_shared_kernel<<<grid,block>>>(xb.data_ptr<float>(),z.data_ptr<float>(),delta_pre.data_ptr<float>(),Bt.data_ptr<float>(),Ct.data_ptr<float>(),A_log.data_ptr<float>(),D.data_ptr<float>(),y.data_ptr<float>(),B,L,I,N); }\n'''\n_ext=load_inline(name='mamba_block_ext_v3',cpp_sources=_cpp,cuda_sources=_cuda,functions=['rms_norm_cuda','conv_silu_z','selective_scan_gated'],extra_cflags=['-O3'],extra_cuda_cflags=['-O3'],verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self,d_model:int,d_state:int,d_conv:int,expand:int):\n super(ModelNew,self).__init__(); self.d_model=d_model; self.d_inner=d_model*expand; self.d_state=d_state; self.d_conv=d_conv\n self.norm=nn.RMSNorm(d_model); self.in_proj=nn.Linear(d_model,self.d_inner*2,bias=False); self.conv1d=nn.Conv1d(self.d_inner,self.d_inner,d_conv,padding=d_conv-1,groups=self.d_inner,bias=True); self.activation=nn.SiLU(); self.A_log=nn.Parameter(torch.randn(self.d_inner,d_state)); self.proj_B=nn.Linear(self.d_inner,d_state,bias=False); self.proj_C=nn.Linear(self.d_inner,d_state,bias=False); self.proj_delta=nn.Linear(self.d_inner,self.d_inner,bias=True); self.D=nn.Parameter(torch.ones(self.d_inner)); self.out_proj=nn.Linear(self.d_inner,d_model,bias=False)\n def forward(self,x:torch.Tensor)->torch.Tensor:\n residual=x; xn=_ext.rms_norm_cuda(x,self.norm.weight); xz=self.in_proj(xn); x_branch,z=_ext.conv_silu_z(xz,self.conv1d.weight,self.conv1d.bias); delta_pre=self.proj_delta(x_branch); B_t=self.proj_B(x_branch); C_t=self.proj_C(x_branch); y=_ext.selective_scan_gated(x_branch,z,delta_pre,B_t,C_t,self.A_log,self.D); return self.out_proj(y)+residual\n" }
result ← compile_kernel (ok)
okcompile_kernel compile_kernel PASSED: kernel compiled without errors.
turn 9 · 1 tool call(s) · 12.3s turn · 12.3s LLM · 7,666 chars (click to expand)
turn 912.3s turn · 12.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 = r'''\n#include <torch/extension.h>\n#include <vector>\nvoid rmsnorm_launcher(torch::Tensor x, torch::Tensor weight, torch::Tensor out);\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);\n\ntorch::Tensor rms_norm_cuda(torch::Tensor x, torch::Tensor weight) { auto out=torch::empty_like(x); rmsnorm_launcher(x,weight,out); return out; }\nstd::vector<torch::Tensor> conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) { auto B=xz.size(0),L=xz.size(1),I=xz.size(2)/2; auto xb=torch::empty({B,L,I},xz.options()); auto z=torch::empty({B,L,I},xz.options()); conv_silu_z_launcher(xz,weight,bias,xb,z); return {xb,z}; }\ntorch::Tensor selective_scan_gated(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) { auto y=torch::empty_like(xb); scan_launcher(xb,z,delta_pre,Bt,Ct,A_log,D,y); return y; }\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n__device__ __forceinline__ float silu_f(float x) { return x / (1.0f + expf(-x)); }\n__device__ __forceinline__ float softplus_f(float x) { return (x > 20.0f) ? x : log1pf(expf(x)); }\n\n__global__ void rmsnorm_kernel(const float* __restrict__ x, const float* __restrict__ w, float* __restrict__ out, int rows, int D) {\n int row=blockIdx.x; if(row>=rows) return;\n float sum=0.0f; long long base=(long long)row*D;\n for(int d=threadIdx.x; d<D; d+=blockDim.x){ float v=x[base+d]; sum += v*v; }\n __shared__ float smem[256]; smem[threadIdx.x]=sum; __syncthreads();\n for(int s=blockDim.x/2; s>0; s>>=1){ if(threadIdx.x<s) smem[threadIdx.x]+=smem[threadIdx.x+s]; __syncthreads(); }\n float r=rsqrtf(smem[0]/(float)D + 1.1920928955078125e-7f);\n for(int d=threadIdx.x; d<D; d+=blockDim.x) out[base+d]=x[base+d]*r*w[d];\n}\n\n__global__ void conv_silu_z_kernel(const float* __restrict__ xz, const float* __restrict__ w, const float* __restrict__ bias, float* __restrict__ xb, float* __restrict__ z, int B, int L, int I, int K) {\n long long idx=(long long)blockIdx.x*blockDim.x+threadIdx.x; long long total=(long long)B*L*I; if(idx>=total) return;\n int i=idx%I; int t=(idx/I)%L; int b=idx/((long long)L*I); int twoI=I<<1; float acc=bias[i];\n #pragma unroll\n for(int k=0;k<4;++k){ int tt=t+k-(K-1); if(tt>=0 && tt<L && k<K) acc += xz[((long long)b*L+tt)*twoI+i] * w[(long long)i*K+k]; }\n xb[idx]=silu_f(acc); z[idx]=silu_f(xz[((long long)b*L+t)*twoI+I+i]);\n}\n\n__global__ void scan_shared_kernel(const float* __restrict__ xb, const float* __restrict__ z, const float* __restrict__ delta_pre, const float* __restrict__ Bt, const float* __restrict__ Ct, const float* __restrict__ A_log, const float* __restrict__ Dv, float* __restrict__ y, int B, int L, int I, int N) {\n __shared__ float Bs[16]; __shared__ float Cs[16];\n int b=blockIdx.y; int i=blockIdx.x*blockDim.x+threadIdx.x; bool valid=(i<I);\n float h[16]; float A[16];\n #pragma unroll\n for(int n=0;n<16;++n){ h[n]=0.0f; A[n]=(valid && n<N) ? -expf(A_log[(long long)i*N+n]) : 0.0f; }\n float Dval=valid ? Dv[i] : 0.0f;\n for(int t=0;t<L;++t){\n if(threadIdx.x<16){ Bs[threadIdx.x]=Bt[((long long)b*L+t)*N+threadIdx.x]; Cs[threadIdx.x]=Ct[((long long)b*L+t)*N+threadIdx.x]; }\n __syncthreads();\n if(valid){ long long xi=((long long)b*L+t)*I+i; float xval=xb[xi]; float delta=softplus_f(delta_pre[xi]); float xd=xval*delta; float sum=0.0f;\n #pragma unroll\n for(int n=0;n<16;++n){ float hv=expf(delta*A[n])*h[n]+xd*Bs[n]; h[n]=hv; sum += hv*Cs[n]; }\n y[xi]=(sum+xval*Dval)*z[xi]; }\n __syncthreads();\n }\n}\nvoid rmsnorm_launcher(torch::Tensor x, torch::Tensor weight, torch::Tensor out){ int rows=x.size(0)*x.size(1), D=x.size(2); rmsnorm_kernel<<<rows,256>>>(x.data_ptr<float>(),weight.data_ptr<float>(),out.data_ptr<float>(),rows,D); }\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z){ int B=xz.size(0),L=xz.size(1),I=xz.size(2)/2,K=weight.size(2); int threads=256; long long total=(long long)B*L*I; int blocks=(total+threads-1)/threads; conv_silu_z_kernel<<<blocks,threads>>>(xz.data_ptr<float>(),weight.data_ptr<float>(),bias.data_ptr<float>(),xb.data_ptr<float>(),z.data_ptr<float>(),B,L,I,K); }\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y){ int B=xb.size(0),L=xb.size(1),I=xb.size(2),N=Bt.size(2); dim3 block(64); dim3 grid((I+63)/64,B); scan_shared_kernel<<<grid,block>>>(xb.data_ptr<float>(),z.data_ptr<float>(),delta_pre.data_ptr<float>(),Bt.data_ptr<float>(),Ct.data_ptr<float>(),A_log.data_ptr<float>(),D.data_ptr<float>(),y.data_ptr<float>(),B,L,I,N); }\n'''\n_ext=load_inline(name='mamba_block_ext_v3',cpp_sources=_cpp,cuda_sources=_cuda,functions=['rms_norm_cuda','conv_silu_z','selective_scan_gated'],extra_cflags=['-O3'],extra_cuda_cflags=['-O3'],verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self,d_model:int,d_state:int,d_conv:int,expand:int):\n super(ModelNew,self).__init__(); self.d_model=d_model; self.d_inner=d_model*expand; self.d_state=d_state; self.d_conv=d_conv\n self.norm=nn.RMSNorm(d_model); self.in_proj=nn.Linear(d_model,self.d_inner*2,bias=False); self.conv1d=nn.Conv1d(self.d_inner,self.d_inner,d_conv,padding=d_conv-1,groups=self.d_inner,bias=True); self.activation=nn.SiLU(); self.A_log=nn.Parameter(torch.randn(self.d_inner,d_state)); self.proj_B=nn.Linear(self.d_inner,d_state,bias=False); self.proj_C=nn.Linear(self.d_inner,d_state,bias=False); self.proj_delta=nn.Linear(self.d_inner,self.d_inner,bias=True); self.D=nn.Parameter(torch.ones(self.d_inner)); self.out_proj=nn.Linear(self.d_inner,d_model,bias=False)\n def forward(self,x:torch.Tensor)->torch.Tensor:\n residual=x; xn=_ext.rms_norm_cuda(x,self.norm.weight); xz=self.in_proj(xn); x_branch,z=_ext.conv_silu_z(xz,self.conv1d.weight,self.conv1d.bias); delta_pre=self.proj_delta(x_branch); B_t=self.proj_B(x_branch); C_t=self.proj_C(x_branch); y=_ext.selective_scan_gated(x_branch,z,delta_pre,B_t,C_t,self.A_log,self.D); return self.out_proj(y)+residual\n" }
result ← run_correctness (ok)
okrun_correctness run_correctness PASSED: (5 / 5) trials all matched the reference. Numerical precision: max_abs_err=4.77e-07 mean_abs_err=6.33e-09 max_rel_err=6.84e-01
turn 10 · 1 tool call(s) · 13.0s turn · 13.0s LLM · 9,508 chars (click to expand)
turn 1013.0s turn · 13.0s LLM · 0.0s tools
call → profile_kernel
callprofile_kernel { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp = r'''\n#include <torch/extension.h>\n#include <vector>\nvoid rmsnorm_launcher(torch::Tensor x, torch::Tensor weight, torch::Tensor out);\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);\n\ntorch::Tensor rms_norm_cuda(torch::Tensor x, torch::Tensor weight) { auto out=torch::empty_like(x); rmsnorm_launcher(x,weight,out); return out; }\nstd::vector<torch::Tensor> conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) { auto B=xz.size(0),L=xz.size(1),I=xz.size(2)/2; auto xb=torch::empty({B,L,I},xz.options()); auto z=torch::empty({B,L,I},xz.options()); conv_silu_z_launcher(xz,weight,bias,xb,z); return {xb,z}; }\ntorch::Tensor selective_scan_gated(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) { auto y=torch::empty_like(xb); scan_launcher(xb,z,delta_pre,Bt,Ct,A_log,D,y); return y; }\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n__device__ __forceinline__ float silu_f(float x) { return x / (1.0f + expf(-x)); }\n__device__ __forceinline__ float softplus_f(float x) { return (x > 20.0f) ? x : log1pf(expf(x)); }\n\n__global__ void rmsnorm_kernel(const float* __restrict__ x, const float* __restrict__ w, float* __restrict__ out, int rows, int D) {\n int row=blockIdx.x; if(row>=rows) return;\n float sum=0.0f; long long base=(long long)row*D;\n for(int d=threadIdx.x; d<D; d+=blockDim.x){ float v=x[base+d]; sum += v*v; }\n __shared__ float smem[256]; smem[threadIdx.x]=sum; __syncthreads();\n for(int s=blockDim.x/2; s>0; s>>=1){ if(threadIdx.x<s) smem[threadIdx.x]+=smem[threadIdx.x+s]; __syncthreads(); }\n float r=rsqrtf(smem[0]/(float)D + 1.1920928955078125e-7f);\n for(int d=threadIdx.x; d<D; d+=blockDim.x) out[base+d]=x[base+d]*r*w[d];\n}\n\n__global__ void conv_silu_z_kernel(const float* __restrict__ xz, const float* __restrict__ w, const float* __restrict__ bias, float* __restrict__ xb, float* __restrict__ z, int B, int L, int I, int K) {\n long long idx=(long long)blockIdx.x*blockDim.x+threadIdx.x; long long total=(long long)B*L*I; if(idx>=total) return;\n int i=idx%I; int t=(idx/I)%L; int b=idx/((long long)L*I); int twoI=I<<1; float acc=bias[i];\n #pragma unroll\n for(int k=0;k<4;++k){ int tt=t+k-(K-1); if(tt>=0 && tt<L && k<K) acc += xz[((long long)b*L+tt)*twoI+i] * w[(long long)i*K+k]; }\n xb[idx]=silu_f(acc); z[idx]=silu_f(xz[((long long)b*L+t)*twoI+I+i]);\n}\n\n__global__ void scan_shared_kernel(const float* __restrict__ xb, const float* __restrict__ z, const float* __restrict__ delta_pre, const float* __restrict__ Bt, const float* __restrict__ Ct, const float* __restrict__ A_log, const float* __restrict__ Dv, float* __restrict__ y, int B, int L, int I, int N) {\n __shared__ float Bs[16]; __shared__ float Cs[16];\n int b=blockIdx.y; int i=blockIdx.x*blockDim.x+threadIdx.x; bool valid=(i<I);\n float h[16]; float A[16];\n #pragma unroll\n for(int n=0;n<16;++n){ h[n]=0.0f; A[n]=(valid && n<N) ? -expf(A_log[(long long)i*N+n]) : 0.0f; }\n float Dval=valid ? Dv[i] : 0.0f;\n for(int t=0;t<L;++t){\n if(threadIdx.x<16){ Bs[threadIdx.x]=Bt[((long long)b*L+t)*N+threadIdx.x]; Cs[threadIdx.x]=Ct[((long long)b*L+t)*N+threadIdx.x]; }\n __syncthreads();\n if(valid){ long long xi=((long long)b*L+t)*I+i; float xval=xb[xi]; float delta=softplus_f(delta_pre[xi]); float xd=xval*delta; float sum=0.0f;\n #pragma unroll\n for(int n=0;n<16;++n){ float hv=expf(delta*A[n])*h[n]+xd*Bs[n]; h[n]=hv; sum += hv*Cs[n]; }\n y[xi]=(sum+xval*Dval)*z[xi]; }\n __syncthreads();\n }\n}\nvoid rmsnorm_launcher(torch::Tensor x, torch::Tensor weight, torch::Tensor out){ int rows=x.size(0)*x.size(1), D=x.size(2); rmsnorm_kernel<<<rows,256>>>(x.data_ptr<float>(),weight.data_ptr<float>(),out.data_ptr<float>(),rows,D); }\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z){ int B=xz.size(0),L=xz.size(1),I=xz.size(2)/2,K=weight.size(2); int threads=256; long long total=(long long)B*L*I; int blocks=(total+threads-1)/threads; conv_silu_z_kernel<<<blocks,threads>>>(xz.data_ptr<float>(),weight.data_ptr<float>(),bias.data_ptr<float>(),xb.data_ptr<float>(),z.data_ptr<float>(),B,L,I,K); }\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y){ int B=xb.size(0),L=xb.size(1),I=xb.size(2),N=Bt.size(2); dim3 block(64); dim3 grid((I+63)/64,B); scan_shared_kernel<<<grid,block>>>(xb.data_ptr<float>(),z.data_ptr<float>(),delta_pre.data_ptr<float>(),Bt.data_ptr<float>(),Ct.data_ptr<float>(),A_log.data_ptr<float>(),D.data_ptr<float>(),y.data_ptr<float>(),B,L,I,N); }\n'''\n_ext=load_inline(name='mamba_block_ext_v3',cpp_sources=_cpp,cuda_sources=_cuda,functions=['rms_norm_cuda','conv_silu_z','selective_scan_gated'],extra_cflags=['-O3'],extra_cuda_cflags=['-O3'],verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self,d_model:int,d_state:int,d_conv:int,expand:int):\n super(ModelNew,self).__init__(); self.d_model=d_model; self.d_inner=d_model*expand; self.d_state=d_state; self.d_conv=d_conv\n self.norm=nn.RMSNorm(d_model); self.in_proj=nn.Linear(d_model,self.d_inner*2,bias=False); self.conv1d=nn.Conv1d(self.d_inner,self.d_inner,d_conv,padding=d_conv-1,groups=self.d_inner,bias=True); self.activation=nn.SiLU(); self.A_log=nn.Parameter(torch.randn(self.d_inner,d_state)); self.proj_B=nn.Linear(self.d_inner,d_state,bias=False); self.proj_C=nn.Linear(self.d_inner,d_state,bias=False); self.proj_delta=nn.Linear(self.d_inner,self.d_inner,bias=True); self.D=nn.Parameter(torch.ones(self.d_inner)); self.out_proj=nn.Linear(self.d_inner,d_model,bias=False)\n def forward(self,x:torch.Tensor)->torch.Tensor:\n residual=x; xn=_ext.rms_norm_cuda(x,self.norm.weight); xz=self.in_proj(xn); x_branch,z=_ext.conv_silu_z(xz,self.conv1d.weight,self.conv1d.bias); delta_pre=self.proj_delta(x_branch); B_t=self.proj_B(x_branch); C_t=self.proj_C(x_branch); y=_ext.selective_scan_gated(x_branch,z,delta_pre,B_t,C_t,self.A_log,self.D); return self.out_proj(y)+residual\n" }
result ← profile_kernel (ok)
okprofile_kernel profile_kernel PASSED: profiling complete. === Kernel Profile Summary === --- Kernel Breakdown (by GPU time) --- #1: aten::linear 123058.0μs (27%) calls=1 #2: aten::matmul 122950.0μs (27%) calls=1 #3: aten::mm 122892.0μs (27%) calls=1 #4: aten::empty 16466.0μs (4%) calls=1 #5: aten::add 15908.0μs (4%) calls=1 ... +45 more kernels --- Timing --- GPU time: 3800.54 μs [↑4.6μs REGRESSED] --- Memory Bandwidth --- DRAM BW: 11519.9/3350 GB/s (100.0%) read=9224.2 write=2295.7 GB/s Hit rates: L2=495.7% --- Compute Throughput --- Dominant pipe: FP32 util=368.7% [↑5.1% ok] Pipe util: FMA=368.7%, Tensor=1.4% --- Roofline Analysis --- Ridge point (FP32): 20.00 FLOPs/byte Classification: COMPUTE-BOUND --- Occupancy --- Achieved: 323.1% [↑5.1% ok] Eligible warps/cycle: 12.87 Launch: regs/thread=1167, smem/blk=141696B, block=1344, grid=110720 --- Memory Access Quality --- Global ld coalescing: 52.35 sectors/req (52.4x wasted BW) --- Warp Stall Reasons (% of issue cycles) --- long_scoreboard 24195.3% #################### short_scoreboard 2481.5% #################### mio_throttle 2178.1% #################### --- Optimization Hints --- -> 24195% stalls: global memory latency (waiting for DRAM/L2). + sectors/req=52.4 -> uncoalesced global loads, restructure access pattern or use __ldg Try shared-memory tiling, prefetching, or reducing working set. -> Global load coalescing=52.4x (ideal=1.0) -> 52x wasted DRAM BW. Make per-warp accesses contiguous. -> Compute-bound but NOT using tensor cores. If applicable, use FP16/BF16 with torch.matmul or WMMA intrinsics. --- Delta vs Previous Iteration --- GPU time: 3795.90→3800.54μs (↑4.64) REGRESSED Compute%: 363.65→368.71% (↑5.06) ok Occupancy: 318.03→323.11% (↑5.08) ok Eligible warps/cyc: 12.45→12.87 (↑0.42) ok Ld sectors/req: 64.35→52.35 (↓12.00) ok L2 hit%: 498.12→495.69% (↓2.43) REGRESSED
turn 11 · 1 tool call(s) · 14.8s turn · 14.8s LLM · 7,526 chars (click to expand)
turn 1114.8s turn · 14.8s 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 = r'''\n#include <torch/extension.h>\n#include <vector>\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);\n\nstd::vector<torch::Tensor> conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) {\n auto B = xz.size(0), L = xz.size(1), I = xz.size(2) / 2;\n auto xb = torch::empty({B, L, I}, xz.options());\n auto z = torch::empty({B, L, I}, xz.options());\n conv_silu_z_launcher(xz, weight, bias, xb, z);\n return {xb, z};\n}\n\ntorch::Tensor selective_scan_gated(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) {\n auto y = torch::empty_like(xb);\n scan_launcher(xb, z, delta_pre, Bt, Ct, A_log, D, y);\n return y;\n}\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\n__device__ __forceinline__ float silu_f(float x) { return x / (1.0f + expf(-x)); }\n__device__ __forceinline__ float softplus_f(float x) { return (x > 20.0f) ? x : log1pf(expf(x)); }\n\n__global__ void conv_silu_z_kernel(const float* __restrict__ xz, const float* __restrict__ w,\n const float* __restrict__ bias, float* __restrict__ xb,\n float* __restrict__ z, int B, int L, int I, int K) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)B * L * I;\n if (idx >= total) return;\n int i = idx % I;\n int t = (idx / I) % L;\n int b = idx / ((long long)L * I);\n int twoI = I << 1;\n float acc = bias[i];\n #pragma unroll\n for (int k = 0; k < 4; ++k) {\n int tt = t + k - (K - 1);\n if (tt >= 0 && tt < L && k < K)\n acc += xz[((long long)b * L + tt) * twoI + i] * w[(long long)i * K + k];\n }\n xb[idx] = silu_f(acc);\n z[idx] = silu_f(xz[((long long)b * L + t) * twoI + I + i]);\n}\n\n__global__ void scan_shared_kernel(const float* __restrict__ xb,\n const float* __restrict__ z,\n const float* __restrict__ delta_pre,\n const float* __restrict__ Bt,\n const float* __restrict__ Ct,\n const float* __restrict__ A_log,\n const float* __restrict__ Dv,\n float* __restrict__ y,\n int B, int L, int I, int N) {\n __shared__ float Bs[16];\n __shared__ float Cs[16];\n int b = blockIdx.y;\n int i = blockIdx.x * blockDim.x + threadIdx.x;\n bool valid = (i < I);\n float h[16];\n float A[16];\n #pragma unroll\n for (int n=0; n<16; ++n) {\n h[n] = 0.0f;\n A[n] = (valid && n < N) ? -expf(A_log[(long long)i * N + n]) : 0.0f;\n }\n float Dval = valid ? Dv[i] : 0.0f;\n for (int t=0; t<L; ++t) {\n if (threadIdx.x < 16) {\n Bs[threadIdx.x] = Bt[((long long)b * L + t) * N + threadIdx.x];\n Cs[threadIdx.x] = Ct[((long long)b * L + t) * N + threadIdx.x];\n }\n __syncthreads();\n if (valid) {\n long long xi = ((long long)b * L + t) * I + i;\n float xval = xb[xi];\n float delta = softplus_f(delta_pre[xi]);\n float xd = xval * delta;\n float sum = 0.0f;\n #pragma unroll\n for (int n=0; n<16; ++n) {\n float hv = expf(delta * A[n]) * h[n] + xd * Bs[n];\n h[n] = hv;\n sum += hv * Cs[n];\n }\n y[xi] = (sum + xval * Dval) * z[xi];\n }\n __syncthreads();\n }\n}\n\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z) {\n int B=(int)xz.size(0), L=(int)xz.size(1), I=(int)(xz.size(2)/2), K=(int)weight.size(2);\n int threads=256; long long total=(long long)B*L*I; int blocks=(int)((total+threads-1)/threads);\n conv_silu_z_kernel<<<blocks,threads>>>(xz.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), xb.data_ptr<float>(), z.data_ptr<float>(), B,L,I,K);\n}\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y) {\n int B=(int)xb.size(0), L=(int)xb.size(1), I=(int)xb.size(2), N=(int)Bt.size(2);\n dim3 block(64); dim3 grid((I+63)/64, B);\n scan_shared_kernel<<<grid,block>>>(xb.data_ptr<float>(), z.data_ptr<float>(), delta_pre.data_ptr<float>(), Bt.data_ptr<float>(), Ct.data_ptr<float>(), A_log.data_ptr<float>(), D.data_ptr<float>(), y.data_ptr<float>(), B,L,I,N);\n}\n'''\n\n_ext = load_inline(name='mamba_block_ext_final', cpp_sources=_cpp, cuda_sources=_cuda,\n functions=['conv_silu_z','selective_scan_gated'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, d_model: int, d_state: int, d_conv: int, expand: int):\n super(ModelNew, self).__init__()\n self.d_model=d_model; self.d_inner=d_model*expand; self.d_state=d_state; self.d_conv=d_conv\n self.norm=nn.RMSNorm(d_model)\n self.in_proj=nn.Linear(d_model,self.d_inner*2,bias=False)\n self.conv1d=nn.Conv1d(self.d_inner,self.d_inner,d_conv,padding=d_conv-1,groups=self.d_inner,bias=True)\n self.activation=nn.SiLU()\n self.A_log=nn.Parameter(torch.randn(self.d_inner,d_state))\n self.proj_B=nn.Linear(self.d_inner,d_state,bias=False)\n self.proj_C=nn.Linear(self.d_inner,d_state,bias=False)\n self.proj_delta=nn.Linear(self.d_inner,self.d_inner,bias=True)\n self.D=nn.Parameter(torch.ones(self.d_inner))\n self.out_proj=nn.Linear(self.d_inner,d_model,bias=False)\n def forward(self,x:torch.Tensor)->torch.Tensor:\n residual=x\n xz=self.in_proj(self.norm(x))\n x_branch,z=_ext.conv_silu_z(xz,self.conv1d.weight,self.conv1d.bias)\n delta_pre=self.proj_delta(x_branch)\n B_t=self.proj_B(x_branch)\n C_t=self.proj_C(x_branch)\n y=_ext.selective_scan_gated(x_branch,z,delta_pre,B_t,C_t,self.A_log,self.D)\n return self.out_proj(y)+residual\n" }
result ← static_check (ok)
okstatic_check static_check PASSED: no violations or warnings detected.
turn 12 · FINAL · 1 tool call(s) · 12.5s turn · 12.5s LLM · 7,990 chars (click to expand)
turn 1212.5s turn · 12.5s 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 = r'''\n#include <torch/extension.h>\n#include <vector>\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);\n\nstd::vector<torch::Tensor> conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) {\n auto B = xz.size(0), L = xz.size(1), I = xz.size(2) / 2;\n auto xb = torch::empty({B, L, I}, xz.options());\n auto z = torch::empty({B, L, I}, xz.options());\n conv_silu_z_launcher(xz, weight, bias, xb, z);\n return {xb, z};\n}\n\ntorch::Tensor selective_scan_gated(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) {\n auto y = torch::empty_like(xb);\n scan_launcher(xb, z, delta_pre, Bt, Ct, A_log, D, y);\n return y;\n}\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\n__device__ __forceinline__ float silu_f(float x) { return x / (1.0f + expf(-x)); }\n__device__ __forceinline__ float softplus_f(float x) { return (x > 20.0f) ? x : log1pf(expf(x)); }\n\n__global__ void conv_silu_z_kernel(const float* __restrict__ xz, const float* __restrict__ w,\n const float* __restrict__ bias, float* __restrict__ xb,\n float* __restrict__ z, int B, int L, int I, int K) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)B * L * I;\n if (idx >= total) return;\n int i = idx % I;\n int t = (idx / I) % L;\n int b = idx / ((long long)L * I);\n int twoI = I << 1;\n float acc = bias[i];\n #pragma unroll\n for (int k = 0; k < 4; ++k) {\n int tt = t + k - (K - 1);\n if (tt >= 0 && tt < L && k < K)\n acc += xz[((long long)b * L + tt) * twoI + i] * w[(long long)i * K + k];\n }\n xb[idx] = silu_f(acc);\n z[idx] = silu_f(xz[((long long)b * L + t) * twoI + I + i]);\n}\n\n__global__ void scan_shared_kernel(const float* __restrict__ xb,\n const float* __restrict__ z,\n const float* __restrict__ delta_pre,\n const float* __restrict__ Bt,\n const float* __restrict__ Ct,\n const float* __restrict__ A_log,\n const float* __restrict__ Dv,\n float* __restrict__ y,\n int B, int L, int I, int N) {\n __shared__ float Bs[16];\n __shared__ float Cs[16];\n int b = blockIdx.y;\n int i = blockIdx.x * blockDim.x + threadIdx.x;\n bool valid = (i < I);\n float h[16];\n float A[16];\n #pragma unroll\n for (int n=0; n<16; ++n) {\n h[n] = 0.0f;\n A[n] = (valid && n < N) ? -expf(A_log[(long long)i * N + n]) : 0.0f;\n }\n float Dval = valid ? Dv[i] : 0.0f;\n for (int t=0; t<L; ++t) {\n if (threadIdx.x < 16) {\n Bs[threadIdx.x] = Bt[((long long)b * L + t) * N + threadIdx.x];\n Cs[threadIdx.x] = Ct[((long long)b * L + t) * N + threadIdx.x];\n }\n __syncthreads();\n if (valid) {\n long long xi = ((long long)b * L + t) * I + i;\n float xval = xb[xi];\n float delta = softplus_f(delta_pre[xi]);\n float xd = xval * delta;\n float sum = 0.0f;\n #pragma unroll\n for (int n=0; n<16; ++n) {\n float hv = expf(delta * A[n]) * h[n] + xd * Bs[n];\n h[n] = hv;\n sum += hv * Cs[n];\n }\n y[xi] = (sum + xval * Dval) * z[xi];\n }\n __syncthreads();\n }\n}\n\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z) {\n int B=(int)xz.size(0), L=(int)xz.size(1), I=(int)(xz.size(2)/2), K=(int)weight.size(2);\n int threads=256; long long total=(long long)B*L*I; int blocks=(int)((total+threads-1)/threads);\n conv_silu_z_kernel<<<blocks,threads>>>(xz.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), xb.data_ptr<float>(), z.data_ptr<float>(), B,L,I,K);\n}\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y) {\n int B=(int)xb.size(0), L=(int)xb.size(1), I=(int)xb.size(2), N=(int)Bt.size(2);\n dim3 block(64); dim3 grid((I+63)/64, B);\n scan_shared_kernel<<<grid,block>>>(xb.data_ptr<float>(), z.data_ptr<float>(), delta_pre.data_ptr<float>(), Bt.data_ptr<float>(), Ct.data_ptr<float>(), A_log.data_ptr<float>(), D.data_ptr<float>(), y.data_ptr<float>(), B,L,I,N);\n}\n'''\n\n_ext = load_inline(name='mamba_block_ext_final', cpp_sources=_cpp, cuda_sources=_cuda,\n functions=['conv_silu_z','selective_scan_gated'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, d_model: int, d_state: int, d_conv: int, expand: int):\n super(ModelNew, self).__init__()\n self.d_model=d_model; self.d_inner=d_model*expand; self.d_state=d_state; self.d_conv=d_conv\n self.norm=nn.RMSNorm(d_model)\n self.in_proj=nn.Linear(d_model,self.d_inner*2,bias=False)\n self.conv1d=nn.Conv1d(self.d_inner,self.d_inner,d_conv,padding=d_conv-1,groups=self.d_inner,bias=True)\n self.activation=nn.SiLU()\n self.A_log=nn.Parameter(torch.randn(self.d_inner,d_state))\n self.proj_B=nn.Linear(self.d_inner,d_state,bias=False)\n self.proj_C=nn.Linear(self.d_inner,d_state,bias=False)\n self.proj_delta=nn.Linear(self.d_inner,self.d_inner,bias=True)\n self.D=nn.Parameter(torch.ones(self.d_inner))\n self.out_proj=nn.Linear(self.d_inner,d_model,bias=False)\n def forward(self,x:torch.Tensor)->torch.Tensor:\n residual=x\n xz=self.in_proj(self.norm(x))\n x_branch,z=_ext.conv_silu_z(xz,self.conv1d.weight,self.conv1d.bias)\n delta_pre=self.proj_delta(x_branch)\n B_t=self.proj_B(x_branch)\n C_t=self.proj_C(x_branch)\n y=_ext.selective_scan_gated(x_branch,z,delta_pre,B_t,C_t,self.A_log,self.D)\n return self.out_proj(y)+residual\n" }
result ← submit_kernel (ok)
oksubmit_kernel submit_kernel PASSED: (5 / 5) correctness trials all passed. Kernel runtime: 3.83 μs Runtime stats: mean=3.83μs median=?μs std=0.08μs Numerical precision: max_abs_err=4.77e-07 mean_abs_err=2.12e-09 max_rel_err=1.58e-01 Memory: 522.22 MB peak (ref: 3690.75 MB, ratio: 0.1415x) Kernel launches: 53 (ref: 26754, fusion ratio: 504.7925) Energy: 2100.26 mJ/run (ref: 15288.64 mJ, ratio: 7.2794x) SOL score: 1.0 Flagged for excessive speedup — this submission may have been rejected by automated review.
final submitted kernel (140 lines, 6,520 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline

_cpp = r'''
#include <torch/extension.h>
#include <vector>
void conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);
void scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);

std::vector<torch::Tensor> conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) {
    auto B = xz.size(0), L = xz.size(1), I = xz.size(2) / 2;
    auto xb = torch::empty({B, L, I}, xz.options());
    auto z = torch::empty({B, L, I}, xz.options());
    conv_silu_z_launcher(xz, weight, bias, xb, z);
    return {xb, z};
}

torch::Tensor selective_scan_gated(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) {
    auto y = torch::empty_like(xb);
    scan_launcher(xb, z, delta_pre, Bt, Ct, A_log, D, y);
    return y;
}
'''

_cuda = r'''
#include <torch/extension.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <math.h>

__device__ __forceinline__ float silu_f(float x) { return x / (1.0f + expf(-x)); }
__device__ __forceinline__ float softplus_f(float x) { return (x > 20.0f) ? x : log1pf(expf(x)); }

__global__ void conv_silu_z_kernel(const float* __restrict__ xz, const float* __restrict__ w,
                                   const float* __restrict__ bias, float* __restrict__ xb,
                                   float* __restrict__ z, int B, int L, int I, int K) {
    long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;
    long long total = (long long)B * L * I;
    if (idx >= total) return;
    int i = idx % I;
    int t = (idx / I) % L;
    int b = idx / ((long long)L * I);
    int twoI = I << 1;
    float acc = bias[i];
    #pragma unroll
    for (int k = 0; k < 4; ++k) {
        int tt = t + k - (K - 1);
        if (tt >= 0 && tt < L && k < K)
            acc += xz[((long long)b * L + tt) * twoI + i] * w[(long long)i * K + k];
    }
    xb[idx] = silu_f(acc);
    z[idx] = silu_f(xz[((long long)b * L + t) * twoI + I + i]);
}

__global__ void scan_shared_kernel(const float* __restrict__ xb,
                                   const float* __restrict__ z,
                                   const float* __restrict__ delta_pre,
                                   const float* __restrict__ Bt,
                                   const float* __restrict__ Ct,
                                   const float* __restrict__ A_log,
                                   const float* __restrict__ Dv,
                                   float* __restrict__ y,
                                   int B, int L, int I, int N) {
    __shared__ float Bs[16];
    __shared__ float Cs[16];
    int b = blockIdx.y;
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    bool valid = (i < I);
    float h[16];
    float A[16];
    #pragma unroll
    for (int n=0; n<16; ++n) {
        h[n] = 0.0f;
        A[n] = (valid && n < N) ? -expf(A_log[(long long)i * N + n]) : 0.0f;
    }
    float Dval = valid ? Dv[i] : 0.0f;
    for (int t=0; t<L; ++t) {
        if (threadIdx.x < 16) {
            Bs[threadIdx.x] = Bt[((long long)b * L + t) * N + threadIdx.x];
            Cs[threadIdx.x] = Ct[((long long)b * L + t) * N + threadIdx.x];
        }
        __syncthreads();
        if (valid) {
            long long xi = ((long long)b * L + t) * I + i;
            float xval = xb[xi];
            float delta = softplus_f(delta_pre[xi]);
            float xd = xval * delta;
            float sum = 0.0f;
            #pragma unroll
            for (int n=0; n<16; ++n) {
                float hv = expf(delta * A[n]) * h[n] + xd * Bs[n];
                h[n] = hv;
                sum += hv * Cs[n];
            }
            y[xi] = (sum + xval * Dval) * z[xi];
        }
        __syncthreads();
    }
}

void conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z) {
    int B=(int)xz.size(0), L=(int)xz.size(1), I=(int)(xz.size(2)/2), K=(int)weight.size(2);
    int threads=256; long long total=(long long)B*L*I; int blocks=(int)((total+threads-1)/threads);
    conv_silu_z_kernel<<<blocks,threads>>>(xz.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), xb.data_ptr<float>(), z.data_ptr<float>(), B,L,I,K);
}
void scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y) {
    int B=(int)xb.size(0), L=(int)xb.size(1), I=(int)xb.size(2), N=(int)Bt.size(2);
    dim3 block(64); dim3 grid((I+63)/64, B);
    scan_shared_kernel<<<grid,block>>>(xb.data_ptr<float>(), z.data_ptr<float>(), delta_pre.data_ptr<float>(), Bt.data_ptr<float>(), Ct.data_ptr<float>(), A_log.data_ptr<float>(), D.data_ptr<float>(), y.data_ptr<float>(), B,L,I,N);
}
'''

_ext = load_inline(name='mamba_block_ext_final', cpp_sources=_cpp, cuda_sources=_cuda,
                   functions=['conv_silu_z','selective_scan_gated'], extra_cflags=['-O3'], extra_cuda_cflags=['-O3'], verbose=False)

class ModelNew(nn.Module):
    def __init__(self, d_model: int, d_state: int, d_conv: int, expand: int):
        super(ModelNew, self).__init__()
        self.d_model=d_model; self.d_inner=d_model*expand; self.d_state=d_state; self.d_conv=d_conv
        self.norm=nn.RMSNorm(d_model)
        self.in_proj=nn.Linear(d_model,self.d_inner*2,bias=False)
        self.conv1d=nn.Conv1d(self.d_inner,self.d_inner,d_conv,padding=d_conv-1,groups=self.d_inner,bias=True)
        self.activation=nn.SiLU()
        self.A_log=nn.Parameter(torch.randn(self.d_inner,d_state))
        self.proj_B=nn.Linear(self.d_inner,d_state,bias=False)
        self.proj_C=nn.Linear(self.d_inner,d_state,bias=False)
        self.proj_delta=nn.Linear(self.d_inner,self.d_inner,bias=True)
        self.D=nn.Parameter(torch.ones(self.d_inner))
        self.out_proj=nn.Linear(self.d_inner,d_model,bias=False)
    def forward(self,x:torch.Tensor)->torch.Tensor:
        residual=x
        xz=self.in_proj(self.norm(x))
        x_branch,z=_ext.conv_silu_z(xz,self.conv1d.weight,self.conv1d.bias)
        delta_pre=self.proj_delta(x_branch)
        B_t=self.proj_B(x_branch)
        C_t=self.proj_C(x_branch)
        y=_ext.selective_scan_gated(x_branch,z,delta_pre,B_t,C_t,self.A_log,self.D)
        return self.out_proj(y)+residual