Interactive Optimization with the SDFG API
Frontends produce a baseline SDFG that mirrors the structure of the user’s source program. The Python SDFG API exposes every node, edge, and property of that graph as a regular Python object, so an SDFG can be optimized incrementally from a notebook or REPL session without recompiling the program after every change. This page collects the entry points most often needed when driving that loop by hand.
Loading and inspecting a baseline
Any SDFG produced by a frontend or saved to disk can be loaded interactively:
import dace
sdfg = dace.SDFG.from_file('matmul.sdfg') # JSON or .sdfgz
sdfg.view() # opens VS Code or Jupyter
sdfg.validate() # raise on inconsistencies
The view() call renders the graph through the
SDFV viewer. validate() will raise descriptive
exceptions on common issues such as missing memlets, dangling connectors, or
undefined symbols.
Operating on the graph
The SDFG is just a stateful graph object. The most common operations are:
Iterating:
sdfg.states(),sdfg.all_nodes_recursive(),sdfg.arrays.items().Locating nodes by predicate, e.g.
[n for n, _ in sdfg.all_nodes_recursive() if isinstance(n, dace.nodes.MapEntry)].Editing properties in place: changing
schedule,storage, ordata.Saving and reloading checkpoints with
save()followed byfrom_file().
Each of these is safe to do inside a live session (even a notebook), as the SDFG
is a pure Python data structure until you call compile().
Applying transformations interactively
The transformation API provides three idioms for firing a transformation from Python:
Pattern matching with
apply_transformations()orapply_transformations_repeated()walks the graph, finds every match for a transformation class, and applies it. These methods accept a list of classes and anoptionsdictionary, making them convenient for batch experiments.Direct application via the
apply_toclass method targets a specific subgraph by passing the matched nodes as keyword arguments. This is the form used inside notebooks when you already know the nodes you want to operate on:from dace.transformation.dataflow import MapFusion MapFusion.apply_to(sdfg, first_map_exit=exit1, array=array_node, second_map_entry=entry2)
Whole-program passes are run with
apply_pass()(orapply_passes()) and operate on the SDFG globally. Common examples includeScalarToSymbolPromotionandTransientReuse.
In all three cases the SDFG is mutated in place, so chaining operations is just calling them in sequence. To revert an experiment, reload from the saved baseline.
Instrumentation feedback loop
Interactive optimization works best when paired with
runtime instrumentation. Set
instrument (or
instrument) on the regions of interest, run
the program once, and inspect
InstrumentationReport to
confirm whether the last transformation actually moved the needle. The
recommended workflow is:
Identify the hottest map or library node from a profile.
Apply a transformation (or a small sequence) targeting it.
Re-run; compare the new instrumentation report against the previous one.
If the change helped, save the SDFG; otherwise reload and try a different sequence.
Composing with the auto-optimizer
The automatic heuristics (dace.transformation.auto.auto_optimize)
are a useful starting point even when the goal is a fully manual schedule.
A common pattern is to call auto_optimize once to establish a strong
baseline, save the result, and then drive the remaining optimizations by
hand with the API described above.
For more involved manipulations, such as scripting transformation searches,
see SDFG Builder API and the samples/optimization directory in the
repository.