gpt-5.5-priority · popcorn · l3_default_gpt
correct 3_SSM2D_FusedBidirectionalCrossScan.py
model
gpt-5.5-priority
turns / max
11 / 15
tool calls
11
tokens (total)
0
wall clock
—
truncated
no
backend
cuda fp32
variant
popcorn
runtime
0.01 μs
ref runtime
0.15 μs
speedup
14.85x
started
2026-05-04T21:25:28Z
timingkernelbench.timing
kernel runtime
0.01 μs
ref runtime
0.15 μs
speedup
14.85x
kernel mean / median / std
0.01 / — / 0.02 μs
ref mean / median / std
0.15 / — / 0.07 μs
numerical precisioneval_kernel_against_ref
max abs error
1.91e-06
mean abs error
9.25e-08
max rel error
0.33
mean rel error
5.42e-07
gpu memoryextended_metrics.measure_memory
kernel peak
35.00 MB
ref peak
42.00 MB
kernel / ref
0.83x
kernel launches / fusiontorch.profiler
kernel launches
2
ref launches
114
fusion ratio (ref / kernel)
57.00x
total cuda time
13 μs
SOL (speed-of-light)nsight_hardware_counters
SOL score (0–1)
0.094
dram util %
6.6%
compute util %
9.4%
bottleneck
compute-bound
dominant pipe
FP32
arithmetic intensity
—
ridge point
20.00
roofline / occupancynsight_hardware_counters
dram bandwidth
221.21 GB/s
dram util %
6.6%
fp32 tflops
—
fp32 util %
—
fp16 tflops
—
occupancy %
78.1%
bottleneck
compute-bound
dominant pipe %
9.4%
arithmetic intensity
—
ridge point
20.00
L1 hit %
—
L2 hit %
69.1%
ld sectors / req
2.15
st sectors / req
—
regs / thread
21
smem / block
1024 B
block size
256
peak bw
3350.00 GB/s
peak fp32 tflops
67.00
peak fp16 tflops
1979.00
warp stalls (top 5)nsight
long_scoreboard
952.8%
mio_throttle
181.7%
short_scoreboard
63.2%
flagssubmit_kernel guard
excessive speedup
flagged
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn

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


class Model(nn.Module):
    """
    Fused **2D bidirectional cross-scan** block for robotics **SSM-hybrid** backbones
    (e.g. Vision Mamba / VMamba-style encoders on overhead maps, costmaps, or
    multi-sensor tiles).

    One forward fuses four fixed scan permutations of ``(H, W)`` into 1D sequences,
    applies a **shared depthwise Conv1d** (lightweight stand-in for a selective SSM
    along the scan), maps each result back to the grid, **sums** the four
    directional contributions, and adds a **residual**.

    Scan order (same spirit as 2D cross-scan / S2D):
      LR — row-major left→right, rows top→bottom  
      RL — row-major right→left per row  
      TB — column-wise top→bottom, columns left→right  
      BT — flip vertical then same as TB  
    """

    def __init__(self, channels: int, kernel_size: int = 3):
        super().__init__()
        assert channels >= 1
        assert kernel_size % 2 == 1, "use odd kernel_size for same-length conv1d"
        self.channels = channels
        pad = kernel_size // 2
        self.dw_conv = nn.Conv1d(
            channels,
            channels,
            kernel_size,
            padding=pad,
            groups=channels,
            bias=True,
        )

    def _apply_scan_conv_unscan(self, x: torch.Tensor) -> torch.Tensor:
        """Shared depthwise conv along flattened 2D, then map back to (B,C,H,W)."""
        B, C, H, W = x.shape
        seq = x.flatten(2)
        y = self.dw_conv(seq)
        return y.view(B, C, H, W)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        """
        Args:
            x: (B, C, H, W) spatial features (map / image / fused tile).
        Returns:
            (B, C, H, W) after fused four-way cross-scan + residual.
        """
        B, C, H, W = x.shape
        assert C == self.channels

        acc = torch.zeros_like(x)

        # LR: row-major
        acc = acc + self._apply_scan_conv_unscan(x)

        # RL: flip W, scan, unflip
        xr = x.flip(dims=(-1,))
        acc = acc + self._apply_scan_conv_unscan(xr).flip(dims=(-1,))

        # TB: columns as sequences (permute to W,H, flatten)
        xt = x.permute(0, 1, 3, 2).contiguous()
        Bt, Ct, Wt, Ht = xt.shape
        seq_t = xt.flatten(2)
        yt = self.dw_conv(seq_t).view(Bt, Ct, Wt, Ht).permute(0, 1, 3, 2).contiguous()
        acc = acc + yt

        # BT: flip H then same TB path
        xb = x.flip(dims=(-2,))
        xbt = xb.permute(0, 1, 3, 2).contiguous()
        Bb, Cb, Wb, Hb = xbt.shape
        seq_b = xbt.flatten(2)
        yb = self.dw_conv(seq_b).view(Bb, Cb, Wb, Hb).permute(0, 1, 3, 2).contiguous().flip(
            dims=(-2,)
        )
        acc = acc + yb

        return x + acc


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

    def __init__(self, channels: int, kernel_size: int = 3):
        super().__init__()
        self._impl = Model(channels, kernel_size=kernel_size)

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


batch_size = 4
channels = 64
height = 32
width = 32
kernel_size = 3


def get_inputs():
    p = popcorn_pri
    x = torch.randn(p.jitter_int(batch_size), channels, p.jitter_int(height), p.jitter_int(width))
    return [x]


def get_init_inputs():
    return [channels, kernel_size]
