Popcorn: Democratized Fast Kernel Dispatching | Tilde

9 min read Original article ↗

Back

TL;DR

Frontier model architecture research keeps changing the op inventory, but most of the stack still assumes a small, stable set of fused kernels. Choosing a correct, fast implementation across packages, shapes, dtypes, and GPUs is hard — and a speedup is worthless if it produces the wrong answer.

Popcorn sits between kernels and users. You call a stable, reference-backed op API; Popcorn routes each call to the fastest implementation validated for those inputs and hardware. Today we are open-sourcing it.

Validated kernel dispatch across tensor shape space

Outline

  1. Introduction — Kernel selection as infrastructure
  2. Design — Contracts, dispatch, correctness, agents
  3. Optimize Modeling Code — Uniform Popcorn API
  4. How to Write a Kernel — Reference, impl, validate, bench
  5. The Popcorn Bundle — Dispatch portfolio and explorer
  6. The Future of Popcorn — More devices, agentic loops, contributions

1: Introduction

Frontier model architecture research presents an open engineering question that most of the stack was never designed to answer: how do you train, optimize, and ship models when the model architecture itself keeps changing? Most libraries and modeling code presume that the op inventory stays somewhat stable. Although it becomes increasingly clear that model architecture is a huge lever in pushing the frontier, current infrastructure is built so that the same handful of fused kernels cover the hot path. That is not our world. Over the past year we have trained thousands of models while pushing the boundaries of model architecture, and we have had to build custom infrastructure to keep up with that pace of experimentation.

One of the sharpest pain points is deciding which kernel to use. The open-source ecosystem is rich: research releases ship kernels, some are tested, some are integrated into libraries, and collections like FLA [1] and Liger [2] gather many of them in one place. But with so many collections, lone kernels, and vendor paths in play, there is no practical way to hand-pick the fastest correct implementation for every op, shape, dtype, and GPU we care about. Numerical errors show up constantly and quietly derail progress. A speedup is worthless if it produces the wrong answer, so confidence in correctness has to come before chasing milliseconds. We want to squeeze performance as we scale, and we want to take full advantage of open source. But inconsistent APIs, mismatched test grids, and incomparable benchmarks make it hard to compare kernels, trust them, or even wire them into a training stack without constant glue work.

To make this ecosystem usable at the pace of model architecture research, kernel selection and development has to become a measured infrastructure problem rather than a recurring integration project that arises with each model architecture. That is why we built Popcorn. Popcorn is a layer between kernels and users. Users call a stable, reference-backed op API, and Popcorn routes each call to the fastest implementation validated for those inputs and hardware. This lets model code benefit from an evolving kernel ecosystem without inheriting its fragmentation or correctness risks.

Today, we're open-sourcing Popcorn and publishing it as a Python package on PyPI. The recommended install is uv pip install popcorn. We hope it gives researchers and kernel engineers a common foundation for comparing implementations, integrating new work, and sharing improvements across the ecosystem.

2: Design

Popcorn is built around a few deliberate bets:

Figure 1. The five principles behind Popcorn's validation and dispatch model.

A contract per op. Every kernel has a pure PyTorch reference that defines semantics (shapes, dtypes, defaults, and gradients) and serves as the correctness oracle. Together, these properties form a contract: for any supported input, a valid implementation must produce the same output as the reference. The contract is one-sided: an implementation may support only a subset of valid inputs, but it must match the reference on every input it claims to support.

Dispatch is data-driven. Every kernel call is implicitly a dispatch request: given inputs, the Dispatcher's goal is to match it with the fastest implementation that satisfies the contract. Candidate implementations are filtered by package availability, shape and dtype support, and optional predicates. A cached performance grid is referenced to map regions of the input space to the best backend, avoiding repeated benchmarking while adapting its choice to the workload.

Correctness is never trusted. Popcorn ships a comprehensive test suite that runs against every kernel implementation to establish its correctness bounds. Failures and crashes are first-class outcomes: a timing result can inform routing only if its output passes validation. Although validating every valid combination of inputs is infeasible, unvalidated paths are never silently treated as correct.

