Compiling¶
Turning a program or a @pl.jit kernel into device kernels and host orchestration.
Concept¶
Compilation runs the pass pipeline over your IR, generates PTO for each InCore function,
hands that to ptoas for the device binary, and emits the host orchestration that
launches them. What you get back is a CompiledProgram — a handle to a directory of
artifacts plus the metadata the runtime needs to dispatch them.
There are two entry points and they differ only in where the IR comes from.
ir.compile(program) takes a @pl.program class. kernel.compile(*args) takes a
@pl.jit function plus sample arguments, specializes it against their shapes, and then
does the same thing.
Quickstart: compile and keep the artifacts¶
import pypto.language as pl
import torch
from pypto.runtime import RunConfig
CFG = RunConfig(platform="__PLATFORM__")
torch.manual_seed(0)
A = torch.randn(128, 128, dtype=torch.float32)
B = torch.randn(128, 128, dtype=torch.float32)
@pl.jit
def add(a: pl.Tensor, b: pl.Tensor, out: pl.Out[pl.Tensor]):
with pl.at(level=pl.Level.CORE_GROUP):
out[:] = pl.add(a, b)
return out
out = torch.zeros(128, 128, dtype=torch.float32)
compiled = add.compile(A, B, out, config=CFG)
print("artifacts in:", compiled.output_dir)
assert compiled.platform == CFG.platform
assert compiled.param_names == ["a", "b", "out"]
compile()'s positional arguments are the kernel's own arguments, not compile options.
add.compile(skip_ptoas=True) is bound against the kernel signature and raises
TypeError: got an unexpected keyword argument; compile options travel in
config=RunConfig(...).
Mechanics¶
ir.compile parameters¶
Eighteen, of which four carry most decisions. The rest have defaults you rarely
move. All are keyword-only — only program is positional.
| Parameter | Default | What it decides |
|---|---|---|
program |
— | The ir.Program to compile |
output_dir |
None |
Where artifacts land; None means <base>/<name>_<timestamp> under PYPTO_PROG_BUILD_DIR or build_output |
strategy |
Default |
The pass pipeline. Default is the only strategy |
dump_passes |
True |
IR snapshot after every pass — see below |
backend_type |
Ascend910B |
Target for passes and codegen (Ascend910B / Ascend950) |
platform |
None |
Execution platform the artifact is built for; must match the worker that dispatches it |
skip_ptoas |
False |
Stop at .pto (MLIR) instead of building the device binary |
verification_level |
None |
NONE / BASIC / ROUNDTRIP; None defers to PYPTO_VERIFY_LEVEL, else BASIC |
memory_planner |
None |
PYPTO / DSA_RP / PTOAS — who plans on-chip buffers (Memory) |
diagnostic_phase |
None |
Which phase warnings and perf hints are gated at |
disabled_diagnostics |
None |
Silence specific checks rather than all of them |
profiling |
False |
Per-stage compile timing into report/pipeline_profile.{txt,json} |
distributed_config |
None |
Compile a HOST-level program per rank (Distributed) |
analyze_auto_scopes_for_deps |
False |
Compiler-derived dependencies for AUTO scopes |
enable_pypto_l0c_double_buffer |
None |
L0C double buffering |
emit_source_loc |
None |
Carry DSL source locations into the emitted .pto |
dump_ptoas_passes |
False |
Also dump ptoas's own pass IR |
runtime |
None |
Simpler runtime ABI to target — TENSORMAP_AND_RINGBUFFER or HOST_BUILD_GRAPH (what @pl.jit.graph needs — Functions); None inherits the active PassContext. The worker must match it |
Pass dumps¶
dump_passes accepts a bool or a PassDumpLevel:
| Value | Effect |
|---|---|
False / PassDumpLevel.NONE |
No snapshots |
True / PassDumpLevel.CONCISE |
One snapshot per pass |
PassDumpLevel.EXPLICIT |
Same, with implicit tile layouts and distributed window buffers resolved |
They land in <output_dir>/passes_dump/NN_after_<PassName>.py, numbered in execution
order. EXPLICIT is what the memory map reads, and what you
want when the question is "which pass changed this".
What ends up in the output directory¶
| Path | Holds |
|---|---|
passes_dump/ |
Per-pass IR snapshots, when dump_passes asks for them |
ptoas/ |
Generated .pto per InCore function, beside the .cpp ptoas produced |
kernels/ |
The compiled device kernels |
report/perf_hints.log |
Compile-time performance hints (Performance) |
report/pipeline_profile.* |
Per-stage compile timing, when profiling=True |
dfx_outputs/ |
Written at run time by the DFX flags, not by compilation |
JITFunction.compile¶
@pl.jit normally fuses specialize + compile + dispatch into one kernel(*args) call.
compile(*sample_args) stops after compilation and returns the CompiledProgram the JIT
cache holds — so a later call with the same specialization key gets the identical object.
It exposes the whole extraction surface, which is what a harness driving the runtime
directly needs: chip_callable, runtime_name, runtime_config, output_dir,
platform, output_indices, param_names, orchestration_names, has_return.
Argument marshalling is not part of that surface — dispatch through
ChipWorker, which does it for you.
lower(*args) goes one step less far: it runs the passes and returns the Program,
writing no artifacts — which also means no passes_dump/. It is the right form for
torch codegen, which wants the IR itself; the
memory map reads a dump on disk and therefore needs
compile().
Edge Cases¶
| Symptom | Cause | Fix |
|---|---|---|
TypeError: got an unexpected keyword argument |
Compile option passed positionally to compile() |
Put it in config=RunConfig(...) |
| Worker rejects the artifact | platform at compile time differs from the worker's |
Compile with the platform you will dispatch on |
No passes_dump/ |
lower() writes no artifacts; dump_passes=False |
Use compile(), or pass dump_passes=PassDumpLevel.EXPLICIT |
| Memory map has nothing to draw | memory_planner=PTOAS skips AllocateMemoryAddr, so the dump carries no offsets |
Compare end to end instead |
verification_levelis a debugging lever, not a default to raise.BASICis the default — unlessPYPTO_VERIFY_LEVELsays otherwise, since the parameter defers to it when leftNone.ROUNDTRIPadditionally reparses each dump and is markedly slower. Raise it when you suspect malformed IR, and put it back.
See Also¶
- Running — dispatching what this page produced.
- Pass Manager — the pipeline
strategyselects. - Debugging — reading the IR this page dumps.
- Precision — when compilation succeeds but the numbers are wrong.