turn 010.2s turn · 10.2s 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) · 28.2s turn · 28.2s LLM · 7,324 chars (click to expand)
turn 128.2s turn · 28.2s LLM · 0.0s tools
reasoning
**Considering C++/CUDA implementation** I need to incorporate C++ and CUDA without using pybind. I'm thinking I should use load_inline to declare the function and cuda_sources for CUDA specifics. There's a chance of compile time issues here. So, I might need to use a C++ wrapper for the torch extension and define the CUDA kernel accordingly. The function in cuda_sources should bind correctly, and I’m focused on ensuring everything runs seamlessly for optimized performance, especially for K==3 cases. **Analyzing weight shapes and indexing** I need to ensure that the weight shape is [C, 1, K] and that both the weight and bias are contiguous. Specifically, for nn.Conv1d, I can optimize for K=3 by unrolling operations. I have a formula for calculating the element index, which maps indices for width, height, channels, and batch size. The challenge lies in managing bounds across the total sequence instead of per row. For neighbor calculations, I'll derive indices carefully, especially when flipping sequences, ensuring that derived indices maintain the integrity of the original positions. **Considering code structure** I’m thinking through the logic here regarding whether `x` is non-contiguous. If it is, I’ll need to address that and use `empty_like`. If it isn't, I’ll check if `x` is already contiguous. For safety, I might use `x = x.contiguous()` to manage the output stride properly. I wonder if the reference returns as contiguous when used alongside accumulations. Alright, let’s code this up and compile it for testing!
call → compile_kernel
callcompile_kernel { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\n\ntorch::Tensor cross_scan_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n return cross_scan_forward_cuda(x, weight, bias);\n}\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__device__ __forceinline__ int spatial_from_lr(int n, int H, int W) {\n return n;\n}\n\n__device__ __forceinline__ int spatial_from_rl(int n, int H, int W) {\n int row = n / W;\n int col = n - row * W;\n return row * W + (W - 1 - col);\n}\n\n__device__ __forceinline__ int spatial_from_tb(int n, int H, int W) {\n int col = n / H;\n int row = n - col * H;\n return row * W + col;\n}\n\n__device__ __forceinline__ int spatial_from_bt(int n, int H, int W) {\n int col = n / H;\n int rowf = n - col * H;\n return (H - 1 - rowf) * W + col;\n}\n\n__global__ void cross_scan_kernel(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int B, int C, int H, int W, int K,\n int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n\n int s = tid;\n int w = s % W; s /= W;\n int h = s % H; s /= H;\n int c = s % C;\n int b = s / C;\n\n int HW = H * W;\n int bc_base = (b * C + c) * HW;\n int pos_lr = h * W + w;\n int pos_rl = h * W + (W - 1 - w);\n int pos_tb = w * H + h;\n int pos_bt = w * H + (H - 1 - h);\n int pad = K >> 1;\n const float* wx = weight + c * K;\n\n float acc = 4.0f * bias[c];\n\n // Generic odd kernel, cross-correlation, zero padding in sequence coordinates.\n #pragma unroll\n for (int kk = 0; kk < K; ++kk) {\n int off = kk - pad;\n float wk = wx[kk];\n int n;\n n = pos_lr + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_lr(n, H, W)], acc);\n n = pos_rl + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_rl(n, H, W)], acc);\n n = pos_tb + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_tb(n, H, W)], acc);\n n = pos_bt + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_bt(n, H, W)], acc);\n }\n\n y[tid] = x[tid] + acc;\n}\n\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n TORCH_CHECK(x.is_cuda(), \"x must be CUDA\");\n TORCH_CHECK(weight.is_cuda(), \"weight must be CUDA\");\n TORCH_CHECK(bias.is_cuda(), \"bias must be CUDA\");\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"only float32 supported\");\n TORCH_CHECK(weight.scalar_type() == torch::kFloat32, \"only float32 weights supported\");\n TORCH_CHECK(bias.scalar_type() == torch::kFloat32, \"only float32 bias supported\");\n TORCH_CHECK(x.is_contiguous(), \"x must be contiguous\");\n TORCH_CHECK(weight.is_contiguous(), \"weight must be contiguous\");\n TORCH_CHECK(bias.is_contiguous(), \"bias must be contiguous\");\n\n int B = (int)x.size(0);\n int C = (int)x.size(1);\n int H = (int)x.size(2);\n int W = (int)x.size(3);\n int K = (int)weight.size(2);\n int total = B * C * H * W;\n auto y = torch::empty_like(x);\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n cross_scan_kernel<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(),\n y.data_ptr<float>(), B, C, H, W, K, total);\n return y;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"cross_scan_ext_v1\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"cross_scan_forward\"],\n extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"],\n extra_cflags=[\"-O3\"],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, channels: int, kernel_size: int = 3):\n super().__init__()\n assert channels >= 1\n assert kernel_size % 2 == 1\n self.channels = channels\n pad = kernel_size // 2\n self.dw_conv = nn.Conv1d(channels, channels, kernel_size, padding=pad, groups=channels, bias=True)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n if not x.is_contiguous():\n x = x.contiguous()\n return _ext.cross_scan_forward(x, self.dw_conv.weight.contiguous(), self.dw_conv.bias.contiguous())\n" }
result ← compile_kernel (ok)
okcompile_kernel compile_kernel PASSED: kernel compiled without errors.
turn 29.0s turn · 9.0s LLM · 0.0s tools
call → run_correctness
callrun_correctness { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\n\ntorch::Tensor cross_scan_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n return cross_scan_forward_cuda(x, weight, bias);\n}\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__device__ __forceinline__ int spatial_from_lr(int n, int H, int W) {\n return n;\n}\n\n__device__ __forceinline__ int spatial_from_rl(int n, int H, int W) {\n int row = n / W;\n int col = n - row * W;\n return row * W + (W - 1 - col);\n}\n\n__device__ __forceinline__ int spatial_from_tb(int n, int H, int W) {\n int col = n / H;\n int row = n - col * H;\n return row * W + col;\n}\n\n__device__ __forceinline__ int spatial_from_bt(int n, int H, int W) {\n int col = n / H;\n int rowf = n - col * H;\n return (H - 1 - rowf) * W + col;\n}\n\n__global__ void cross_scan_kernel(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int B, int C, int H, int W, int K,\n int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n\n int s = tid;\n int w = s % W; s /= W;\n int h = s % H; s /= H;\n int c = s % C;\n int b = s / C;\n\n int HW = H * W;\n int bc_base = (b * C + c) * HW;\n int pos_lr = h * W + w;\n int pos_rl = h * W + (W - 1 - w);\n int pos_tb = w * H + h;\n int pos_bt = w * H + (H - 1 - h);\n int pad = K >> 1;\n const float* wx = weight + c * K;\n\n float acc = 4.0f * bias[c];\n\n #pragma unroll\n for (int kk = 0; kk < K; ++kk) {\n int off = kk - pad;\n float wk = wx[kk];\n int n;\n n = pos_lr + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_lr(n, H, W)], acc);\n n = pos_rl + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_rl(n, H, W)], acc);\n n = pos_tb + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_tb(n, H, W)], acc);\n n = pos_bt + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_bt(n, H, W)], acc);\n }\n\n y[tid] = x[tid] + acc;\n}\n\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n TORCH_CHECK(x.is_cuda(), \"x must be CUDA\");\n TORCH_CHECK(weight.is_cuda(), \"weight must be CUDA\");\n TORCH_CHECK(bias.is_cuda(), \"bias must be CUDA\");\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"only float32 supported\");\n TORCH_CHECK(weight.scalar_type() == torch::kFloat32, \"only float32 weights supported\");\n TORCH_CHECK(bias.scalar_type() == torch::kFloat32, \"only float32 bias supported\");\n TORCH_CHECK(x.is_contiguous(), \"x must be contiguous\");\n TORCH_CHECK(weight.is_contiguous(), \"weight must be contiguous\");\n TORCH_CHECK(bias.is_contiguous(), \"bias must be contiguous\");\n\n int B = (int)x.size(0);\n int C = (int)x.size(1);\n int H = (int)x.size(2);\n int W = (int)x.size(3);\n int K = (int)weight.size(2);\n int total = B * C * H * W;\n auto y = torch::empty_like(x);\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n cross_scan_kernel<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(),\n y.data_ptr<float>(), B, C, H, W, K, total);\n return y;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"cross_scan_ext_v1\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"cross_scan_forward\"],\n extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"],\n extra_cflags=[\"-O3\"],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, channels: int, kernel_size: int = 3):\n super().__init__()\n assert channels >= 1\n assert kernel_size % 2 == 1\n self.channels = channels\n pad = kernel_size // 2\n self.dw_conv = nn.Conv1d(channels, channels, kernel_size, padding=pad, groups=channels, bias=True)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n if not x.is_contiguous():\n x = x.contiguous()\n return _ext.cross_scan_forward(x, self.dw_conv.weight.contiguous(), self.dw_conv.bias.contiguous())\n" }
result ← run_correctness (ok)
okrun_correctness run_correctness PASSED: (5 / 5) trials all matched the reference. Numerical precision: max_abs_err=1.91e-06 mean_abs_err=1.40e-07 max_rel_err=9.62e-02
turn 3 · 1 tool call(s) · 25.9s turn · 25.9s LLM · 7,215 chars (click to expand)
turn 325.9s turn · 25.9s LLM · 0.0s tools
call → compile_kernel
callcompile_kernel { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\ntorch::Tensor cross_scan_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n return cross_scan_forward_cuda(x, weight, bias);\n}\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void cross_scan_kernel3(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n\n int s = tid;\n int w = s % W; s /= W;\n int h = s % H; s /= H;\n int c = s % C;\n\n int HW = H * W;\n int spat = h * W + w;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n\n // LR sequence (row-major original)\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < HW - 1) acc = fmaf(w2, xp[spat + 1], acc);\n\n // RL sequence (row-major after horizontal flip), mapped back.\n if (w < W - 1) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * W], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < H - 1) acc = fmaf(w2, xp[(h + 1) * W + (W - 1)], acc);\n\n // TB sequence (column-major original)\n if (h > 0) acc = fmaf(w0, xp[spat - W], acc);\n else if (w > 0) acc = fmaf(w0, xp[(H - 1) * W + (w - 1)], acc);\n if (h < H - 1) acc = fmaf(w2, xp[spat + W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[w + 1], acc);\n\n // BT sequence (column-major after vertical flip), mapped back.\n if (h < H - 1) acc = fmaf(w0, xp[spat + W], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[(H - 1) * W + (w + 1)], acc);\n\n y[tid] = xv + acc;\n}\n\n__device__ __forceinline__ int spatial_from_rl(int n, int H, int W) {\n int row = n / W;\n int col = n - row * W;\n return row * W + (W - 1 - col);\n}\n__device__ __forceinline__ int spatial_from_tb(int n, int H, int W) {\n int col = n / H;\n int row = n - col * H;\n return row * W + col;\n}\n__device__ __forceinline__ int spatial_from_bt(int n, int H, int W) {\n int col = n / H;\n int rowf = n - col * H;\n return (H - 1 - rowf) * W + col;\n}\n\n__global__ void cross_scan_kernel_generic(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int K, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid;\n int w = s % W; s /= W;\n int h = s % H; s /= H;\n int c = s % C;\n int HW = H * W;\n int spat = h * W + w;\n int bc_base = tid - spat;\n int pos_lr = spat;\n int pos_rl = h * W + (W - 1 - w);\n int pos_tb = w * H + h;\n int pos_bt = w * H + (H - 1 - h);\n int pad = K >> 1;\n const float* wx = weight + c * K;\n float acc = 4.0f * bias[c];\n for (int kk = 0; kk < K; ++kk) {\n int off = kk - pad;\n float wk = wx[kk];\n int n = pos_lr + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + n], acc);\n n = pos_rl + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_rl(n, H, W)], acc);\n n = pos_tb + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_tb(n, H, W)], acc);\n n = pos_bt + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_bt(n, H, W)], acc);\n }\n y[tid] = x[tid] + acc;\n}\n\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n TORCH_CHECK(x.is_cuda() && weight.is_cuda() && bias.is_cuda(), \"CUDA tensors required\");\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"only float32 supported\");\n TORCH_CHECK(x.is_contiguous() && weight.is_contiguous() && bias.is_contiguous(), \"contiguous tensors required\");\n int B = (int)x.size(0);\n int C = (int)x.size(1);\n int H = (int)x.size(2);\n int W = (int)x.size(3);\n int K = (int)weight.size(2);\n int total = B * C * H * W;\n auto y = torch::empty_like(x);\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n if (K == 3) {\n cross_scan_kernel3<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, total);\n } else {\n cross_scan_kernel_generic<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, K, total);\n }\n return y;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"cross_scan_ext_v2\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"cross_scan_forward\"],\n extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"],\n extra_cflags=[\"-O3\"],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, channels: int, kernel_size: int = 3):\n super().__init__()\n assert channels >= 1\n assert kernel_size % 2 == 1\n self.channels = channels\n pad = kernel_size // 2\n self.dw_conv = nn.Conv1d(channels, channels, kernel_size, padding=pad, groups=channels, bias=True)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n if not x.is_contiguous():\n x = x.contiguous()\n return _ext.cross_scan_forward(x, self.dw_conv.weight.contiguous(), self.dw_conv.bias.contiguous())\n" }
result ← compile_kernel (ok)
okcompile_kernel compile_kernel PASSED: kernel compiled without errors.
turn 4 · 1 tool call(s) · 11.7s turn · 11.7s LLM · 7,095 chars (click to expand)
turn 411.7s turn · 11.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_src = r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\ntorch::Tensor cross_scan_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n return cross_scan_forward_cuda(x, weight, bias);\n}\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void cross_scan_kernel3(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n\n int s = tid;\n int w = s % W; s /= W;\n int h = s % H; s /= H;\n int c = s % C;\n\n int HW = H * W;\n int spat = h * W + w;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < HW - 1) acc = fmaf(w2, xp[spat + 1], acc);\n\n if (w < W - 1) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * W], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < H - 1) acc = fmaf(w2, xp[(h + 1) * W + (W - 1)], acc);\n\n if (h > 0) acc = fmaf(w0, xp[spat - W], acc);\n else if (w > 0) acc = fmaf(w0, xp[(H - 1) * W + (w - 1)], acc);\n if (h < H - 1) acc = fmaf(w2, xp[spat + W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[w + 1], acc);\n\n if (h < H - 1) acc = fmaf(w0, xp[spat + W], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[(H - 1) * W + (w + 1)], acc);\n\n y[tid] = xv + acc;\n}\n\n__device__ __forceinline__ int spatial_from_rl(int n, int H, int W) {\n int row = n / W;\n int col = n - row * W;\n return row * W + (W - 1 - col);\n}\n__device__ __forceinline__ int spatial_from_tb(int n, int H, int W) {\n int col = n / H;\n int row = n - col * H;\n return row * W + col;\n}\n__device__ __forceinline__ int spatial_from_bt(int n, int H, int W) {\n int col = n / H;\n int rowf = n - col * H;\n return (H - 1 - rowf) * W + col;\n}\n\n__global__ void cross_scan_kernel_generic(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int K, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid;\n int w = s % W; s /= W;\n int h = s % H; s /= H;\n int c = s % C;\n int HW = H * W;\n int spat = h * W + w;\n int bc_base = tid - spat;\n int pos_lr = spat;\n int pos_rl = h * W + (W - 1 - w);\n int pos_tb = w * H + h;\n int pos_bt = w * H + (H - 1 - h);\n int pad = K >> 1;\n const float* wx = weight + c * K;\n float acc = 4.0f * bias[c];\n for (int kk = 0; kk < K; ++kk) {\n int off = kk - pad;\n float wk = wx[kk];\n int n = pos_lr + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + n], acc);\n n = pos_rl + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_rl(n, H, W)], acc);\n n = pos_tb + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_tb(n, H, W)], acc);\n n = pos_bt + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_bt(n, H, W)], acc);\n }\n y[tid] = x[tid] + acc;\n}\n\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n TORCH_CHECK(x.is_cuda() && weight.is_cuda() && bias.is_cuda(), \"CUDA tensors required\");\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"only float32 supported\");\n TORCH_CHECK(x.is_contiguous() && weight.is_contiguous() && bias.is_contiguous(), \"contiguous tensors required\");\n int B = (int)x.size(0);\n int C = (int)x.size(1);\n int H = (int)x.size(2);\n int W = (int)x.size(3);\n int K = (int)weight.size(2);\n int total = B * C * H * W;\n auto y = torch::empty_like(x);\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n if (K == 3) {\n cross_scan_kernel3<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, total);\n } else {\n cross_scan_kernel_generic<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, K, total);\n }\n return y;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"cross_scan_ext_v2\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"cross_scan_forward\"],\n extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"],\n extra_cflags=[\"-O3\"],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, channels: int, kernel_size: int = 3):\n super().__init__()\n assert channels >= 1\n assert kernel_size % 2 == 1\n self.channels = channels\n pad = kernel_size // 2\n self.dw_conv = nn.Conv1d(channels, channels, kernel_size, padding=pad, groups=channels, bias=True)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n if not x.is_contiguous():\n x = x.contiguous()\n return _ext.cross_scan_forward(x, self.dw_conv.weight.contiguous(), self.dw_conv.bias.contiguous())\n" }
result ← run_correctness (ok)
okrun_correctness run_correctness PASSED: (5 / 5) trials all matched the reference. Numerical precision: max_abs_err=2.86e-06 mean_abs_err=1.11e-07 max_rel_err=3.33e-01
turn 5 · 1 tool call(s) · 27.8s turn · 27.8s LLM · 9,111 chars (click to expand)
turn 527.8s turn · 27.8s LLM · 0.0s tools
call → compile_kernel
callcompile_kernel { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\ntorch::Tensor cross_scan_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) { return cross_scan_forward_cuda(x, weight, bias); }\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void cross_scan_kernel3_32_64(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int spat = tid & 1023;\n int w = tid & 31;\n int h = (tid >> 5) & 31;\n int c = (tid >> 10) & 63;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n float ws = w0 + w2;\n\n if ((unsigned)(h - 1) < 30u && (unsigned)(w - 1) < 30u) {\n acc = fmaf(ws, xp[spat - 1], acc);\n acc = fmaf(ws, xp[spat + 1], acc);\n acc = fmaf(ws, xp[spat - 32], acc);\n acc = fmaf(ws, xp[spat + 32], acc);\n } else {\n // LR\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < 1023) acc = fmaf(w2, xp[spat + 1], acc);\n // RL\n if (w < 31) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * 32], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < 31) acc = fmaf(w2, xp[(h + 1) * 32 + 31], acc);\n // TB\n if (h > 0) acc = fmaf(w0, xp[spat - 32], acc);\n else if (w > 0) acc = fmaf(w0, xp[992 + (w - 1)], acc);\n if (h < 31) acc = fmaf(w2, xp[spat + 32], acc);\n else if (w < 31) acc = fmaf(w2, xp[w + 1], acc);\n // BT\n if (h < 31) acc = fmaf(w0, xp[spat + 32], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - 32], acc);\n else if (w < 31) acc = fmaf(w2, xp[992 + (w + 1)], acc);\n }\n y[tid] = xv + acc;\n}\n\n__global__ void cross_scan_kernel3(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid;\n int w = s % W; s /= W;\n int h = s % H; s /= H;\n int c = s % C;\n int HW = H * W;\n int spat = h * W + w;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < HW - 1) acc = fmaf(w2, xp[spat + 1], acc);\n if (w < W - 1) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * W], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < H - 1) acc = fmaf(w2, xp[(h + 1) * W + (W - 1)], acc);\n if (h > 0) acc = fmaf(w0, xp[spat - W], acc);\n else if (w > 0) acc = fmaf(w0, xp[(H - 1) * W + (w - 1)], acc);\n if (h < H - 1) acc = fmaf(w2, xp[spat + W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[w + 1], acc);\n if (h < H - 1) acc = fmaf(w0, xp[spat + W], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[(H - 1) * W + (w + 1)], acc);\n y[tid] = xv + acc;\n}\n\n__device__ __forceinline__ int spatial_from_rl(int n, int H, int W) { int row = n / W; int col = n - row * W; return row * W + (W - 1 - col); }\n__device__ __forceinline__ int spatial_from_tb(int n, int H, int W) { int col = n / H; int row = n - col * H; return row * W + col; }\n__device__ __forceinline__ int spatial_from_bt(int n, int H, int W) { int col = n / H; int rowf = n - col * H; return (H - 1 - rowf) * W + col; }\n\n__global__ void cross_scan_kernel_generic(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int K, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid; int w = s % W; s /= W; int h = s % H; s /= H; int c = s % C;\n int HW = H * W; int spat = h * W + w; int bc_base = tid - spat;\n int pos_lr = spat, pos_rl = h * W + (W - 1 - w), pos_tb = w * H + h, pos_bt = w * H + (H - 1 - h);\n int pad = K >> 1; const float* wx = weight + c * K; float acc = 4.0f * bias[c];\n for (int kk = 0; kk < K; ++kk) {\n int off = kk - pad; float wk = wx[kk]; int n = pos_lr + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + n], acc);\n n = pos_rl + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_rl(n, H, W)], acc);\n n = pos_tb + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_tb(n, H, W)], acc);\n n = pos_bt + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_bt(n, H, W)], acc);\n }\n y[tid] = x[tid] + acc;\n}\n\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n TORCH_CHECK(x.is_cuda() && weight.is_cuda() && bias.is_cuda(), \"CUDA tensors required\");\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"only float32 supported\");\n TORCH_CHECK(x.is_contiguous() && weight.is_contiguous() && bias.is_contiguous(), \"contiguous tensors required\");\n int B = (int)x.size(0), C = (int)x.size(1), H = (int)x.size(2), W = (int)x.size(3), K = (int)weight.size(2);\n int total = B * C * H * W;\n auto y = torch::empty_like(x);\n int threads = 256, blocks = (total + threads - 1) / threads;\n if (K == 3 && C == 64 && H == 32 && W == 32) {\n cross_scan_kernel3_32_64<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), total);\n } else if (K == 3) {\n cross_scan_kernel3<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, total);\n } else {\n cross_scan_kernel_generic<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, K, total);\n }\n return y;\n}\n\"\"\"\n\n_ext = load_inline(name=\"cross_scan_ext_v3\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"cross_scan_forward\"], extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"], extra_cflags=[\"-O3\"], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, channels: int, kernel_size: int = 3):\n super().__init__()\n assert channels >= 1\n assert kernel_size % 2 == 1\n self.channels = channels\n pad = kernel_size // 2\n self.dw_conv = nn.Conv1d(channels, channels, kernel_size, padding=pad, groups=channels, bias=True)\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n if not x.is_contiguous():\n x = x.contiguous()\n return _ext.cross_scan_forward(x, self.dw_conv.weight.contiguous(), self.dw_conv.bias.contiguous())\n" }
result ← compile_kernel (ok)
okcompile_kernel compile_kernel PASSED: kernel compiled without errors.
turn 6 · 1 tool call(s) · 15.9s turn · 15.9s LLM · 9,153 chars (click to expand)
turn 615.9s turn · 15.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_src = r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\ntorch::Tensor cross_scan_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) { return cross_scan_forward_cuda(x, weight, bias); }\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void cross_scan_kernel3_32_64(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int spat = tid & 1023;\n int w = tid & 31;\n int h = (tid >> 5) & 31;\n int c = (tid >> 10) & 63;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n float ws = w0 + w2;\n\n if ((unsigned)(h - 1) < 30u && (unsigned)(w - 1) < 30u) {\n acc = fmaf(ws, xp[spat - 1], acc);\n acc = fmaf(ws, xp[spat + 1], acc);\n acc = fmaf(ws, xp[spat - 32], acc);\n acc = fmaf(ws, xp[spat + 32], acc);\n } else {\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < 1023) acc = fmaf(w2, xp[spat + 1], acc);\n if (w < 31) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * 32], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < 31) acc = fmaf(w2, xp[(h + 1) * 32 + 31], acc);\n if (h > 0) acc = fmaf(w0, xp[spat - 32], acc);\n else if (w > 0) acc = fmaf(w0, xp[992 + (w - 1)], acc);\n if (h < 31) acc = fmaf(w2, xp[spat + 32], acc);\n else if (w < 31) acc = fmaf(w2, xp[w + 1], acc);\n if (h < 31) acc = fmaf(w0, xp[spat + 32], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - 32], acc);\n else if (w < 31) acc = fmaf(w2, xp[992 + (w + 1)], acc);\n }\n y[tid] = xv + acc;\n}\n\n__global__ void cross_scan_kernel3(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid;\n int w = s % W; s /= W;\n int h = s % H; s /= H;\n int c = s % C;\n int HW = H * W;\n int spat = h * W + w;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < HW - 1) acc = fmaf(w2, xp[spat + 1], acc);\n if (w < W - 1) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * W], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < H - 1) acc = fmaf(w2, xp[(h + 1) * W + (W - 1)], acc);\n if (h > 0) acc = fmaf(w0, xp[spat - W], acc);\n else if (w > 0) acc = fmaf(w0, xp[(H - 1) * W + (w - 1)], acc);\n if (h < H - 1) acc = fmaf(w2, xp[spat + W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[w + 1], acc);\n if (h < H - 1) acc = fmaf(w0, xp[spat + W], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[(H - 1) * W + (w + 1)], acc);\n y[tid] = xv + acc;\n}\n\n__device__ __forceinline__ int spatial_from_rl(int n, int H, int W) { int row = n / W; int col = n - row * W; return row * W + (W - 1 - col); }\n__device__ __forceinline__ int spatial_from_tb(int n, int H, int W) { int col = n / H; int row = n - col * H; return row * W + col; }\n__device__ __forceinline__ int spatial_from_bt(int n, int H, int W) { int col = n / H; int rowf = n - col * H; return (H - 1 - rowf) * W + col; }\n\n__global__ void cross_scan_kernel_generic(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int K, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid; int w = s % W; s /= W; int h = s % H; s /= H; int c = s % C;\n int HW = H * W; int spat = h * W + w; int bc_base = tid - spat;\n int pos_lr = spat, pos_rl = h * W + (W - 1 - w), pos_tb = w * H + h, pos_bt = w * H + (H - 1 - h);\n int pad = K >> 1; const float* wx = weight + c * K; float acc = 4.0f * bias[c];\n for (int kk = 0; kk < K; ++kk) {\n int off = kk - pad; float wk = wx[kk]; int n = pos_lr + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + n], acc);\n n = pos_rl + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_rl(n, H, W)], acc);\n n = pos_tb + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_tb(n, H, W)], acc);\n n = pos_bt + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_bt(n, H, W)], acc);\n }\n y[tid] = x[tid] + acc;\n}\n\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n TORCH_CHECK(x.is_cuda() && weight.is_cuda() && bias.is_cuda(), \"CUDA tensors required\");\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"only float32 supported\");\n TORCH_CHECK(x.is_contiguous() && weight.is_contiguous() && bias.is_contiguous(), \"contiguous tensors required\");\n int B = (int)x.size(0), C = (int)x.size(1), H = (int)x.size(2), W = (int)x.size(3), K = (int)weight.size(2);\n int total = B * C * H * W;\n auto y = torch::empty_like(x);\n int threads = 256, blocks = (total + threads - 1) / threads;\n if (K == 3 && C == 64 && H == 32 && W == 32) {\n cross_scan_kernel3_32_64<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), total);\n } else if (K == 3) {\n cross_scan_kernel3<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, total);\n } else {\n cross_scan_kernel_generic<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, K, total);\n }\n return y;\n}\n\"\"\"\n\n_ext = load_inline(name=\"cross_scan_ext_v3\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"cross_scan_forward\"], extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"], extra_cflags=[\"-O3\"], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, channels: int, kernel_size: int = 3):\n super().__init__()\n assert channels >= 1\n assert kernel_size % 2 == 1\n self.channels = channels\n pad = kernel_size // 2\n self.dw_conv = nn.Conv1d(channels, channels, kernel_size, padding=pad, groups=channels, bias=True)\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n if not x.is_contiguous():\n x = x.contiguous()\n return _ext.cross_scan_forward(x, self.dw_conv.weight.contiguous(), self.dw_conv.bias.contiguous())\n" }
result ← run_correctness (ok)
okrun_correctness run_correctness PASSED: (5 / 5) trials all matched the reference. Numerical precision: max_abs_err=1.91e-06 mean_abs_err=9.25e-08 max_rel_err=3.33e-01
turn 7 · 1 tool call(s) · 27.3s turn · 27.3s LLM · 10,204 chars (click to expand)
turn 727.3s turn · 27.3s LLM · 0.0s tools
reasoning
**Evaluating performance optimizations** I’m thinking about optimizing my Python code to avoid unnecessary overhead. I wonder if using contiguous data inputs is necessary for correctness. I’m considering a direct call to an extension to skip Python branches. Maybe I should be careful with non-contiguous data since the user wants the same signature for input. The anticipated timing is getting interesting as well, with potential improvements looking promising. I’ll also consider the memory and kernel launch overhead in my calculations. **Analyzing boundary conditions** I’m considering a potential issue with the boundary formula for specialized interiors that combines coefficients. It looks like the spat is relevant only at the interior, not the global sequence boundary. I’m thinking that if height (h) is zero and width (w) is one, it isn’t in the interior; it represents a boundary path instead. Likewise, when h equals one and w equals zero, that's also a boundary path. I’ll keep in mind that h and w range from 1 to 30. **Preparing final code** I'm focusing on preparing the final code. It seems like I need to ensure that the boundary path is included and consider a generic fallback option. I should also allow the constructor to accept arbitrary kernel_size. It's important to check for static correctness, even if it means using v3 code without checks since static checks aren't affected. My goal is to compile the code and ensure it runs correctly without using TORCH_CHECK.
call → compile_kernel
callcompile_kernel { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\ntorch::Tensor cross_scan_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) { return cross_scan_forward_cuda(x, weight, bias); }\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void cross_scan_kernel3_32_64(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int spat = tid & 1023;\n int w = tid & 31;\n int h = (tid >> 5) & 31;\n int c = (tid >> 10) & 63;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n float ws = w0 + w2;\n\n if ((unsigned)(h - 1) < 30u && (unsigned)(w - 1) < 30u) {\n acc = fmaf(ws, xp[spat - 1], acc);\n acc = fmaf(ws, xp[spat + 1], acc);\n acc = fmaf(ws, xp[spat - 32], acc);\n acc = fmaf(ws, xp[spat + 32], acc);\n } else {\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < 1023) acc = fmaf(w2, xp[spat + 1], acc);\n if (w < 31) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * 32], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < 31) acc = fmaf(w2, xp[(h + 1) * 32 + 31], acc);\n if (h > 0) acc = fmaf(w0, xp[spat - 32], acc);\n else if (w > 0) acc = fmaf(w0, xp[992 + (w - 1)], acc);\n if (h < 31) acc = fmaf(w2, xp[spat + 32], acc);\n else if (w < 31) acc = fmaf(w2, xp[w + 1], acc);\n if (h < 31) acc = fmaf(w0, xp[spat + 32], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - 32], acc);\n else if (w < 31) acc = fmaf(w2, xp[992 + (w + 1)], acc);\n }\n y[tid] = xv + acc;\n}\n\n__global__ void cross_scan_kernel3(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid;\n int w = s % W; s /= W;\n int h = s % H; s /= H;\n int c = s % C;\n int HW = H * W;\n int spat = h * W + w;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < HW - 1) acc = fmaf(w2, xp[spat + 1], acc);\n if (w < W - 1) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * W], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < H - 1) acc = fmaf(w2, xp[(h + 1) * W + (W - 1)], acc);\n if (h > 0) acc = fmaf(w0, xp[spat - W], acc);\n else if (w > 0) acc = fmaf(w0, xp[(H - 1) * W + (w - 1)], acc);\n if (h < H - 1) acc = fmaf(w2, xp[spat + W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[w + 1], acc);\n if (h < H - 1) acc = fmaf(w0, xp[spat + W], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[(H - 1) * W + (w + 1)], acc);\n y[tid] = xv + acc;\n}\n\n__device__ __forceinline__ int spatial_from_rl(int n, int H, int W) { int row = n / W; int col = n - row * W; return row * W + (W - 1 - col); }\n__device__ __forceinline__ int spatial_from_tb(int n, int H, int W) { int col = n / H; int row = n - col * H; return row * W + col; }\n__device__ __forceinline__ int spatial_from_bt(int n, int H, int W) { int col = n / H; int rowf = n - col * H; return (H - 1 - rowf) * W + col; }\n\n__global__ void cross_scan_kernel_generic(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int K, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid; int w = s % W; s /= W; int h = s % H; s /= H; int c = s % C;\n int HW = H * W; int spat = h * W + w; int bc_base = tid - spat;\n int pos_lr = spat, pos_rl = h * W + (W - 1 - w), pos_tb = w * H + h, pos_bt = w * H + (H - 1 - h);\n int pad = K >> 1; const float* wx = weight + c * K; float acc = 4.0f * bias[c];\n for (int kk = 0; kk < K; ++kk) {\n int off = kk - pad; float wk = wx[kk]; int n = pos_lr + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + n], acc);\n n = pos_rl + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_rl(n, H, W)], acc);\n n = pos_tb + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_tb(n, H, W)], acc);\n n = pos_bt + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_bt(n, H, W)], acc);\n }\n y[tid] = x[tid] + acc;\n}\n\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n int B = (int)x.size(0), C = (int)x.size(1), H = (int)x.size(2), W = (int)x.size(3), K = (int)weight.size(2);\n int total = B * C * H * W;\n auto y = torch::empty_like(x);\n int threads = 256, blocks = (total + threads - 1) / threads;\n if (K == 3 && C == 64 && H == 32 && W == 32) {\n cross_scan_kernel3_32_64<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), total);\n } else if (K == 3) {\n cross_scan_kernel3<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, total);\n } else {\n cross_scan_kernel_generic<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, K, total);\n }\n return y;\n}\n\"\"\"\n\n_ext = load_inline(name=\"cross_scan_ext_final\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"cross_scan_forward\"], extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"], extra_cflags=[\"-O3\"], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, channels: int, kernel_size: int = 3):\n super().__init__()\n assert channels >= 1\n assert kernel_size % 2 == 1\n self.channels = channels\n pad = kernel_size // 2\n self.dw_conv = nn.Conv1d(channels, channels, kernel_size, padding=pad, groups=channels, bias=True)\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.cross_scan_forward(x, self.dw_conv.weight, self.dw_conv.bias)\n" }
result ← compile_kernel (ok)
okcompile_kernel compile_kernel PASSED: kernel compiled without errors.
turn 8 · 1 tool call(s) · 16.2s turn · 16.2s LLM · 8,703 chars (click to expand)
turn 816.2s turn · 16.2s LLM · 0.0s tools
call → run_correctness
callrun_correctness { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\ntorch::Tensor cross_scan_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) { return cross_scan_forward_cuda(x, weight, bias); }\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void cross_scan_kernel3_32_64(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int spat = tid & 1023;\n int w = tid & 31;\n int h = (tid >> 5) & 31;\n int c = (tid >> 10) & 63;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n float ws = w0 + w2;\n\n if ((unsigned)(h - 1) < 30u && (unsigned)(w - 1) < 30u) {\n acc = fmaf(ws, xp[spat - 1], acc);\n acc = fmaf(ws, xp[spat + 1], acc);\n acc = fmaf(ws, xp[spat - 32], acc);\n acc = fmaf(ws, xp[spat + 32], acc);\n } else {\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < 1023) acc = fmaf(w2, xp[spat + 1], acc);\n if (w < 31) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * 32], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < 31) acc = fmaf(w2, xp[(h + 1) * 32 + 31], acc);\n if (h > 0) acc = fmaf(w0, xp[spat - 32], acc);\n else if (w > 0) acc = fmaf(w0, xp[992 + (w - 1)], acc);\n if (h < 31) acc = fmaf(w2, xp[spat + 32], acc);\n else if (w < 31) acc = fmaf(w2, xp[w + 1], acc);\n if (h < 31) acc = fmaf(w0, xp[spat + 32], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - 32], acc);\n else if (w < 31) acc = fmaf(w2, xp[992 + (w + 1)], acc);\n }\n y[tid] = xv + acc;\n}\n\n__global__ void cross_scan_kernel3(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid;\n int w = s % W; s /= W;\n int h = s % H; s /= H;\n int c = s % C;\n int HW = H * W;\n int spat = h * W + w;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < HW - 1) acc = fmaf(w2, xp[spat + 1], acc);\n if (w < W - 1) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * W], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < H - 1) acc = fmaf(w2, xp[(h + 1) * W + (W - 1)], acc);\n if (h > 0) acc = fmaf(w0, xp[spat - W], acc);\n else if (w > 0) acc = fmaf(w0, xp[(H - 1) * W + (w - 1)], acc);\n if (h < H - 1) acc = fmaf(w2, xp[spat + W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[w + 1], acc);\n if (h < H - 1) acc = fmaf(w0, xp[spat + W], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[(H - 1) * W + (w + 1)], acc);\n y[tid] = xv + acc;\n}\n\n__device__ __forceinline__ int spatial_from_rl(int n, int H, int W) { int row = n / W; int col = n - row * W; return row * W + (W - 1 - col); }\n__device__ __forceinline__ int spatial_from_tb(int n, int H, int W) { int col = n / H; int row = n - col * H; return row * W + col; }\n__device__ __forceinline__ int spatial_from_bt(int n, int H, int W) { int col = n / H; int rowf = n - col * H; return (H - 1 - rowf) * W + col; }\n\n__global__ void cross_scan_kernel_generic(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int K, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid; int w = s % W; s /= W; int h = s % H; s /= H; int c = s % C;\n int HW = H * W; int spat = h * W + w; int bc_base = tid - spat;\n int pos_lr = spat, pos_rl = h * W + (W - 1 - w), pos_tb = w * H + h, pos_bt = w * H + (H - 1 - h);\n int pad = K >> 1; const float* wx = weight + c * K; float acc = 4.0f * bias[c];\n for (int kk = 0; kk < K; ++kk) {\n int off = kk - pad; float wk = wx[kk]; int n = pos_lr + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + n], acc);\n n = pos_rl + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_rl(n, H, W)], acc);\n n = pos_tb + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_tb(n, H, W)], acc);\n n = pos_bt + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_bt(n, H, W)], acc);\n }\n y[tid] = x[tid] + acc;\n}\n\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n int B = (int)x.size(0), C = (int)x.size(1), H = (int)x.size(2), W = (int)x.size(3), K = (int)weight.size(2);\n int total = B * C * H * W;\n auto y = torch::empty_like(x);\n int threads = 256, blocks = (total + threads - 1) / threads;\n if (K == 3 && C == 64 && H == 32 && W == 32) {\n cross_scan_kernel3_32_64<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), total);\n } else if (K == 3) {\n cross_scan_kernel3<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, total);\n } else {\n cross_scan_kernel_generic<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, K, total);\n }\n return y;\n}\n\"\"\"\n\n_ext = load_inline(name=\"cross_scan_ext_final\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"cross_scan_forward\"], extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"], extra_cflags=[\"-O3\"], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, channels: int, kernel_size: int = 3):\n super().__init__()\n assert channels >= 1\n assert kernel_size % 2 == 1\n self.channels = channels\n pad = kernel_size // 2\n self.dw_conv = nn.Conv1d(channels, channels, kernel_size, padding=pad, groups=channels, bias=True)\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.cross_scan_forward(x, self.dw_conv.weight, self.dw_conv.bias)\n" }
result ← run_correctness (ok)
okrun_correctness run_correctness PASSED: (5 / 5) trials all matched the reference. Numerical precision: max_abs_err=1.91e-06 mean_abs_err=9.25e-08 max_rel_err=3.33e-01
turn 9 · 1 tool call(s) · 16.5s turn · 16.5s LLM · 8,595 chars (click to expand)
turn 916.5s turn · 16.5s LLM · 0.0s tools
call → static_check
callstatic_check { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\ntorch::Tensor cross_scan_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) { return cross_scan_forward_cuda(x, weight, bias); }\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void cross_scan_kernel3_32_64(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int spat = tid & 1023;\n int w = tid & 31;\n int h = (tid >> 5) & 31;\n int c = (tid >> 10) & 63;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n float ws = w0 + w2;\n\n if ((unsigned)(h - 1) < 30u && (unsigned)(w - 1) < 30u) {\n acc = fmaf(ws, xp[spat - 1], acc);\n acc = fmaf(ws, xp[spat + 1], acc);\n acc = fmaf(ws, xp[spat - 32], acc);\n acc = fmaf(ws, xp[spat + 32], acc);\n } else {\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < 1023) acc = fmaf(w2, xp[spat + 1], acc);\n if (w < 31) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * 32], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < 31) acc = fmaf(w2, xp[(h + 1) * 32 + 31], acc);\n if (h > 0) acc = fmaf(w0, xp[spat - 32], acc);\n else if (w > 0) acc = fmaf(w0, xp[992 + (w - 1)], acc);\n if (h < 31) acc = fmaf(w2, xp[spat + 32], acc);\n else if (w < 31) acc = fmaf(w2, xp[w + 1], acc);\n if (h < 31) acc = fmaf(w0, xp[spat + 32], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - 32], acc);\n else if (w < 31) acc = fmaf(w2, xp[992 + (w + 1)], acc);\n }\n y[tid] = xv + acc;\n}\n\n__global__ void cross_scan_kernel3(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid;\n int w = s % W; s /= W;\n int h = s % H; s /= H;\n int c = s % C;\n int HW = H * W;\n int spat = h * W + w;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < HW - 1) acc = fmaf(w2, xp[spat + 1], acc);\n if (w < W - 1) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * W], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < H - 1) acc = fmaf(w2, xp[(h + 1) * W + (W - 1)], acc);\n if (h > 0) acc = fmaf(w0, xp[spat - W], acc);\n else if (w > 0) acc = fmaf(w0, xp[(H - 1) * W + (w - 1)], acc);\n if (h < H - 1) acc = fmaf(w2, xp[spat + W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[w + 1], acc);\n if (h < H - 1) acc = fmaf(w0, xp[spat + W], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[(H - 1) * W + (w + 1)], acc);\n y[tid] = xv + acc;\n}\n\n__device__ __forceinline__ int spatial_from_rl(int n, int H, int W) { int row = n / W; int col = n - row * W; return row * W + (W - 1 - col); }\n__device__ __forceinline__ int spatial_from_tb(int n, int H, int W) { int col = n / H; int row = n - col * H; return row * W + col; }\n__device__ __forceinline__ int spatial_from_bt(int n, int H, int W) { int col = n / H; int rowf = n - col * H; return (H - 1 - rowf) * W + col; }\n\n__global__ void cross_scan_kernel_generic(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int K, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid; int w = s % W; s /= W; int h = s % H; s /= H; int c = s % C;\n int HW = H * W; int spat = h * W + w; int bc_base = tid - spat;\n int pos_lr = spat, pos_rl = h * W + (W - 1 - w), pos_tb = w * H + h, pos_bt = w * H + (H - 1 - h);\n int pad = K >> 1; const float* wx = weight + c * K; float acc = 4.0f * bias[c];\n for (int kk = 0; kk < K; ++kk) {\n int off = kk - pad; float wk = wx[kk]; int n = pos_lr + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + n], acc);\n n = pos_rl + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_rl(n, H, W)], acc);\n n = pos_tb + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_tb(n, H, W)], acc);\n n = pos_bt + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_bt(n, H, W)], acc);\n }\n y[tid] = x[tid] + acc;\n}\n\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n int B = (int)x.size(0), C = (int)x.size(1), H = (int)x.size(2), W = (int)x.size(3), K = (int)weight.size(2);\n int total = B * C * H * W;\n auto y = torch::empty_like(x);\n int threads = 256, blocks = (total + threads - 1) / threads;\n if (K == 3 && C == 64 && H == 32 && W == 32) {\n cross_scan_kernel3_32_64<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), total);\n } else if (K == 3) {\n cross_scan_kernel3<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, total);\n } else {\n cross_scan_kernel_generic<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, K, total);\n }\n return y;\n}\n\"\"\"\n\n_ext = load_inline(name=\"cross_scan_ext_final\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"cross_scan_forward\"], extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"], extra_cflags=[\"-O3\"], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, channels: int, kernel_size: int = 3):\n super().__init__()\n assert channels >= 1\n assert kernel_size % 2 == 1\n self.channels = channels\n pad = kernel_size // 2\n self.dw_conv = nn.Conv1d(channels, channels, kernel_size, padding=pad, groups=channels, bias=True)\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.cross_scan_forward(x, self.dw_conv.weight, self.dw_conv.bias)\n" }
result ← static_check (ok)
okstatic_check static_check PASSED: no violations or warnings detected.
turn 10 · FINAL · 1 tool call(s) · 15.7s turn · 15.7s LLM · 8,993 chars (click to expand)
turn 1015.7s turn · 15.7s LLM · 0.0s tools · FINAL
call → submit_kernel
callsubmit_kernel { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\ntorch::Tensor cross_scan_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) { return cross_scan_forward_cuda(x, weight, bias); }\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void cross_scan_kernel3_32_64(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int spat = tid & 1023;\n int w = tid & 31;\n int h = (tid >> 5) & 31;\n int c = (tid >> 10) & 63;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n float ws = w0 + w2;\n\n if ((unsigned)(h - 1) < 30u && (unsigned)(w - 1) < 30u) {\n acc = fmaf(ws, xp[spat - 1], acc);\n acc = fmaf(ws, xp[spat + 1], acc);\n acc = fmaf(ws, xp[spat - 32], acc);\n acc = fmaf(ws, xp[spat + 32], acc);\n } else {\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < 1023) acc = fmaf(w2, xp[spat + 1], acc);\n if (w < 31) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * 32], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < 31) acc = fmaf(w2, xp[(h + 1) * 32 + 31], acc);\n if (h > 0) acc = fmaf(w0, xp[spat - 32], acc);\n else if (w > 0) acc = fmaf(w0, xp[992 + (w - 1)], acc);\n if (h < 31) acc = fmaf(w2, xp[spat + 32], acc);\n else if (w < 31) acc = fmaf(w2, xp[w + 1], acc);\n if (h < 31) acc = fmaf(w0, xp[spat + 32], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - 32], acc);\n else if (w < 31) acc = fmaf(w2, xp[992 + (w + 1)], acc);\n }\n y[tid] = xv + acc;\n}\n\n__global__ void cross_scan_kernel3(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid;\n int w = s % W; s /= W;\n int h = s % H; s /= H;\n int c = s % C;\n int HW = H * W;\n int spat = h * W + w;\n int bc_base = tid - spat;\n const float* xp = x + bc_base;\n const float* wc = weight + c * 3;\n float w0 = wc[0], w1 = wc[1], w2 = wc[2];\n float xv = xp[spat];\n float acc = 4.0f * bias[c] + (4.0f * w1) * xv;\n if (spat > 0) acc = fmaf(w0, xp[spat - 1], acc);\n if (spat < HW - 1) acc = fmaf(w2, xp[spat + 1], acc);\n if (w < W - 1) acc = fmaf(w0, xp[spat + 1], acc);\n else if (h > 0) acc = fmaf(w0, xp[(h - 1) * W], acc);\n if (w > 0) acc = fmaf(w2, xp[spat - 1], acc);\n else if (h < H - 1) acc = fmaf(w2, xp[(h + 1) * W + (W - 1)], acc);\n if (h > 0) acc = fmaf(w0, xp[spat - W], acc);\n else if (w > 0) acc = fmaf(w0, xp[(H - 1) * W + (w - 1)], acc);\n if (h < H - 1) acc = fmaf(w2, xp[spat + W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[w + 1], acc);\n if (h < H - 1) acc = fmaf(w0, xp[spat + W], acc);\n else if (w > 0) acc = fmaf(w0, xp[w - 1], acc);\n if (h > 0) acc = fmaf(w2, xp[spat - W], acc);\n else if (w < W - 1) acc = fmaf(w2, xp[(H - 1) * W + (w + 1)], acc);\n y[tid] = xv + acc;\n}\n\n__device__ __forceinline__ int spatial_from_rl(int n, int H, int W) { int row = n / W; int col = n - row * W; return row * W + (W - 1 - col); }\n__device__ __forceinline__ int spatial_from_tb(int n, int H, int W) { int col = n / H; int row = n - col * H; return row * W + col; }\n__device__ __forceinline__ int spatial_from_bt(int n, int H, int W) { int col = n / H; int rowf = n - col * H; return (H - 1 - rowf) * W + col; }\n\n__global__ void cross_scan_kernel_generic(const float* __restrict__ x,\n const float* __restrict__ weight,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int C, int H, int W, int K, int total) {\n int tid = blockIdx.x * blockDim.x + threadIdx.x;\n if (tid >= total) return;\n int s = tid; int w = s % W; s /= W; int h = s % H; s /= H; int c = s % C;\n int HW = H * W; int spat = h * W + w; int bc_base = tid - spat;\n int pos_lr = spat, pos_rl = h * W + (W - 1 - w), pos_tb = w * H + h, pos_bt = w * H + (H - 1 - h);\n int pad = K >> 1; const float* wx = weight + c * K; float acc = 4.0f * bias[c];\n for (int kk = 0; kk < K; ++kk) {\n int off = kk - pad; float wk = wx[kk]; int n = pos_lr + off;\n if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + n], acc);\n n = pos_rl + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_rl(n, H, W)], acc);\n n = pos_tb + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_tb(n, H, W)], acc);\n n = pos_bt + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_bt(n, H, W)], acc);\n }\n y[tid] = x[tid] + acc;\n}\n\ntorch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n int B = (int)x.size(0), C = (int)x.size(1), H = (int)x.size(2), W = (int)x.size(3), K = (int)weight.size(2);\n int total = B * C * H * W;\n auto y = torch::empty_like(x);\n int threads = 256, blocks = (total + threads - 1) / threads;\n if (K == 3 && C == 64 && H == 32 && W == 32) {\n cross_scan_kernel3_32_64<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), total);\n } else if (K == 3) {\n cross_scan_kernel3<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, total);\n } else {\n cross_scan_kernel_generic<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, K, total);\n }\n return y;\n}\n\"\"\"\n\n_ext = load_inline(name=\"cross_scan_ext_final\", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=[\"cross_scan_forward\"], extra_cuda_cflags=[\"-O3\", \"--use_fast_math\"], extra_cflags=[\"-O3\"], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, channels: int, kernel_size: int = 3):\n super().__init__()\n assert channels >= 1\n assert kernel_size % 2 == 1\n self.channels = channels\n pad = kernel_size // 2\n self.dw_conv = nn.Conv1d(channels, channels, kernel_size, padding=pad, groups=channels, bias=True)\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.cross_scan_forward(x, self.dw_conv.weight, self.dw_conv.bias)\n" }
result ← submit_kernel (ok)
oksubmit_kernel submit_kernel PASSED: (5 / 5) correctness trials all passed. Kernel runtime: 0.01 μs Runtime stats: mean=0.01μs median=?μs std=0.02μs Numerical precision: max_abs_err=1.91e-06 mean_abs_err=9.25e-08 max_rel_err=3.33e-01 Memory: 35.0 MB peak (ref: 42.0 MB, ratio: 0.8333x) Kernel launches: 2 (ref: 114, fusion ratio: 57.0) SOL score: 0.0941 Flagged for excessive speedup — this submission may have been rejected by automated review.
final submitted kernel (148 lines, 7,449 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline

_cpp_src = r"""
#include <torch/extension.h>
torch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);
torch::Tensor cross_scan_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) { return cross_scan_forward_cuda(x, weight, bias); }
"""

_cuda_src = r"""
#include <torch/extension.h>
#include <cuda.h>
#include <cuda_runtime.h>

__global__ void cross_scan_kernel3_32_64(const float* __restrict__ x,
                                   const float* __restrict__ weight,
                                   const float* __restrict__ bias,
                                   float* __restrict__ y,
                                   int total) {
    int tid = blockIdx.x * blockDim.x + threadIdx.x;
    if (tid >= total) return;
    int spat = tid & 1023;
    int w = tid & 31;
    int h = (tid >> 5) & 31;
    int c = (tid >> 10) & 63;
    int bc_base = tid - spat;
    const float* xp = x + bc_base;
    const float* wc = weight + c * 3;
    float w0 = wc[0], w1 = wc[1], w2 = wc[2];
    float xv = xp[spat];
    float acc = 4.0f * bias[c] + (4.0f * w1) * xv;
    float ws = w0 + w2;

    if ((unsigned)(h - 1) < 30u && (unsigned)(w - 1) < 30u) {
        acc = fmaf(ws, xp[spat - 1], acc);
        acc = fmaf(ws, xp[spat + 1], acc);
        acc = fmaf(ws, xp[spat - 32], acc);
        acc = fmaf(ws, xp[spat + 32], acc);
    } else {
        if (spat > 0)     acc = fmaf(w0, xp[spat - 1], acc);
        if (spat < 1023)  acc = fmaf(w2, xp[spat + 1], acc);
        if (w < 31)       acc = fmaf(w0, xp[spat + 1], acc);
        else if (h > 0)   acc = fmaf(w0, xp[(h - 1) * 32], acc);
        if (w > 0)        acc = fmaf(w2, xp[spat - 1], acc);
        else if (h < 31)  acc = fmaf(w2, xp[(h + 1) * 32 + 31], acc);
        if (h > 0)        acc = fmaf(w0, xp[spat - 32], acc);
        else if (w > 0)   acc = fmaf(w0, xp[992 + (w - 1)], acc);
        if (h < 31)       acc = fmaf(w2, xp[spat + 32], acc);
        else if (w < 31)  acc = fmaf(w2, xp[w + 1], acc);
        if (h < 31)       acc = fmaf(w0, xp[spat + 32], acc);
        else if (w > 0)   acc = fmaf(w0, xp[w - 1], acc);
        if (h > 0)        acc = fmaf(w2, xp[spat - 32], acc);
        else if (w < 31)  acc = fmaf(w2, xp[992 + (w + 1)], acc);
    }
    y[tid] = xv + acc;
}

__global__ void cross_scan_kernel3(const float* __restrict__ x,
                                   const float* __restrict__ weight,
                                   const float* __restrict__ bias,
                                   float* __restrict__ y,
                                   int C, int H, int W, int total) {
    int tid = blockIdx.x * blockDim.x + threadIdx.x;
    if (tid >= total) return;
    int s = tid;
    int w = s % W; s /= W;
    int h = s % H; s /= H;
    int c = s % C;
    int HW = H * W;
    int spat = h * W + w;
    int bc_base = tid - spat;
    const float* xp = x + bc_base;
    const float* wc = weight + c * 3;
    float w0 = wc[0], w1 = wc[1], w2 = wc[2];
    float xv = xp[spat];
    float acc = 4.0f * bias[c] + (4.0f * w1) * xv;
    if (spat > 0)      acc = fmaf(w0, xp[spat - 1], acc);
    if (spat < HW - 1) acc = fmaf(w2, xp[spat + 1], acc);
    if (w < W - 1)        acc = fmaf(w0, xp[spat + 1], acc);
    else if (h > 0)       acc = fmaf(w0, xp[(h - 1) * W], acc);
    if (w > 0)            acc = fmaf(w2, xp[spat - 1], acc);
    else if (h < H - 1)   acc = fmaf(w2, xp[(h + 1) * W + (W - 1)], acc);
    if (h > 0)            acc = fmaf(w0, xp[spat - W], acc);
    else if (w > 0)       acc = fmaf(w0, xp[(H - 1) * W + (w - 1)], acc);
    if (h < H - 1)        acc = fmaf(w2, xp[spat + W], acc);
    else if (w < W - 1)   acc = fmaf(w2, xp[w + 1], acc);
    if (h < H - 1)        acc = fmaf(w0, xp[spat + W], acc);
    else if (w > 0)       acc = fmaf(w0, xp[w - 1], acc);
    if (h > 0)            acc = fmaf(w2, xp[spat - W], acc);
    else if (w < W - 1)   acc = fmaf(w2, xp[(H - 1) * W + (w + 1)], acc);
    y[tid] = xv + acc;
}

__device__ __forceinline__ int spatial_from_rl(int n, int H, int W) { int row = n / W; int col = n - row * W; return row * W + (W - 1 - col); }
__device__ __forceinline__ int spatial_from_tb(int n, int H, int W) { int col = n / H; int row = n - col * H; return row * W + col; }
__device__ __forceinline__ int spatial_from_bt(int n, int H, int W) { int col = n / H; int rowf = n - col * H; return (H - 1 - rowf) * W + col; }

__global__ void cross_scan_kernel_generic(const float* __restrict__ x,
                                  const float* __restrict__ weight,
                                  const float* __restrict__ bias,
                                  float* __restrict__ y,
                                  int C, int H, int W, int K, int total) {
    int tid = blockIdx.x * blockDim.x + threadIdx.x;
    if (tid >= total) return;
    int s = tid; int w = s % W; s /= W; int h = s % H; s /= H; int c = s % C;
    int HW = H * W; int spat = h * W + w; int bc_base = tid - spat;
    int pos_lr = spat, pos_rl = h * W + (W - 1 - w), pos_tb = w * H + h, pos_bt = w * H + (H - 1 - h);
    int pad = K >> 1; const float* wx = weight + c * K; float acc = 4.0f * bias[c];
    for (int kk = 0; kk < K; ++kk) {
        int off = kk - pad; float wk = wx[kk]; int n = pos_lr + off;
        if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + n], acc);
        n = pos_rl + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_rl(n, H, W)], acc);
        n = pos_tb + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_tb(n, H, W)], acc);
        n = pos_bt + off; if ((unsigned)n < (unsigned)HW) acc = fmaf(wk, x[bc_base + spatial_from_bt(n, H, W)], acc);
    }
    y[tid] = x[tid] + acc;
}

torch::Tensor cross_scan_forward_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {
    int B = (int)x.size(0), C = (int)x.size(1), H = (int)x.size(2), W = (int)x.size(3), K = (int)weight.size(2);
    int total = B * C * H * W;
    auto y = torch::empty_like(x);
    int threads = 256, blocks = (total + threads - 1) / threads;
    if (K == 3 && C == 64 && H == 32 && W == 32) {
        cross_scan_kernel3_32_64<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), total);
    } else if (K == 3) {
        cross_scan_kernel3<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, total);
    } else {
        cross_scan_kernel_generic<<<blocks, threads>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>(), C, H, W, K, total);
    }
    return y;
}
"""

_ext = load_inline(name="cross_scan_ext_final", cpp_sources=_cpp_src, cuda_sources=_cuda_src, functions=["cross_scan_forward"], extra_cuda_cflags=["-O3", "--use_fast_math"], extra_cflags=["-O3"], verbose=False)

class ModelNew(nn.Module):
    def __init__(self, channels: int, kernel_size: int = 3):
        super().__init__()
        assert channels >= 1
        assert kernel_size % 2 == 1
        self.channels = channels
        pad = kernel_size // 2
        self.dw_conv = nn.Conv1d(channels, channels, kernel_size, padding=pad, groups=channels, bias=True)
    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return _ext.cross_scan_forward(x, self.dw_conv.weight, self.dw_conv.bias)