Build where you run. Popcorn is designed so new kernels and implementations can be developed and evaluated in the environments where they will run. Its large collection of kernels makes it particularly easy to compare new algorithms with existing ones and develop high-performance implementations without compromising correctness. We encourage the community to share what they build by contributing to Popcorn's first-party kernel collection.

Agents are in the loop. The project was designed with agents in mind. The repository includes machine-readable documentation, agent instructions, and an experimental optimization loop inspired by AutoKernel [3]. The loop builds on the same validation and benchmarking harness to help agents produce reliable kernels.

3: Optimize Modeling Code

Consider training code for a small hybrid LM written in plain PyTorch, with alternating Gated DeltaNet and Wall Attention blocks.

from fla.modules.activations import swiglu
from fla.modules.layernorm import rms_norm
from liger_kernel.transformers.functional import (
    liger_fused_linear_cross_entropy,
    liger_rope,
)
from wall_attn.training import wall_attn

# ...
h = swiglu(gate, up)
# ...
h = rms_norm(h, weight, None, eps=1e-6)
# ...
q, k = liger_rope(q, k, cos, sin)
# ...
h = wall_attn(q, k, v, g, None, None, None, None)
# ...
loss = liger_fused_linear_cross_entropy(h, lm_head_weight, labels)
# ...

We replace the corresponding calls with the uniform Popcorn interface. Kernel selection and dispatching will occur automatically.

from popcorn.kernels import (
    swiglu,
    rms_norm,
    rope,
    linear_cross_entropy,
    wall_attn,
)

# ...
h = swiglu(gate, up)
# ...
h = rms_norm(h, weight)
# ...
q, k = rope(q, k, cos, sin)
# ...
h = wall_attn(q, k, v, g)
# ...
loss = linear_cross_entropy(h, lm_head_weight, labels)
# ...

Popcorn also supports an experimental compile hook that replaces subgraphs that match supported kernels with a Popcorn kernel dispatcher to accelerate existing modeling code with no adapting or monkey-patching. For more information, refer to the Popcorn documentation.

4: How to Write a Kernel

Writing a new kernel follows the same pattern as using one: define one clean interface, then let Popcorn handle validation and selection behind it.

Suppose we want to fuse Q/K RMS normalization with rotary embeddings. Before we write a fast implementation, we start with a clear PyTorch reference — the contract every backend must match.

import torch
from jaxtyping import Float
from torch import Tensor

from popcorn import Tag, register_kernel


def _rotate_half(x):
    x1, x2 = x.chunk(2, dim=-1)
    return torch.cat((-x2, x1), dim=-1)


@register_kernel(
    test_args={"eps": [1e-6]},
    tags={Tag.NORMALIZATION, Tag.POSITIONAL, Tag.FUSED},
)
def qk_norm_rope(
    q: Float[Tensor, "batch q_heads seq head_dim"],
    k: Float[Tensor, "batch kv_heads seq head_dim"],
    q_weight: Float[Tensor, "head_dim"],
    k_weight: Float[Tensor, "head_dim"],
    cos: Float[Tensor, "cos_batch seq head_dim"],
    sin: Float[Tensor, "cos_batch seq head_dim"],
    eps: float = 1e-6,
) -> tuple[
    Float[Tensor, "batch q_heads seq head_dim"],
    Float[Tensor, "batch kv_heads seq head_dim"],
]:
    def norm(x, weight):
        rstd = torch.rsqrt(x.float().square().mean(-1, keepdim=True) + eps)
        return (x.float() * rstd * weight.float()).to(x.dtype)

    q, k = norm(q, q_weight), norm(k, k_weight)
    cos, sin = cos.detach()[:, None], sin.detach()[:, None]
    return (
        q * cos + _rotate_half(q) * sin,
        k * cos + _rotate_half(k) * sin,
    )

The shape annotations using jaxtyping define the public API and input geometry. Popcorn uses them to construct test cases, while the reference remains the correctness oracle.

The optimized implementation lives separately and keeps that same signature. It can be Triton, CUDA, or an adapter around an existing library.

# src/popcorn/impls/qk_norm_rope_tl.py
def qk_norm_rope(q, k, q_weight, k_weight, cos, sin, eps):
    return (
        _NormRope.apply(q, q_weight, cos, sin, eps),
        _NormRope.apply(k, k_weight, cos, sin, eps),
    )

Registering it is just a lazy source reference:

# src/popcorn/kernels/qk_norm_rope.py
qk_norm_rope.register(
    "popcorn",
    source="popcorn.impls.qk_norm_rope_tl.qk_norm_rope",
)

That is it. There are no hand-written shape ranges or priority rules. Popcorn establishes where the implementation is correct and fast through the same validation and benchmark harness used for every backend.

for record in qk_norm_rope.validate(**inputs):
    report(record)

for record in qk_norm_rope.benchmark(**inputs):
    report(record)

Then the full grid turns that evidence into dispatch policy:

uv run popcorn bench run qk_norm_rope --backend popcorn

Passing results expand the region where the new implementation can serve calls. Outside that evidence, Popcorn keeps the same public API and safely falls back to the PyTorch reference.

5: The Popcorn Bundle

Popcorn does not ship a new kernel brand, but rather a validated dispatch envelope. For each op × dtype × shape, we keep only backends that pass the contract, then pick the fastest.

Popcorn stands on the shoulders of the open-source kernel ecosystem: flash-linear-attention [1], Liger-Kernel [2], quack [4], flash-attention [5], NVIDIA cuDNN Frontend [6], NVIDIA Transformer Engine [7], and Unsloth [8]. The optimized backends it dispatches to are built and maintained by their authors.

Loading portfolio…

Figure 2. Dispatch winners across featured operations, with validation outcomes across the full H100 suite. Unsupported cases are excluded from validation rates.

Across ops the winner is rarely uniform. On swiglu and rms_norm the envelope moves among fla / liger / unsloth as width changes, but on attn it moves among fa3 / fla / cudnn / torch. On gated_delta_rule, fla:recurrent dominates when it passes. Gray cells are demonstrate correctness issues where timing alone would be misleading.

Loading dispatch explorer…

Figure 3. Shape-dependent dispatch on H100.

6: The Future of Popcorn

This release only ships benchmark evidence for H100s, but Popcorn is designed to be a gateway for kernels on any hardware, and we plan to expand coverage as adoption grows across domains. The bigger shift we're preparing for is that more and more kernels will be written by AI agents. Writing a candidate kernel is becoming cheap; filtering and validating the results is still the hard part, and it's exactly what Popcorn's harness is positioned to do. In this spirit, we're working on two experimental workflows:

  1. An optimization loop, inspired by AutoKernel [3], built on top of Popcorn's correctness and benchmarking harness. Popcorn's strict handling of interfaces gives agents consistent, reliable feedback on every candidate they produce.
  2. Deeper fusion into torch.compile. Our experimental compile hook detects subgraphs that match supported kernels and routes them through Popcorn's dispatcher. This enables acceleration without requiring constant rewrites or monkey-patching.

From here on we plan to release our kernel work through Popcorn, and we'd love for you to contribute yours.

Cite this work

@article{tilde2026popcorn,
  title   = {Popcorn: Democratized Fast Kernel Dispatching},
  author  = {Averbuch, Timor and Pai, Dhruv},
  year    = {2026},
  url     = {https://tilderesearch.com/blog/popcorn}
}

References

  1. Liger Kernel: Efficient Triton Kernels for LLM Training

    Hsu, P.-L., Dai, Y., Kothapalli, V., Song, Q., Tang, S., Zhu, S., Shimizu, S., Sahni, S., Ning, H., and Chen, Y. (2024)

    .