FW-GLM-5-1 · popcorn · pop_l123_st_gpt
correct 8_DeepSeekMoEGroundedTop2Routing.py
model
FW-GLM-5-1
turns / max
1 / 1
tool calls
1
tokens (total)
3666
wall clock
1476.2s
truncated
no
backend
cuda fp32
variant
popcorn
runtime
0.29 μs
ref runtime
0.05 μs
speedup
0.16x
started
2026-05-11T09:38:15Z
timingkernelbench.timing
kernel runtime
0.29 μs
ref runtime
0.05 μs
speedup
0.16x
kernel mean / median / std
0.29 / — / 3.64e-04 μs
ref mean / median / std
0.05 / — / 5.87e-04 μs
numerical precisioneval_kernel_against_ref
max abs error
5.36e-07
mean abs error
1.83e-08
max rel error
2.43e-06
mean rel error
6.88e-08
gpu memoryextended_metrics.measure_memory
kernel peak
35.32 MB
ref peak
35.76 MB
kernel / ref
0.99x
kernel launches / fusiontorch.profiler
kernel launches
1
ref launches
20
fusion ratio (ref / kernel)
20.00x
total cuda time
3 μs
SOL (speed-of-light)nsight_hardware_counters
SOL score (0–1)
0.004
dram util %
0.4%
compute util %
0.0%
bottleneck
unknown
dominant pipe
None
arithmetic intensity
—
ridge point
20.00
roofline / occupancynsight_hardware_counters
dram bandwidth
13.01 GB/s
dram util %
0.4%
fp32 tflops
—
fp32 util %
—
fp16 tflops
—
occupancy %
12.5%
bottleneck
unknown
dominant pipe %
—
arithmetic intensity
—
ridge point
20.00
L1 hit %
—
L2 hit %
54.8%
ld sectors / req
16.56
st sectors / req
—
regs / thread
32
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
4227.0%
short_scoreboard
5.1%
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn


class Model(nn.Module):
    """
    Grounded top-2 MoE router.

    Router logits are biased by token-expert similarity against learned
    grounding embeddings, then normalized over the selected top-2 experts.
    """

    def __init__(self):
        super().__init__()

    def forward(
        self,
        token_hidden: torch.Tensor,
        router_logits: torch.Tensor,
        expert_ground: torch.Tensor,
        alpha: float,
    ) -> torch.Tensor:
        grounded = router_logits + alpha * (token_hidden @ expert_ground.t())
        top_vals, top_idx = torch.topk(grounded, k=2, dim=-1)
        top_weights = torch.softmax(top_vals, dim=-1)
        return torch.stack((top_idx.to(torch.float32), top_weights), dim=-1)


num_tokens = 4096
hidden_dim = 128
num_experts = 16
alpha = 0.35


def get_inputs():
    p = popcorn_pri
    nt = p.jitter_int(num_tokens)
    hd = p.jitter_int(hidden_dim, align=16)
    ne = p.jitter_int(num_experts, minimum=2)
    token_hidden = torch.randn(nt, hd, dtype=torch.float32)
    router_logits = torch.randn(nt, ne, dtype=torch.float32)
    expert_ground = torch.randn(ne, hd, dtype=torch.float32)
    return [token_hidden, router_logits, expert_ground, alpha]



def get_init_inputs():
    return []
