Adding a cuTile Kernel to TileGym
End-to-end workflow for adding a new operator (e.g., my_op) with cuTile backend.
Execution Rules
MUST follow these rules strictly:
- Use TodoWrite to create the checklist below BEFORE writing any code
- Execute steps in order — do NOT skip ahead or combine steps
- Mark each todo as
completedafter finishing,in_progresswhen starting - If a step is not applicable (e.g., no cuTile impl), mark it
completedwith a note, do NOT silently skip - Each step MUST result in a file write or explicit skip decision — no silent omissions
Instructions
MUST copy this checklist to TodoWrite at the start:
Step 1: Register dispatch interface
File: src/tilegym/ops/ops.py
Add a @dispatch function — this is the single entry point for all backends.
Key rules:
- Function body only raises
NotImplementedError - Include
**kwargsfor backend-specific parameters
Reference: See existing ops in src/tilegym/ops/ops.py (e.g., silu_and_mul, softmax)
Step 2: Implement cuTile backend
File: src/tilegym/ops/cutile/my_op.py
The file structure follows this template:
Reference: src/tilegym/ops/cutile/silu_and_mul.py
Step 3: Register in __init__.py (CRITICAL)
Missing this step means the cuTile backend implementation never gets loaded.
File: src/tilegym/ops/cutile/__init__.py
Add inside if is_backend_available("cutile"): block (alphabetically):
And in the function import section:
And add "my_op" to __all__.
Step 4: Add tests
File: tests/ops/test_my_op.py
CRITICAL: Always import from tilegym.ops, NEVER from tilegym.ops.cutile.my_op.
Key patterns:
_backends = ["cutile"]test_op: useset_backend(backend)with try-except, callself.setUp()
Reference: tests/ops/test_silu_and_mul.py
Below is the common errors.
Step 5: Add benchmark to tests/benchmark
File: tests/benchmark/bench_my_op.py
Key rules from benchmark_rules.md:
- Call the op via
tilegym.ops.my_op(a, b, ..., backend=backend)— do not useset_backend. - Define
ALL_BACKENDS(include at leastcutileandtorch), filter withget_supported_backends(). - Implement
reference_my_op(...)and register it:register_impl("my_op", "torch")(reference_my_op). - Use
create_benchmark_config()to buildtriton.testing.Benchmarkconfigs (e.g. by shape/dtype). - Use
@triton.testing.perf_report([...])onbench_my_op(...); inside the bench function: correctness check withtorch.testing.assert_close(fn(), ref(), ...), thenms = triton.testing.do_bench(fn)(ordo_bench_cudagraph), compute GB/s or TFLOPS, and return the metric. - Entry point:
if __name__ == "__main__": bench_my_op.run(print_data=True).
Template structure:
Benchmark Plot Names: Must include -TFLOPS or -GBps suffix
- Example:
plot_name=f"persistent-layer-norm-M{num_rows}-{dtype_name}-GBps"


