aiqbench analysis
NVIDIA's cuTile.jl extends its tile-based GPU programming model to Julia, allowing the ecosystem to leverage existing optimized kernels from cuTile Python without rewriting them. By utilizing an LLM skill in TileGym to automate this cross-DSL translation, developers can bypass manual porting while navigating critical semantic differences like indexing and memory layout between the two languages. This approach systematizes the creation of validated custom kernels for scientific computing, reducing the barrier to entry for high-performance GPU acceleration in Julia.
Automating GPU Kernel Translation with AI Agents: cuTile Python to cuTile.jl

NVIDIA CUDA Tile (cuTile) is a tile-based programming model that enables developers to write GPU kernels in terms of tile-level operations—loads, stores, and... NVIDIA CUDA Tile (cuTile) is a tile-based programming model that enables developers to write GPU kernels in terms of tile-level operations—loads, stores, and matrix multiply-accumulate—rather than manually coordinating threads, warps, and shared memory. cuTile.jl brings the same tile-based approach to the dynamic programming language Julia. Users can write custom GPU kernels without dropping… Source
NVIDIA CUDA Tile (cuTile) is a tile-based programming model that enables developers to write GPU kernels in terms of tile-level operations—loads, stores, and matrix multiply-accumulate—rather than manually coordinating threads, warps, and shared memory.
cuTile.jl brings the same tile-based approach to the dynamic programming language Julia. Users can write custom GPU kernels without dropping down to NVIDIA CUDA C++. Custom kernels are often essential in Julia’s scientific computing ecosystem— spanning differential equations, probabilistic programming, and physics simulations.
cuTile Python has a growing library of optimized kernels for GPU acceleration. The ability to translate those kernels to cuTile.jl provides the Julia ecosystem with immediate access to battle-tested implementations, instead of rewriting each one from scratch.
This post covers cross-domain-specific language (DSL) GPU kernel translation, from porting cuTile Python kernels to cuTile.jl (Julia). It shows how to:
Translate GPU kernels between cuTile Python and cuTile.jl: Walk through a complete matrix multiplication example side-by-side.
Avoid semantic traps that break naive translations: Indexing, broadcasting, memory layout, and loop forms all diverge between the two DSLs—and silent mismatches produce wrong results, not compiler errors.
Build a repeatable, skill-driven AI workflow: The translation knowledge is packaged into an LLM skill in TileGym that produces validated Julia kernels in a single pass, systematizing a one-off porting effort.
Both cuTile Python and cuTile.jl frontends share the same tiled abstraction, making the translation largely algorithmic. However, the cumulative surface-level differences between the two languages are non-trivial, as shown in Table 1.
Julia (cuTile.jl)
0-based (ct.bid(0))
1-based (ct.bid(1))
Explicit dot syntax (a .+ b)
@ct.kernel decorator
Plain function ... end
param: ct.Constant[int] in signature
param::Int in signature, ct.Constant(val) at launch
tile.astype(ct.float32)
convert(ct.Tile{Float32}, tile)
ct.mma(a, b, acc=acc)
Table 1. High-level differences between writing tile code in Python versus Julia
None of these translations are conceptually difficult, but miss one ct.bid(0) that should be ct.bid(1), and you get silent data corruption. Use * instead of .* for element-wise multiply, and Julia silently does a matrix multiply instead. These are the kinds of bugs that waste hours.
A shared abstraction with a finite set of recurring pitfalls is well-suited for an AI-assisted workflow—if the model is taught what to watch out for.
Translating cuTile Python to cuTile.jl
The process is best understood through actual code. The following examples are from TileGym, where the team ported a set of cuTile Python kernels to cuTile.jl and packaged them as a self-contained Julia subproject.
The running example uses matmul, which is complex enough to show key translation challenges. Beyond basic syntax differences, the translation must handle loop structure, TF32 tensor core conversion, and the shift from row-major to column-major layout.
cuTile.jl (Julia):
The layout flips: The Python row-major A(M,K) becomes column-major A_jl(K,M) in Julia. The accumulator, load indices, and store indices all change accordingly. Get the accumulator shape wrong—say (TM, TN) instead of (TN, TM)—and you get wrong results with no compiler warning.
ct.mma → muladd: cuTile.jl maps matrix multiply-accumulate to the Julia standard muladd, and ct.PaddingMode.ZERO becomes ct.PaddingMode.Zero (PascalCase).
Softmax pushes things further. Three strategies were implemented in Julia—tensor memory accelerator (TMA) single-tile, online, and chunked—to handle different tensor sizes. On top of the matmul patterns, the softmax function brings in broadcast dot syntax (ct.exp(ct.sub(a, b)) → exp.(a .- b)), renamed reductions (ct.max → maximum, ct.sum → sum, axis +1), and element-wise ct.maximum(a, b) → max.(a, b).
But the real challenge isn’t syntax—it’s maintaining correct running max/sum statistics through the translation.
The primary outcome of this project wasn’t the translated kernels—it was the skill built to produce them.
Figure 1. The conversion skill packages translation rules, API mappings, examples, validation, and tests into a single reusable workflow
A skill, in this context, is a directory of structured knowledge that lives in the repository and is picked up by an LLM agent. The path to this particular skill is:.claude/skills/converting-cutile-to-julia/.
The critical-rules.md alone captures 17 pitfalls the team encountered. Table 2 details the most common pitfalls and the associated fixes.
Use max.(a, b) (broadcast dot)
ct.load with order — index positions wrong
Table 2. Pitfalls and associated fixes for some of the more common issues encountered
There’s also a static validator script that catches things like leftover ct.bid(0), for loops inside kernels, and Python-style type names—before running on the GPU. With all of this in place, the model doesn’t have to rediscover the conversion rules each time. It reads the skill, follows the checklist, and applies the rules.
These three kernels were deliberately selected. Kernel add is the simplest method to test the full translation surface. Matmul adds loop structure, tensor cores, and the layout flip. Softmax introduces multipass algorithms with invariants that have to survive translation. Each kernel has tests that compare against a CPU reference with per-dtype tolerances, including boundary cases where dimensions don’t align to tile sizes.
Pre-flight: Scan the source for patterns that require special handling (for loops, ct.mma, order=, and so on).
Convert: Apply the API mapping and critical rules.
Validate: Run the static checker.
Test: Run Julia tests against reference implementations.
Fix: If something fails, use the debugging guide, fix, and rerun.
For a representative general matrix multiply (GEMM) conversion, the process took about 4 minutes and ~78K tokens on a frontier LLM with no manual intervention. Subsequent kernels were faster because the examples and rules were already in the repo.
Table 3 lists the pitfalls that caused bugs during ports, all of which are now handled automatically in the skills.
ct.bid(0) left unchanged
Julia * is matmul; need .*
ct.PaddingMode.ZERO
Julia uses PascalCase: .Zero
Table 3. Common pitfalls, symptoms, and root causes that cause bugs during the porting of tile code from Python to Julia
The takeaway isn’t that AI wrote the code. It’s the ability to capture what was learned into something the model can reuse next time. A prompt can say, “Be careful with indexing.” A skill can say, “Here are the 17 specific things that go wrong, here’s how to check for them, and here’s a script that catches them automatically.”
Now, future ports can start from a repo that already has working examples, a tested API mapping, a static validator, and a debugging guide. Each one takes less effort than the last.
A broader takeaway is that the challenge in using AI for systems work isn’t code generation—it’s producing correct code in domains where the compiler won’t catch semantic mistakes. Encoding domain rules in version control, alongside the code they describe, is one way to address this.
Julia 1.12+ and NVIDIA CUDA 13.1+ driver
NVIDIA Ampere, NVIDIA Ada, or NVIDIA Blackwell GPU (compute capability 8.x, 10.x, 11.x, 12.x)
An LLM agent with file system access (for example, Claude Code). To use the conversion skill for your own kernels, point your LLM agent at .claude/skills/converting-cutile-to-julia/SKILL.md, provide a cuTile Python kernel as input, and start translating Python kernels to Julia.
Full text under the publisher's open licence · 1131 words
Related coverage

Translating CUDA Tile Operations from Python to Rust Using Agentic AI
NVIDIA · Sep 16, 2026

Academia is for Ambition — Alex Zhang, MIT
Latent Space · Oct 2, 2026

[AINews] not much happened today
Latent Space · Sep 10, 2026

Hyperloom - Autonomous Agentic Inference Optimization for AMD GPUs
AMD · Jul 23, 2026