turn 0 · FINAL · 1 tool call(s) · 1476.2s turn · 29.7s LLM · tokens in=1,099 · out=2,567 · total=3,666 · 11,121 chars (click to expand)
turn 01476.2s turn · 29.7s LLM · 1446.5s tools · tokens in=1,099 · out=2,567 · total=3,666 · FINAL
reasoning
Let me analyze this task: 1. The model is a grounded top-2 MoE router 2. It computes: `grounded = router_logits + alpha * (token_hidden @ expert_ground.t())` 3. Then it finds top-2 values and indices 4. Then applies softmax to those top-2 values 5. Returns a stacked tensor of shape (num_tokens, 2, 2) containing indices and weights Let me trace through the shapes: - token_hidden: (num_tokens, hidden_dim) = (4096, 128) - router_logits: (num_tokens, num_experts) = (4096, 16) - expert_ground: (num_experts, hidden_dim) = (16, 128) - alpha: scalar float Operations: 1. expert_ground.t(): (hidden_dim, num_experts) = (128, 16) 2. token_hidden @ expert_ground.t(): (num_tokens, num_experts) = (4096, 16) 3. alpha * that result: (4096, 16) 4. router_logits + that: (4096, 16) - this is grounded 5. topk(grounded, k=2, dim=-1): top_vals (4096, 2), top_idx (4096, 2) 6. softmax(top_vals, dim=-1): (4096, 2) - this is top_weights 7. top_idx.to(float32): (4096, 2) 8. stack((top_idx_float, top_weights), dim=-1): (4096, 2, 2) So the output is (num_tokens, 2, 2) where: - output[i, :, 0] = top indices as float - output[i, :, 1] = softmax weights Now I need to write a CUDA kernel for this. Let me think about the optimal approach: 1. The matrix multiplication is the main computational work: (4096, 128) @ (128, 16) = (4096, 16) 2. After that, element-wise addition with router_logits occurs. 3. topk along the expert dimension requires finding the two largest values per token. 4. Softmax is then applied to those two values. 5. Finally, the indices and weights get stacked together. For performance, I could leverage cuBLAS for the matmul, then write a fused kernel to handle the bias addition, topk, softmax, and stacking operations all at once. This would reduce memory transfers between steps. The optimal strategy combines cuBLAS for the GEMM with a custom kernel for the subsequent operations. I'll use cublasGemm for the matrix multiplication, then implement a kernel that fuses the remaining steps together. For the fused component, I can have each thread handle one token row, computing the bias addition inline, then performing top-k selection and softmax normalization before outputting the results. This approach minimizes kernel launch overhead and memory bandwidth by keeping intermediate results in registers or shared memory. Here's the implementation structure: set up cuBLAS handle during initialization, compute the grounded matrix by scaling the similarity scores and adding them to router logits, then launch a kernel where each thread processes one token to find the top-k experts and compute their weights. The kernel iterates through all experts to find the two highest-scoring ones, then applies softmax to normalize their values. Finally, it writes the expert indices and their corresponding weights to the output tensor, packing them as (index, weight) pairs for each of the top-2 experts. The forward pass computes grounded scores by scaling the matrix multiplication result and adding it to the router logits, then launches the kernel with one thread per token to extract and weight the top experts. The output is transposed to match the expected shape of (num_tokens, 2, 2) where the two experts' indices and weights are stacked along the last dimension. For each token, we're selecting the top 2 experts with their corresponding weights, so the structure makes sense as expert_0_idx, expert_0_weight, expert_1_idx, expert_1_weight arranged across the final dimension. The PyTorch implementation achieves this by stacking the indices and weights tensors along dim=-1, which interleaves them correctly for the desired output format. For the CUDA kernel, I need to output in the same shape: (num_tokens, 2, 2). I'll use cuBLAS for the matmul, then apply topk with softmax. The output tensor gets arranged so position [i, j, 0] holds the expert index and [i, j, 1] holds its weight. I'll structure the kernel to compute this directly without intermediate transposes.
call → submit_kernel
callsubmit_kernel { "kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n# Compile CUDA kernel at module load time\ncuda_source = r\"\"\"\n#include <torch/extension.h>\n#include <cublas_v2.h>\n#include <cuda_runtime.h>\n#include <cfloat>\n\nstatic cublasHandle_t get_cublas_handle() {\n static cublasHandle_t handle = nullptr;\n if (handle == nullptr) {\n cublasCreate(&handle);\n }\n return handle;\n}\n\n__global__ void top2_softmax_kernel(\n const float* __restrict__ grounded, // (num_tokens, num_experts)\n float* __restrict__ output, // (num_tokens, 2, 2)\n int num_tokens,\n int num_experts\n) {\n int token_idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (token_idx >= num_tokens) return;\n \n const float* row = grounded + token_idx * num_experts;\n \n // Find top-2 values and indices\n float max1 = -FLT_MAX, max2 = -FLT_MAX;\n int idx1 = 0, idx2 = 0;\n \n // First pass: find max1\n for (int e = 0; e < num_experts; e++) {\n float val = row[e];\n if (val > max1) {\n max2 = max1;\n idx2 = idx1;\n max1 = val;\n idx1 = e;\n } else if (val > max2) {\n max2 = val;\n idx2 = e;\n }\n }\n \n // Softmax on top-2 values\n float max_val = fmaxf(max1, max2);\n float e1 = expf(max1 - max_val);\n float e2 = expf(max2 - max_val);\n float sum = e1 + e2;\n float w1 = e1 / sum;\n float w2 = e2 / sum;\n \n // Write output: (num_tokens, 2, 2)\n // output[token_idx, :, :] = [[idx1, w1], [idx2, w2]]\n output[token_idx * 4 + 0] = static_cast<float>(idx1); // [token_idx, 0, 0]\n output[token_idx * 4 + 1] = w1; // [token_idx, 0, 1]\n output[token_idx * 4 + 2] = static_cast<float>(idx2); // [token_idx, 1, 0]\n output[token_idx * 4 + 3] = w2; // [token_idx, 1, 1]\n}\n\n// Fused kernel: computes grounded = router_logits + alpha * (H @ G^T), then top2+softmax\n// Each thread handles one token, computes dot product with all experts\n__global__ void fused_top2_kernel(\n const float* __restrict__ token_hidden, // (num_tokens, hidden_dim)\n const float* __restrict__ router_logits, // (num_tokens, num_experts)\n const float* __restrict__ expert_ground, // (num_experts, hidden_dim)\n float* __restrict__ output, // (num_tokens, 2, 2)\n int num_tokens,\n int hidden_dim,\n int num_experts,\n float alpha\n) {\n int token_idx = blockIdx.x * blockDim.x + threadIdx.x;\n if (token_idx >= num_tokens) return;\n \n const float* hidden_row = token_hidden + token_idx * hidden_dim;\n const float* logits_row = router_logits + token_idx * num_experts;\n \n // Find top-2 grounded values and indices\n // grounded[i,e] = router_logits[i,e] + alpha * dot(hidden[i], ground[e])\n float max1 = -FLT_MAX, max2 = -FLT_MAX;\n int idx1 = 0, idx2 = 0;\n \n for (int e = 0; e < num_experts; e++) {\n // Compute dot product with expert e\n float dot = 0.0f;\n const float* ground_row = expert_ground + e * hidden_dim;\n for (int h = 0; h < hidden_dim; h++) {\n dot += hidden_row[h] * ground_row[h];\n }\n \n float grounded_val = logits_row[e] + alpha * dot;\n \n if (grounded_val > max1) {\n max2 = max1;\n idx2 = idx1;\n max1 = grounded_val;\n idx1 = e;\n } else if (grounded_val > max2) {\n max2 = grounded_val;\n idx2 = e;\n }\n }\n \n // Softmax on top-2 values (numerically stable)\n float max_val = fmaxf(max1, max2);\n float e1 = expf(max1 - max_val);\n float e2 = expf(max2 - max_val);\n float sum = e1 + e2;\n float w1 = e1 / sum;\n float w2 = e2 / sum;\n \n // Write output\n output[token_idx * 4 + 0] = static_cast<float>(idx1);\n output[token_idx * 4 + 1] = w1;\n output[token_idx * 4 + 2] = static_cast<float>(idx2);\n output[token_idx * 4 + 3] = w2;\n}\n\ntorch::Tensor grounded_top2_cuda(\n torch::Tensor token_hidden,\n torch::Tensor router_logits,\n torch::Tensor expert_ground,\n float alpha\n) {\n int num_tokens = token_hidden.size(0);\n int hidden_dim = token_hidden.size(1);\n int num_experts = router_logits.size(1);\n \n auto output = torch::empty({num_tokens, 2, 2}, \n torch::dtype(torch::kFloat32)\n .device(token_hidden.device()));\n \n int threads = 256;\n int blocks = (num_tokens + threads - 1) / threads;\n \n fused_top2_kernel<<<blocks, threads>>>(\n token_hidden.data_ptr<float>(),\n router_logits.data_ptr<float>(),\n expert_ground.data_ptr<float>(),\n output.data_ptr<float>(),\n num_tokens,\n hidden_dim,\n num_experts,\n alpha\n );\n \n return output;\n}\n\"\"\"\n\n# Load the CUDA extension\ngrounded_top2_ext = load_inline(\n name='grounded_top2_ext',\n cpp_sources=\"torch::Tensor grounded_top2_cuda(torch::Tensor, torch::Tensor, torch::Tensor, float);\",\n cuda_sources=cuda_source,\n functions=['grounded_top2_cuda'],\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n verbose=False\n)\n\n\nclass ModelNew(nn.Module):\n \"\"\"\n Grounded top-2 MoE router with custom CUDA kernel.\n \"\"\"\n \n def __init__(self):\n super().__init__()\n \n def forward(\n self,\n token_hidden: torch.Tensor,\n router_logits: torch.Tensor,\n expert_ground: torch.Tensor,\n alpha: float,\n ) -> torch.Tensor:\n return grounded_top2_ext.grounded_top2_cuda(\n token_hidden, router_logits, expert_ground, alpha\n )" }
result ← submit_kernel (ok)
oksubmit_kernel submit_kernel PASSED: (5 / 5) correctness trials all passed. Kernel runtime: 0.29 μs Runtime stats: mean=0.29μs median=?μs std=0.00μs Numerical precision: max_abs_err=5.36e-07 mean_abs_err=1.83e-08 max_rel_err=2.43e-06 Memory: 35.32 MB peak (ref: 35.76 MB, ratio: 0.9878x) Kernel launches: 1 (ref: 20, fusion ratio: 20.0) SOL score: 0.0039
final submitted kernel (184 lines, 5,652 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline

# Compile CUDA kernel at module load time
cuda_source = r"""
#include <torch/extension.h>
#include <cublas_v2.h>
#include <cuda_runtime.h>
#include <cfloat>

static cublasHandle_t get_cublas_handle() {
    static cublasHandle_t handle = nullptr;
    if (handle == nullptr) {
        cublasCreate(&handle);
    }
    return handle;
}

__global__ void top2_softmax_kernel(
    const float* __restrict__ grounded,  // (num_tokens, num_experts)
    float* __restrict__ output,          // (num_tokens, 2, 2)
    int num_tokens,
    int num_experts
) {
    int token_idx = blockIdx.x * blockDim.x + threadIdx.x;
    if (token_idx >= num_tokens) return;
    
    const float* row = grounded + token_idx * num_experts;
    
    // Find top-2 values and indices
    float max1 = -FLT_MAX, max2 = -FLT_MAX;
    int idx1 = 0, idx2 = 0;
    
    // First pass: find max1
    for (int e = 0; e < num_experts; e++) {
        float val = row[e];
        if (val > max1) {
            max2 = max1;
            idx2 = idx1;
            max1 = val;
            idx1 = e;
        } else if (val > max2) {
            max2 = val;
            idx2 = e;
        }
    }
    
    // Softmax on top-2 values
    float max_val = fmaxf(max1, max2);
    float e1 = expf(max1 - max_val);
    float e2 = expf(max2 - max_val);
    float sum = e1 + e2;
    float w1 = e1 / sum;
    float w2 = e2 / sum;
    
    // Write output: (num_tokens, 2, 2)
    // output[token_idx, :, :] = [[idx1, w1], [idx2, w2]]
    output[token_idx * 4 + 0] = static_cast<float>(idx1);  // [token_idx, 0, 0]
    output[token_idx * 4 + 1] = w1;                        // [token_idx, 0, 1]
    output[token_idx * 4 + 2] = static_cast<float>(idx2);  // [token_idx, 1, 0]
    output[token_idx * 4 + 3] = w2;                        // [token_idx, 1, 1]
}

// Fused kernel: computes grounded = router_logits + alpha * (H @ G^T), then top2+softmax
// Each thread handles one token, computes dot product with all experts
__global__ void fused_top2_kernel(
    const float* __restrict__ token_hidden,  // (num_tokens, hidden_dim)
    const float* __restrict__ router_logits,  // (num_tokens, num_experts)
    const float* __restrict__ expert_ground,  // (num_experts, hidden_dim)
    float* __restrict__ output,               // (num_tokens, 2, 2)
    int num_tokens,
    int hidden_dim,
    int num_experts,
    float alpha
) {
    int token_idx = blockIdx.x * blockDim.x + threadIdx.x;
    if (token_idx >= num_tokens) return;
    
    const float* hidden_row = token_hidden + token_idx * hidden_dim;
    const float* logits_row = router_logits + token_idx * num_experts;
    
    // Find top-2 grounded values and indices
    // grounded[i,e] = router_logits[i,e] + alpha * dot(hidden[i], ground[e])
    float max1 = -FLT_MAX, max2 = -FLT_MAX;
    int idx1 = 0, idx2 = 0;
    
    for (int e = 0; e < num_experts; e++) {
        // Compute dot product with expert e
        float dot = 0.0f;
        const float* ground_row = expert_ground + e * hidden_dim;
        for (int h = 0; h < hidden_dim; h++) {
            dot += hidden_row[h] * ground_row[h];
        }
        
        float grounded_val = logits_row[e] + alpha * dot;
        
        if (grounded_val > max1) {
            max2 = max1;
            idx2 = idx1;
            max1 = grounded_val;
            idx1 = e;
        } else if (grounded_val > max2) {
            max2 = grounded_val;
            idx2 = e;
        }
    }
    
    // Softmax on top-2 values (numerically stable)
    float max_val = fmaxf(max1, max2);
    float e1 = expf(max1 - max_val);
    float e2 = expf(max2 - max_val);
    float sum = e1 + e2;
    float w1 = e1 / sum;
    float w2 = e2 / sum;
    
    // Write output
    output[token_idx * 4 + 0] = static_cast<float>(idx1);
    output[token_idx * 4 + 1] = w1;
    output[token_idx * 4 + 2] = static_cast<float>(idx2);
    output[token_idx * 4 + 3] = w2;
}

torch::Tensor grounded_top2_cuda(
    torch::Tensor token_hidden,
    torch::Tensor router_logits,
    torch::Tensor expert_ground,
    float alpha
) {
    int num_tokens = token_hidden.size(0);
    int hidden_dim = token_hidden.size(1);
    int num_experts = router_logits.size(1);
    
    auto output = torch::empty({num_tokens, 2, 2}, 
                               torch::dtype(torch::kFloat32)
                               .device(token_hidden.device()));
    
    int threads = 256;
    int blocks = (num_tokens + threads - 1) / threads;
    
    fused_top2_kernel<<<blocks, threads>>>(
        token_hidden.data_ptr<float>(),
        router_logits.data_ptr<float>(),
        expert_ground.data_ptr<float>(),
        output.data_ptr<float>(),
        num_tokens,
        hidden_dim,
        num_experts,
        alpha
    );
    
    return output;
}
"""

# Load the CUDA extension
grounded_top2_ext = load_inline(
    name='grounded_top2_ext',
    cpp_sources="torch::Tensor grounded_top2_cuda(torch::Tensor, torch::Tensor, torch::Tensor, float);",
    cuda_sources=cuda_source,
    functions=['grounded_top2_cuda'],
    extra_cuda_cflags=['-O3', '--use_fast_math'],
    verbose=False
)


class ModelNew(nn.Module):
    """
    Grounded top-2 MoE router with custom CUDA kernel.
    """
    
    def __init__(self):
        super().__init__()
    
    def forward(
        self,
        token_hidden: torch.Tensor,
        router_logits: torch.Tensor,
        expert_ground: torch.Tensor,
        alpha: float,
    ) -> torch.Tensor:
        return grounded_top2_ext.grounded_top2_cuda(
            token_hidden, router_logits, expert_ground, alpha
        )