Skip to content

Build1 publisher3 min readPublished

Diffing Tile IR catches the kernel ports that pass tests and are still wrong

NVIDIA put all 24 public TileGym operators through an agent pipeline into cuTile Rust at 99.5% of cuTile Python performance on average, with a Tile IR diff deciding at each stage whether a conversion advanced.

The Engineer · Build desk

Illustration accompanying Diffing Tile IR catches the kernel ports that pass tests and are still wrong

What happened

  • NVIDIA's team built an AI agent skill that translates cuTile Python and Triton-TileIR kernels into cuTile Rust, so the TileGym production kernel library can be used from Rust.
  • All 24 public TileGym operators were ported with the skill and reached 99.5% of cuTile Python performance on average, across roughly 40 GPU kernels.
  • Each conversion runs a bounded multi-agent pipeline covering analysis, device kernel, host and FFI code and benchmarking, with every stage ending in a machine-checkable verdict from validator scripts and Tile IR diffs.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint The structural check depends on the reference and the translation compiling to the same dialect. Where the two toolchains share no IR, the agent pipeline runs and the diff that made its output acceptable does not.
  • cost The adoption cost lands on the kernel signature. Every specialization the Python JIT inferred has to be found and declared, so the porting effort scales with how much a kernel left implicit.
  • capability Acceptance can now reject a translation that passes its tests, because a wrong cost hint or a missing divisibility attribute shows up in the IR comparison rather than in production performance.
  • precedent A vendor publishing per-stage machine-checkable verdicts sets a bar for the next agentic-porting claim: without a reference artifact to diff against, the number is a benchmark result and not evidence of a faithful port.

The agent has to close a declaration gap. cuTile Python's JIT specializes each kernel implicitly at call time, while the Rust front end requires every specialization to be declared in the kernel's signature [7]. Translating a kernel means recovering what the Python version never had to say, and writing it down.

That buys an earlier failure. The Rust source is compiled ahead of time, and rustc checks tile shapes and element types [13]. The crate embeds the kernel AST, and at first launch the runtime specializes it with the concrete const-generic values and compiles a cubin, cached after that [14]. The GPU binary is still JIT-compiled [14]. Nothing is specialized unless the signature declares it [14].

Other projects can reuse the check, and it works because of where the front ends meet. cuTile Python, Triton-TileIR and cuTile Rust are three front ends over one IR, the cuda_tile dialect, and all three feed the same tileiras compiler, which performs the tile-level optimizations and emits the GPU binary [8]. NVIDIA defines a faithful port as one that reproduces the reference kernel's IR structure: the same memory-op families, the same tile shapes, the same reductions [10]. Both sides can be dumped and diffed before a single test is executed [10].

That catches a class of error tests do not. NVIDIA gives two examples, a TMA load with the wrong cost hint and a dropped divisibility attribute, either of which can pass tests while being incorrect outside test coverage and may bring performance regressions [11]. Comparison against the reference IR finds them, and the IR diff stage is central to the pipeline [11][12].

For the 99.5% to say anything about someone else's port, the source and target have to compile through the same optimizer. NVIDIA describes the job as re-expressing the same tile program in a safer host language, with the same compiler and the same performance model underneath. It is not a re-optimization [9]. Remove the shared IR and the diff has no reference. Acceptance then falls back to tests and benchmarks. The wrong-but-plausible port survives that [11].

The headline figure averages over 24 operators containing roughly 40 GPU kernels [3][4], about 1.7 kernels per operator [17]. The set spans element-wise operations up to flash-attention decode, Multi-head Latent Attention and mixture-of-experts models [4]. A 0.5% average shortfall [18] across a set that includes memory-bound element-wise kernels is not the same claim as a 0.5% shortfall on MoE, and the post reports the average without per-kernel numbers. It also states the average against cuTile Python, while each conversion started from whichever reference the operator had, cuTile Python or Triton-TileIR [5].

Inside TileGym, adoption is a backend switch: tilegym.set_backend("cutile-rs") routes the same operator API to the Rust kernels [15]. cuTile Rust extends the Rust ownership model to tile-based GPU kernels, splitting mutable outputs into disjoint pieces and preserving the host-side ownership contract across kernel launches, and it lets a programmer opt out locally to execute Tile IR operations directly when lower-level control is needed [1]. The skill ships in the TileGym repo [16].

What to watch

  • Whether NVIDIA publishes the per-kernel distribution behind the 99.5% average, including the worst case among the roughly 40 kernels.
  • Whether the skill's validators hold up on kernels outside TileGym, where there may be no reference Tile IR to diff against.
  • Whether other GPU kernel projects adopt IR comparison as the acceptance gate for agent-generated code.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories