dace.transformation package

Subpackages

Submodules

Passes and Pipelines

API for SDFG analysis and manipulation Passes, as well as Pipelines that contain multiple dependent passes.

class dace.transformation.pass_pipeline.FixedPointPipeline(passes: List[dace.transformation.pass_pipeline.Pass])

Bases: dace.transformation.pass_pipeline.Pipeline

A special type of Pipeline that applies its ``Pass``es in repeated succession until they all stop modifying the SDFG (i.e., by returning None).

See:Pipeline
apply_pass(sdfg: dace.sdfg.sdfg.SDFG, pipeline_results: Dict[str, Any]) → Optional[Dict[str, Any]]

Applies the pipeline to the SDFG in repeated succession until the SDFG is no longer modified. :param sdfg: The SDFG to apply the pass to. :param pipeline_results: If in the context of a Pipeline, a dictionary that is populated with prior Pass

results as {Pass subclass name: returned object from pass}. If not run in a pipeline, an empty dictionary is expected.
Returns:A dictionary of {Pass subclass name: return value} for applied passes, or None if no Passes were applied in the context of this pipeline.
class dace.transformation.pass_pipeline.Modifies

Bases: enum.Flag

Specifies which elements of an SDFG have been modified by a Pass/Transformation. This is used when deciding whether to rerun certain Passes for SDFG analysis. Note that this is a Python Flag, which means values such as Memlets | Symbols are allowed.

AccessNodes = 16

Access nodes’ existence or properties were modified

Descriptors = 1

Data descriptors (e.g., arrays, streams) and their properties were modified

Edges = 264

Any edge (memlet or inter-state) was modified

Everything = 511

Modification to arbitrary parts of SDFGs (nodes, edges, or properties)

InterstateEdges = 8

Contents (conditions/assignments) or existence of inter-state edges were modified

Memlets = 256

Memlets’ existence, contents, or properties were modified

NestedSDFGs = 128

SDFG nesting structure or properties of NestedSDFG nodes were modified

Nodes = 240

Modification of any dataflow node (contained in an SDFG state) was made

Nothing = 0

Nothing was modified

Scopes = 32

Scopes (e.g., Map, Consume, Pipeline) or associated properties were created/removed/modified

States = 4

The number of SDFG states and their connectivity (not their contents) were modified

Symbols = 2

Symbols were modified

Tasklets = 64

Tasklets were created/removed or their contents were modified

class dace.transformation.pass_pipeline.Pass

Bases: object

An SDFG analysis or manipulation that registers as part of the SDFG history. Classes that extend Pass can be used for optimization purposes, to collect data on an entire SDFG, for cleanup, or other uses. Pattern-matching transformations, as well as the SDFG simplification process, extend Pass. Passes may depend on each other through a Pipeline object, which will ensure dependencies are met and that passes do not run redundantly.

A Pass is defined by one main method: apply_pass. This method receives the SDFG to manipulate/analyze, as well as the previous Pipeline results, if run in the context of a pipeline. The other three, pipeline-related methods are: * depends_on: Which other passes this pass requires * modifies: Which elements of the SDFG does this Pass modify (used to avoid re-applying when unnecessary) * should_reapply: Given the modified elements of the SDFG, should this pass be rerun?

Seealso:Pipeline
apply_pass(sdfg: dace.sdfg.sdfg.SDFG, pipeline_results: Dict[str, Any]) → Optional[Any]

Applies the pass to the given SDFG. :param sdfg: The SDFG to apply the pass to. :param pipeline_results: If in the context of a Pipeline, a dictionary that is populated with prior Pass

results as {Pass subclass name: returned object from pass}. If not run in a pipeline, an empty dictionary is expected.
Returns:Some object if pass was applied, or None if nothing changed.
depends_on() → Set[Union[Type[dace.transformation.pass_pipeline.Pass], dace.transformation.pass_pipeline.Pass]]

If in the context of a Pipeline, which other Passes need to run first. :return: A set of Pass subclasses or objects that need to run prior to this Pass.

modifies() → dace.transformation.pass_pipeline.Modifies

Which elements of the SDFG (e.g., memlets, state structure) are modified by this pass, if run successfully. :return: A Modifies set of flags of modified elements.

report(pass_retval: Any) → Optional[str]

Returns a user-readable string report based on the results of this pass. :param pass_retval: The return value from applying this pass. :return: A string with the user-readable report, or None if nothing to report.

should_reapply(modified: dace.transformation.pass_pipeline.Modifies) → bool

In the context of a Pipeline, queries whether this Pass should be rerun after other passes have run and modified the SDFG. :param modified: Flags specifying which elements of the SDFG were modified. :return: True if this Pass should be rerun when the given elements are modified.

class dace.transformation.pass_pipeline.Pipeline(passes: List[dace.transformation.pass_pipeline.Pass])

Bases: dace.transformation.pass_pipeline.Pass

A pass pipeline contains multiple, potentially dependent Pass objects, and applies them in order. Each contained pass may depend on other (e.g., analysis) passes, which the Pipeline avoids rerunning depending on which elements were modified by applied passes. An example of a built-in pipeline is the SimplifyPass, which runs multiple complexity reduction passes and may reuse data across them. Prior results of applied passes are contained in the pipeline_results argument to apply_pass, which can be used to access previous return values of Passes.

A Pipeline in itself is a type of a Pass, so it can be arbitrarily nested in another Pipelines. Its dependencies and modified elements are unions of the contained Pass objects.

Creating a Pipeline can be performed by instantiating the object with a list of Pass objects, or by extending the pipeline class (e.g., if pipeline order should be modified). The return value of applying a pipeline is a dictionary whose keys are the Pass subclass names and values are the return values of each pass. Example use:

my_simplify = Pipeline([ScalarToSymbolPromotion(integers_only=False), ConstantPropagation()])
results = my_simplify.apply_pass(sdfg, {})
print('Promoted scalars:', results['ScalarToSymbolPromotion'])
apply_pass(sdfg: dace.sdfg.sdfg.SDFG, pipeline_results: Dict[str, Any]) → Optional[Dict[str, Any]]

Applies the pass to the given SDFG. :param sdfg: The SDFG to apply the pass to. :param pipeline_results: If in the context of a Pipeline, a dictionary that is populated with prior Pass

results as {Pass subclass name: returned object from pass}. If not run in a pipeline, an empty dictionary is expected.
Returns:Some object if pass was applied, or None if nothing changed.
apply_subpass(sdfg: dace.sdfg.sdfg.SDFG, p: dace.transformation.pass_pipeline.Pass, state: Dict[str, Any]) → Optional[Any]

Apply a pass from the pipeline. This method is meant to be overridden by subclasses.

Parameters:
  • sdfg – The SDFG to apply the pass to.
  • p – The pass to apply.
  • state – The pipeline results state.
Returns:

The pass return value.

depends_on() → Set[Type[dace.transformation.pass_pipeline.Pass]]

If in the context of a Pipeline, which other Passes need to run first. :return: A set of Pass subclasses or objects that need to run prior to this Pass.

iterate_over_passes(sdfg: dace.sdfg.sdfg.SDFG) → Iterator[dace.transformation.pass_pipeline.Pass]

Iterates over passes in the pipeline, potentially multiple times based on which elements were modified in the pass. Note that this method may be overridden by subclasses to modify pass order.

Parameters:sdfg – The SDFG on which the pipeline is currently being applied
modifies() → dace.transformation.pass_pipeline.Modifies

Which elements of the SDFG (e.g., memlets, state structure) are modified by this pipeline, if run successfully. Computed as the union of all modified elements of each pass in the pipeline. :return: A Modifies set of flags of modified elements.

should_reapply(modified: dace.transformation.pass_pipeline.Modifies) → bool

In the context of a Pipeline, queries whether this Pass should be rerun after other passes have run and modified the SDFG. :param modified: Flags specifying which elements of the SDFG were modified. :return: True if this Pass should be rerun when the given elements are modified.

class dace.transformation.pass_pipeline.ScopePass

Bases: dace.transformation.pass_pipeline.Pass

A specialized Pass type that applies to each scope (e.g., Map, Consume, Pipeline) separately. Such a pass is realized by implementing the apply method, which accepts a scope entry node and its parent SDFG state.

See:Pass
apply(scope: dace.sdfg.nodes.EntryNode, state: dace.sdfg.state.SDFGState, pipeline_results: Dict[str, Any]) → Optional[Any]

Applies this pass on the given scope. :param scope: The entry node of the scope to apply the pass to. :param state: The parent SDFG state of the given scope. :param pipeline_results: If in the context of a Pipeline, a dictionary that is populated with prior Pass

results as {Pass subclass name: returned object from pass}. If not run in a pipeline, an empty dictionary is expected.
Returns:Some object if pass was applied, or None if nothing changed.
apply_pass(sdfg: dace.sdfg.sdfg.SDFG, pipeline_results: Dict[str, Any]) → Optional[Dict[dace.sdfg.nodes.EntryNode, Optional[Any]]]

Applies the pass to the scopes of the given SDFG by calling apply on each scope entry node. :param sdfg: The SDFG to apply the pass to. :param pipeline_results: If in the context of a Pipeline, a dictionary that is populated with prior Pass

results as {Pass subclass name: returned object from pass}. If not run in a pipeline, an empty dictionary is expected.
Returns:A dictionary of {entry node: return value} for visited scopes with a non-None return value, or None if nothing was returned.
class dace.transformation.pass_pipeline.StatePass

Bases: dace.transformation.pass_pipeline.Pass

A specialized Pass type that applies to each SDFG state separately. Such a pass is realized by implementing the apply method, which accepts a single state.

See:Pass
apply(state: dace.sdfg.state.SDFGState, pipeline_results: Dict[str, Any]) → Optional[Any]

Applies this pass on the given state. :param state: The SDFG state to apply the pass to. :param pipeline_results: If in the context of a Pipeline, a dictionary that is populated with prior Pass

results as {Pass subclass name: returned object from pass}. If not run in a pipeline, an empty dictionary is expected.
Returns:Some object if pass was applied, or None if nothing changed.
apply_pass(sdfg: dace.sdfg.sdfg.SDFG, pipeline_results: Dict[str, Any]) → Optional[Dict[dace.sdfg.state.SDFGState, Optional[Any]]]

Applies the pass to states of the given SDFG by calling apply on each state. :param sdfg: The SDFG to apply the pass to. :param pipeline_results: If in the context of a Pipeline, a dictionary that is populated with prior Pass

results as {Pass subclass name: returned object from pass}. If not run in a pipeline, an empty dictionary is expected.
Returns:A dictionary of {state: return value} for visited states with a non-None return value, or None if nothing was returned.
class dace.transformation.pass_pipeline.VisitorPass

Bases: dace.transformation.pass_pipeline.Pass

A simple type of Pass that provides a Python visitor object on an SDFG. Used for either analyzing an SDFG or modifying properties of existing elements (rather than their graph structure). Applying a visitor pass on an SDFG would call visit_<ElementType> methods on the SDFG elements with the element, its parent, and previous pipeline results, if in the context of a Pipeline.

For example:

class HasWriteConflicts(VisitorPass):
    def __init__(self):
        self.found_wcr = False

    def visit_Memlet(self, memlet: dace.Memlet, parent: dace.SDFGState, pipeline_results: Dict[str, Any]):
        if memlet.wcr:
            self.found_wcr = True

            # If a value is returned, a dictionary key will be filled with the visited object and the value
            return memlet.wcr

wcr_checker = HasWriteConflicts()
memlets_with_wcr = wcr_checker.apply_pass(sdfg, {})
print('SDFG has write-conflicted memlets:', wcr_checker.found_wcr)
print('Memlets:', memlets_with_wcr)
apply_pass(sdfg: dace.sdfg.sdfg.SDFG, pipeline_results: Dict[str, Any]) → Optional[Dict[Any, Any]]

Visits the given SDFG recursively, calling defined visit_* methods for each element. :param sdfg: The SDFG to recursively visit. :param pipeline_results: If in the context of a Pipeline, a dictionary that is populated with prior Pass

results as {Pass subclass name: returned object from pass}. If not run in a pipeline, an empty dictionary is expected.
Returns:A dictionary of {element: return value} for visited elements with a non-None return value, or None if nothing was returned.
generic_visit(element: Any, parent: Any, pipeline_results: Dict[str, Any]) → Any

A default method that is called for elements that do not have a special visitor. :param element: The element to visit. :param parent: The parent of the visited element (e.g., SDFGState for dataflow elements, SDFG for SDFGStates). :param pipeline_results: If in the context of a Pipeline, a dictionary that is populated with prior Pass

results as {Pass subclass name: returned object from pass}. If not run in a pipeline, an empty dictionary is expected.

Transformations

This file contains classes that describe data-centric transformations.

All transformations extend the TransformationBase class. There are three built-in types of transformations in DaCe:
  • Pattern-matching Transformations (extending PatternTransformation): Transformations that require a certain subgraph structure to match. Within this abstract class, there are two sub-classes: * SingleStateTransformation: Patterns are limited to a single SDFG state. * MultiStateTransformation: Patterns are given on a subgraph of an SDFG state machine. A pattern-matching must extend at least one of those two classes.
  • Subgraph Transformations (extending SubgraphTransformation): Transformations that can operate on arbitrary subgraphs.
  • Library node expansions (extending ExpandTransformation): An internal class used for tracking how library nodes are expanded.
class dace.transformation.transformation.ExpandTransformation(*args, **kwargs)

Bases: dace.transformation.transformation.PatternTransformation

Base class for transformations that simply expand a node into a subgraph, and thus needs only simple matching and replacement functionality. Subclasses only need to implement the method “expansion”.

This is an internal interface used to track the expansion of library nodes.

apply(state, sdfg, *args, **kwargs)

Applies this transformation instance on the matched pattern graph. :param sdfg: The SDFG to apply the transformation to. :return: A transformation-defined return value, which could be used

to pass analysis data out, or nothing.
can_be_applied(graph: dace.sdfg.graph.OrderedMultiDiConnectorGraph, expr_index: int, sdfg, permissive: bool = False)

Returns True if this transformation can be applied on the candidate matched subgraph. :param graph: SDFGState object if this transformation is

single-state, or SDFG object otherwise.
Parameters:
  • expr_index – The list index from PatternTransformation.expressions that was matched.
  • sdfg – If graph is an SDFGState, its parent SDFG. Otherwise should be equal to graph.
  • permissive – Whether transformation should run in permissive mode.
Returns:

True if the transformation can be applied.

static expansion(node: dace.sdfg.nodes.LibraryNode, parent_state: dace.sdfg.state.SDFGState, parent_sdfg: dace.sdfg.sdfg.SDFG, *args, **kwargs)
classmethod expressions()

Returns a list of Graph objects that will be matched in the subgraph isomorphism phase. Used as a pre-pass before calling can_be_applied. :see: PatternTransformation.can_be_applied

static from_json(json_obj: Dict[str, Any], context: Dict[str, Any] = None) → dace.transformation.transformation.ExpandTransformation
match_to_str(graph: dace.sdfg.graph.OrderedMultiDiConnectorGraph)

Returns a string representation of the pattern match on the candidate subgraph. Used when identifying matches in the console UI.

static postprocessing(sdfg, state, expansion)
properties()
to_json(parent=None) → Dict[str, Any]
class dace.transformation.transformation.MultiStateTransformation(*args, **kwargs)

Bases: dace.transformation.transformation.PatternTransformation, abc.ABC

Base class for pattern-matching transformations that find matches within an SDFG state machine. New transformations that extend this class must contain static PatternNode-annotated fields that represent the nodes in the pattern graph, and use them to implement at least three methods:

  • expressions: A method that returns a list of graph
    patterns (SDFG objects) that match this transformation.
  • can_be_applied: A method that, given a subgraph candidate,
    checks for additional conditions whether it can be transformed.
  • apply: A method that applies the transformation
    on the given SDFG.

For example: ``` class MyTransformation(MultiStateTransformation):

state_a = PatternNode(SDFGState) state_b = PatternNode(SDFGState)

@classmethod def expressions(cls):

return [node_path_graph(cls.state_a, cls.state_b)]

```

For more information and optimization opportunities, see the respective methods’ documentation.

Seealso:PatternNode
can_be_applied(graph: dace.sdfg.sdfg.SDFG, expr_index: int, sdfg: dace.sdfg.sdfg.SDFG, permissive: bool = False) → bool

Returns True if this transformation can be applied on the candidate matched subgraph. :param graph: SDFG object in which the match was found. :param candidate: A mapping between node IDs returned from

PatternTransformation.expressions and the nodes in graph.
Parameters:
  • expr_index – The list index from PatternTransformation.expressions that was matched.
  • sdfg – The SDFG in which the match was found (equal to graph).
  • permissive – Whether transformation should run in permissive mode.
Returns:

True if the transformation can be applied.

classmethod expressions() → List[dace.sdfg.graph.SubgraphView]

Returns a list of SDFG subgraphs that will be matched in the subgraph isomorphism phase. Used as a pre-pass before calling can_be_applied.

properties()
class dace.transformation.transformation.PatternNode(nodeclass: Type[T])

Bases: typing.Generic

Static field wrapper of a node or an SDFG state that designates it as part of a subgraph pattern. These objects are used in subclasses of PatternTransformation to represent the subgraph patterns.

Example use: ``` class MyTransformation(SingleStateTransformation):

some_map_node = PatternNode(nodes.MapEntry) array = PatternNode(nodes.AccessNode)

```

The two nodes can then be used in the transformation static methods (e.g., expressions, can_be_applied) to represent the nodes, and in the instance methods to point to the nodes in the parent SDFG.

class dace.transformation.transformation.PatternTransformation(*args, **kwargs)

Bases: dace.transformation.transformation.TransformationBase

Abstract class for pattern-matching transformations. Please extend either SingleStateTransformation or MultiStateTransformation.

See:SingleStateTransformation
See:MultiStateTransformation
Seealso:PatternNode
annotates_memlets() → bool

Indicates whether the transformation annotates the edges it creates or modifies with the appropriate memlets. This determines whether to apply memlet propagation after the transformation.

apply(graph: Union[dace.sdfg.sdfg.SDFG, dace.sdfg.state.SDFGState], sdfg: dace.sdfg.sdfg.SDFG) → Optional[Any]

Applies this transformation instance on the matched pattern graph. :param sdfg: The SDFG to apply the transformation to. :return: A transformation-defined return value, which could be used

to pass analysis data out, or nothing.
apply_pass(sdfg: dace.sdfg.sdfg.SDFG, pipeline_results: Dict[str, Any]) → Optional[Any]

Applies the pass to the given SDFG. :param sdfg: The SDFG to apply the pass to. :param pipeline_results: If in the context of a Pipeline, a dictionary that is populated with prior Pass

results as {Pass subclass name: returned object from pass}. If not run in a pipeline, an empty dictionary is expected.
Returns:Some object if pass was applied, or None if nothing changed.
apply_pattern(append: bool = True, annotate: bool = True) → Optional[Any]

Applies this transformation on the given SDFG, using the transformation instance to find the right SDFG object (based on SDFG ID), and applying memlet propagation as necessary. :param sdfg: The SDFG (or an SDFG in the same hierarchy) to apply the

transformation to.
Parameters:append – If True, appends the transformation to the SDFG transformation history.
Returns:A transformation-defined return value, which could be used to pass analysis data out, or nothing.
classmethod apply_to(sdfg: dace.sdfg.sdfg.SDFG, options: Optional[Dict[str, Any]] = None, expr_index: int = 0, verify: bool = True, annotate: bool = True, permissive: bool = False, save: bool = True, **where)

Applies this transformation to a given subgraph, defined by a set of nodes. Raises an error if arguments are invalid or transformation is not applicable.

The subgraph is defined by the where dictionary, where each key is taken from the PatternNode fields of the transformation. For example, applying MapCollapse on two maps can pe performed as follows:

` MapCollapse.apply_to(sdfg, outer_map_entry=map_a, inner_map_entry=map_b) `

Parameters:
  • sdfg – The SDFG to apply the transformation to.
  • options – A set of parameters to use for applying the transformation.
  • expr_index – The pattern expression index to try to match with.
  • verify – Check that can_be_applied returns True before applying.
  • annotate – Run memlet propagation after application if necessary.
  • permissive – Apply transformation in permissive mode.
  • save – Save transformation as part of the SDFG file. Set to False if composing transformations.
  • where – A dictionary of node names (from the transformation) to nodes in the SDFG or a single state.
can_be_applied(graph: Union[dace.sdfg.sdfg.SDFG, dace.sdfg.state.SDFGState], expr_index: int, sdfg: dace.sdfg.sdfg.SDFG, permissive: bool = False) → bool

Returns True if this transformation can be applied on the candidate matched subgraph. :param graph: SDFGState object if this transformation is

single-state, or SDFG object otherwise.
Parameters:
  • expr_index – The list index from PatternTransformation.expressions that was matched.
  • sdfg – If graph is an SDFGState, its parent SDFG. Otherwise should be equal to graph.
  • permissive – Whether transformation should run in permissive mode.
Returns:

True if the transformation can be applied.

expr_index

Object property of type int

classmethod expressions() → List[dace.sdfg.graph.SubgraphView]

Returns a list of Graph objects that will be matched in the subgraph isomorphism phase. Used as a pre-pass before calling can_be_applied. :see: PatternTransformation.can_be_applied

static from_json(json_obj: Dict[str, Any], context: Dict[str, Any] = None) → dace.transformation.transformation.PatternTransformation
match_to_str(graph: Union[dace.sdfg.sdfg.SDFG, dace.sdfg.state.SDFGState]) → str

Returns a string representation of the pattern match on the candidate subgraph. Used when identifying matches in the console UI.

print_match(sdfg: dace.sdfg.sdfg.SDFG) → str

Returns a string representation of the pattern match on the given SDFG. Used for printing matches in the console UI.

properties()
sdfg_id

Object property of type int

setup_match(sdfg: dace.sdfg.sdfg.SDFG, sdfg_id: int, state_id: int, subgraph: Dict[PatternNode, int], expr_index: int, override: bool = False, options: Optional[Dict[str, Any]] = None) → None

Sets the transformation to a given subgraph pattern.

Parameters:
  • sdfg_id – A unique ID of the SDFG.
  • state_id – The node ID of the SDFG state, if applicable. If transformation does not operate on a single state, the value should be -1.
  • subgraph – A mapping between node IDs returned from PatternTransformation.expressions and the nodes in graph.
  • expr_index – The list index from PatternTransformation.expressions that was matched.
  • override – If True, accepts the subgraph dictionary as-is (mostly for internal use).
  • options – An optional dictionary of transformation properties
Raises:
  • TypeError – When transformation is not subclass of PatternTransformation.
  • TypeError – When state_id is not instance of int.
  • TypeError – When subgraph is not a dict of {PatternNode: int}.
state_id

Object property of type int

classmethod subclasses_recursive(all_subclasses: bool = False) → Set[Type[dace.transformation.transformation.PatternTransformation]]

Returns all subclasses of this class, including subclasses of subclasses. :param all_subclasses: Include all subclasses (e.g., including ExpandTransformation).

subgraph
to_json(parent=None) → Dict[str, Any]
class dace.transformation.transformation.SingleStateTransformation(*args, **kwargs)

Bases: dace.transformation.transformation.PatternTransformation, abc.ABC

Base class for pattern-matching transformations that find matches within a single SDFG state. New transformations that extend this class must contain static PatternNode fields that represent the nodes in the pattern graph, and use them to implement at least three methods:

  • expressions: A method that returns a list of graph
    patterns (SDFGState objects) that match this transformation.
  • can_be_applied: A method that, given a subgraph candidate,
    checks for additional conditions whether it can be transformed.
  • apply: A method that applies the transformation
    on the given SDFG.

For example: ``` class MyTransformation(SingleStateTransformation):

node_a = PatternNode(nodes.AccessNode) node_b = PatternNode(nodes.MapEntry)

@classmethod def expressions(cls):

return [node_path_graph(cls.node_a, cls.node_b)]

```

For more information and optimization opportunities, see the respective methods’ documentation.

Seealso:PatternNode
can_be_applied(graph: dace.sdfg.state.SDFGState, expr_index: int, sdfg: dace.sdfg.sdfg.SDFG, permissive: bool = False) → bool

Returns True if this transformation can be applied on the candidate matched subgraph. :param graph: SDFGState object in which the match was found. :param candidate: A mapping between node IDs returned from

PatternTransformation.expressions and the nodes in graph.
Parameters:
  • expr_index – The list index from PatternTransformation.expressions that was matched.
  • sdfg – The parent SDFG of the matched state.
  • permissive – Whether transformation should run in permissive mode.
Returns:

True if the transformation can be applied.

classmethod expressions() → List[dace.sdfg.state.StateSubgraphView]

Returns a list of SDFG state subgraphs that will be matched in the subgraph isomorphism phase. Used as a pre-pass before calling can_be_applied.

properties()
class dace.transformation.transformation.SubgraphTransformation(*args, **kwargs)

Bases: dace.transformation.transformation.TransformationBase

Base class for transformations that apply on arbitrary subgraphs, rather than matching a specific pattern.

Subclasses need to implement the can_be_applied and apply operations, as well as registered with the subclass registry. See the PatternTransformation class docstring for more information.

apply(sdfg: dace.sdfg.sdfg.SDFG)

Applies the transformation on the given subgraph. :param sdfg: The SDFG that includes the subgraph.

apply_pass(sdfg: dace.sdfg.sdfg.SDFG, pipeline_results: Dict[str, Any]) → Optional[Any]

Applies the pass to the given SDFG. :param sdfg: The SDFG to apply the pass to. :param pipeline_results: If in the context of a Pipeline, a dictionary that is populated with prior Pass

results as {Pass subclass name: returned object from pass}. If not run in a pipeline, an empty dictionary is expected.
Returns:Some object if pass was applied, or None if nothing changed.
classmethod apply_to(sdfg: dace.sdfg.sdfg.SDFG, *where, verify: bool = True, **options)

Applies this transformation to a given subgraph, defined by a set of nodes. Raises an error if arguments are invalid or transformation is not applicable.

To apply the transformation on a specific subgraph, the where parameter can be used either on a subgraph object (SubgraphView), or on directly on a list of subgraph nodes, given as Node or SDFGState objects. Transformation properties can then be given as keyword arguments. For example, applying SubgraphFusion on a subgraph of three nodes can be called in one of two ways: ``` # Subgraph SubgraphFusion.apply_to(

sdfg, SubgraphView(state, [node_a, node_b, node_c]))

# Simplified API: list of nodes SubgraphFusion.apply_to(sdfg, node_a, node_b, node_c) ```

Parameters:
  • sdfg – The SDFG to apply the transformation to.
  • where – A set of nodes in the SDFG/state, or a subgraph thereof.
  • verify – Check that can_be_applied returns True before applying.
  • options – A set of parameters to use for applying the transformation.
can_be_applied(sdfg: dace.sdfg.sdfg.SDFG, subgraph: dace.sdfg.graph.SubgraphView) → bool

Tries to match the transformation on a given subgraph, returning True if this transformation can be applied. :param sdfg: The SDFG that includes the subgraph. :param subgraph: The SDFG or state subgraph to try to apply the

transformation on.
Returns:True if the subgraph can be transformed, or False otherwise.
static from_json(json_obj: Dict[str, Any], context: Dict[str, Any] = None) → dace.transformation.transformation.SubgraphTransformation
get_subgraph(sdfg: dace.sdfg.sdfg.SDFG) → dace.sdfg.graph.SubgraphView
properties()
sdfg_id

ID of SDFG to transform

setup_match(subgraph: Union[Set[int], dace.sdfg.graph.SubgraphView], sdfg_id: int = None, state_id: int = None)

Sets the transformation to a given subgraph.

Parameters:
  • subgraph – A set of node (or state) IDs or a subgraph view object.
  • sdfg_id – A unique ID of the SDFG.
  • state_id – The node ID of the SDFG state, if applicable. If transformation does not operate on a single state, the value should be -1.
state_id

ID of state to transform subgraph within, or -1 to transform the SDFG

classmethod subclasses_recursive() → Set[Type[dace.transformation.transformation.PatternTransformation]]

Returns all subclasses of this class, including subclasses of subclasses. :param all_subclasses: Include all subclasses (e.g., including ExpandTransformation).

subgraph

Subgraph in transformation instance

subgraph_view(sdfg: dace.sdfg.sdfg.SDFG) → dace.sdfg.graph.SubgraphView
to_json(parent=None)
class dace.transformation.transformation.TransformationBase

Bases: dace.transformation.pass_pipeline.Pass

Base class for graph rewriting transformations. An instance of a TransformationBase object represents a match of the transformation (i.e., including a specific subgraph candidate to apply the transformation to), as well as properties of the transformation, which may affect if it can apply or not.

A Transformation can also be seen as a Pass that, when applied, operates on the given subgraph.

See:PatternTransformation
See:SubgraphTransformation
See:ExpandTransformation
modifies()

Which elements of the SDFG (e.g., memlets, state structure) are modified by this pass, if run successfully. :return: A Modifies set of flags of modified elements.

should_reapply(_: dace.transformation.pass_pipeline.Modifies) → bool

In the context of a Pipeline, queries whether this Pass should be rerun after other passes have run and modified the SDFG. :param modified: Flags specifying which elements of the SDFG were modified. :return: True if this Pass should be rerun when the given elements are modified.

dace.transformation.helpers module

Transformation helper API.

dace.transformation.helpers.are_subsets_contiguous(subset_a: dace.subsets.Subset, subset_b: dace.subsets.Subset, dim: int = None) → bool
dace.transformation.helpers.constant_symbols(sdfg: dace.sdfg.sdfg.SDFG) → Set[str]

Returns a set of symbols that will never change values throughout the course of the given SDFG. Specifically, these are the input symbols (i.e., not defined in a particular scope) that are never set by interstate edges. :param sdfg: The input SDFG. :return: A set of symbol names that remain constant throughout the SDFG.

dace.transformation.helpers.contained_in(state: dace.sdfg.state.SDFGState, node: dace.sdfg.nodes.Node, scope: dace.sdfg.nodes.EntryNode) → bool

Returns true if the specified node is contained within the scope opened by the given entry node (including through nested SDFGs).

dace.transformation.helpers.extract_map_dims(sdfg: dace.sdfg.sdfg.SDFG, map_entry: dace.sdfg.nodes.MapEntry, dims: List[int]) → Tuple[dace.sdfg.nodes.MapEntry, dace.sdfg.nodes.MapEntry]

Helper function that extracts specific map dimensions into an outer map. :param sdfg: The SDFG where the map resides. :param map_entry: Map entry node to extract. :param dims: A list of dimension indices to extract. :return: A 2-tuple containing the extracted map and the remainder map.

dace.transformation.helpers.find_contiguous_subsets(subset_list: List[dace.subsets.Subset], dim: int = None) → Set[dace.subsets.Subset]

Finds the set of largest contiguous subsets in a list of subsets. :param subsets: Iterable of subset objects. :param dim: Check for contiguity only for the specified dimension. :return: A list of contiguous subsets.

dace.transformation.helpers.find_sdfg_control_flow(sdfg: dace.sdfg.sdfg.SDFG) → Dict[dace.sdfg.state.SDFGState, Set[dace.sdfg.state.SDFGState]]

Partitions the SDFG to subgraphs that can be nested independently of each other. The method does not nest the subgraphs but alters the SDFG; (1) interstate edges are split, (2) scope source/sink states that belong to multiple scopes are duplicated (see _copy_state).

Parameters:sdfg – The SDFG to be partitioned.
Returns:The found subgraphs in the form of a dictionary where the keys are the start state of the subgraphs and the values are the sets of SDFGStates contained withing each subgraph.
dace.transformation.helpers.get_internal_scopes(state: dace.sdfg.state.SDFGState, entry: dace.sdfg.nodes.EntryNode, immediate: bool = False) → List[Tuple[dace.sdfg.state.SDFGState, dace.sdfg.nodes.EntryNode]]

Returns all internal scopes within a given scope, including if they reside in nested SDFGs. :param state: State in which entry node resides. :param entry: The entry node to start from. :param immediate: If True, only returns the scopes that are immediately

nested in the map.
dace.transformation.helpers.get_parent_map(state: dace.sdfg.state.SDFGState, node: Optional[dace.sdfg.nodes.Node] = None) → Optional[Tuple[dace.sdfg.nodes.EntryNode, dace.sdfg.state.SDFGState]]

Returns the map in which the state (and node) are contained in, or None if it is free. :param state: The state to test or parent of the node to test. :param node: The node to test (optional). :return: A tuple of (entry node, state) or None.

dace.transformation.helpers.gpu_map_has_explicit_threadblocks(state: dace.sdfg.state.SDFGState, entry: dace.sdfg.nodes.EntryNode) → bool

Returns True if GPU_Device map has explicit thread-block maps nested within.

dace.transformation.helpers.is_symbol_unused(sdfg: dace.sdfg.sdfg.SDFG, sym: str) → bool

Checks for uses of symbol in an SDFG, and if there are none returns False. :param sdfg: The SDFG to search. :param sym: The symbol to test. :return: True if the symbol can be removed, False otherwise.

dace.transformation.helpers.nest_sdfg_control_flow(sdfg: dace.sdfg.sdfg.SDFG, components=None)

Partitions the SDFG to subgraphs and nests them.

Parameters:
  • sdfg – The SDFG to be partitioned.
  • components – An existing partition of the SDFG.
dace.transformation.helpers.nest_sdfg_subgraph(sdfg: dace.sdfg.sdfg.SDFG, subgraph: dace.sdfg.graph.SubgraphView, start: Optional[dace.sdfg.state.SDFGState] = None) → dace.sdfg.state.SDFGState

Nests an SDFG subgraph (SDFGStates and InterstateEdges).

Parameters:
  • sdfg – The SDFG containing the subgraph.
  • subgraph – The SubgraphView description of the subgraph.
  • start – The start state of the subgraph.
Returns:

The SDFGState containing the NestedSDFG node (containing the nested SDFG subgraph).

dace.transformation.helpers.nest_state_subgraph(sdfg: dace.sdfg.sdfg.SDFG, state: dace.sdfg.state.SDFGState, subgraph: dace.sdfg.graph.SubgraphView, name: Optional[str] = None, full_data: bool = False) → dace.sdfg.nodes.NestedSDFG

Turns a state subgraph into a nested SDFG. Operates in-place. :param sdfg: The SDFG containing the state subgraph. :param state: The state containing the subgraph. :param subgraph: Subgraph to nest. :param name: An optional name for the nested SDFG. :param full_data: If True, nests entire input/output data. :return: The nested SDFG node. :raise KeyError: Some or all nodes in the subgraph are not located in

this state, or the state does not belong to the given SDFG.
Raises:ValueError – The subgraph is contained in more than one scope.
dace.transformation.helpers.offset_map(sdfg: dace.sdfg.sdfg.SDFG, state: dace.sdfg.state.SDFGState, entry: dace.sdfg.nodes.MapEntry, dim: int, offset: Union[sympy.core.basic.Basic, dace.symbolic.SymExpr], negative: bool = True)

Offsets a map parameter and its contents by a value. :param sdfg: The SDFG in which the map resides. :param state: The state in which the map resides. :param entry: The map entry node. :param dim: The map dimension to offset. :param offset: The value to offset by. :param negative: If True, offsets by -offset.

dace.transformation.helpers.permute_map(map_entry: dace.sdfg.nodes.MapEntry, perm: List[int])

Permutes indices of a map according to a given list of integers.

dace.transformation.helpers.reconnect_edge_through_map(state: dace.sdfg.state.SDFGState, edge: dace.sdfg.graph.MultiConnectorEdge[dace.memlet.Memlet][dace.memlet.Memlet], new_node: Union[dace.sdfg.nodes.EntryNode, dace.sdfg.nodes.ExitNode], keep_src: bool) → Tuple[dace.sdfg.graph.MultiConnectorEdge[dace.memlet.Memlet][dace.memlet.Memlet], dace.sdfg.graph.MultiConnectorEdge[dace.memlet.Memlet][dace.memlet.Memlet]]

Reconnects an edge through a map scope, removes old edge, and returns the two new edges. :param state: The state in which the edge and map reside. :param edge: The edge to reconnect and remove. :param new_node: The scope (map) entry or exit to reconnect through. :param keep_src: If True, keeps the source of the edge intact, otherwise

keeps destination of edge.
Returns:A 2-tuple of (incoming edge, outgoing edge).
dace.transformation.helpers.redirect_edge(state: dace.sdfg.state.SDFGState, edge: dace.sdfg.graph.MultiConnectorEdge[dace.memlet.Memlet][dace.memlet.Memlet], new_src: Optional[dace.sdfg.nodes.Node] = None, new_dst: Optional[dace.sdfg.nodes.Node] = None, new_src_conn: Optional[str] = None, new_dst_conn: Optional[str] = None, new_data: Optional[str] = None, new_memlet: Optional[dace.memlet.Memlet] = None) → dace.sdfg.graph.MultiConnectorEdge[dace.memlet.Memlet][dace.memlet.Memlet]

Redirects an edge in a state. Choose which elements to override by setting the keyword arguments. :param state: The SDFG state in which the edge resides. :param edge: The edge to redirect. :param new_src: If provided, redirects the source of the new edge. :param new_dst: If provided, redirects the destination of the new edge. :param new_src_conn: If provided, renames the source connector of the edge. :param new_dst_conn: If provided, renames the destination connector of the

edge.
Parameters:
  • new_data – If provided, changes the data on the memlet of the edge, and the entire associated memlet tree.
  • new_memlet – If provided, changes only the memlet of the new edge.
Returns:

The new, redirected edge.

Note:

new_data and new_memlet cannot be used at the same time.

dace.transformation.helpers.replicate_scope(sdfg: dace.sdfg.sdfg.SDFG, state: dace.sdfg.state.SDFGState, scope: dace.sdfg.scope.ScopeSubgraphView) → dace.sdfg.scope.ScopeSubgraphView

Replicates a scope subgraph view within a state, reconnecting all external edges to the same nodes. :param sdfg: The SDFG in which the subgraph scope resides. :param state: The SDFG state in which the subgraph scope resides. :param scope: The scope subgraph to replicate. :return: A reconnected replica of the scope.

dace.transformation.helpers.scope_tree_recursive(state: dace.sdfg.state.SDFGState, entry: Optional[dace.sdfg.nodes.EntryNode] = None) → dace.sdfg.scope.ScopeTree

Returns a scope tree that includes scopes from nested SDFGs. :param state: The state that contains the root of the scope tree. :param entry: A scope entry node to set as root, otherwise the state is

the root if None is given.
dace.transformation.helpers.simplify_state(state: dace.sdfg.state.SDFGState, remove_views: bool = False) → networkx.classes.multidigraph.MultiDiGraph

Returns a networkx MultiDiGraph object that contains all the access nodes and corresponding edges of an SDFG state. The removed code nodes and map scopes are replaced by edges that connect their ancestor and succesor access nodes. :param state: The input SDFG state. :return: The MultiDiGraph object.

dace.transformation.helpers.split_interstate_edges(sdfg: dace.sdfg.sdfg.SDFG) → None

Splits all inter-state edges into edges with conditions and edges with assignments. This procedure helps in nested loop detection. :param sdfg: The SDFG to split :note: Operates in-place on the SDFG.

dace.transformation.helpers.state_fission(sdfg: dace.sdfg.sdfg.SDFG, subgraph: dace.sdfg.graph.SubgraphView, label: Optional[str] = None) → dace.sdfg.state.SDFGState

Given a subgraph, adds a new SDFG state before the state that contains it, removes the subgraph from the original state, and connects the two states. :param subgraph: the subgraph to remove. :return: the newly created SDFG state.

dace.transformation.helpers.tile(sdfg: dace.sdfg.sdfg.SDFG, map_entry: dace.sdfg.nodes.MapEntry, divides_evenly: bool, skew: bool, **tile_sizes)

Helper function that tiles a Map scope by the given sizes, in the given order. :param sdfg: The SDFG where the map resides. :param map_entry: The map entry node to tile. :param divides_evenly: If True, skips pre/postamble for cases

where the map dimension is not a multiplier of the tile size.
Parameters:
  • skew – If True, skews the tiled map to start from zero. Helps compilers improve performance in certain cases.
  • tile_sizes – An ordered dictionary of the map parameter names to tile and their respective tile size (which can be symbolic expressions).
dace.transformation.helpers.unsqueeze_memlet(internal_memlet: dace.memlet.Memlet, external_memlet: dace.memlet.Memlet, preserve_minima: bool = False, use_src_subset: bool = False, use_dst_subset: bool = False) → dace.memlet.Memlet

Unsqueezes and offsets a memlet, as per the semantics of nested SDFGs. :param internal_memlet: The internal memlet (inside nested SDFG)

before modification.
Parameters:
  • external_memlet – The external memlet before modification.
  • preserve_minima – Do not change the subset’s minimum elements.
  • use_src_subset – If both sides of the memlet refer to same array, prefer source subset.
  • use_dst_subset – If both sides of the memlet refer to same array, prefer destination subset.
Returns:

Offset Memlet to set on the resulting graph.

dace.transformation.pattern_matching module

dace.transformation.optimizer module

Contains classes and functions related to optimization of the stateful dataflow graph representation.

class dace.transformation.optimizer.Optimizer(sdfg, inplace=True)

Bases: object

Implements methods for optimizing a DaCe program stateful dataflow graph representation, by matching patterns and applying transformations on it.

get_pattern_matches(permissive=False, states=None, patterns=None, sdfg=None, options=None) → Iterator[dace.transformation.transformation.PatternTransformation]

Returns all possible transformations for the current SDFG. :param permissive: Consider transformations in permissive mode. :param states: An iterable of SDFG states to consider when pattern

matching. If None, considers all.
Parameters:
  • patterns – An iterable of transformation classes to consider when matching. If None, considers all registered transformations in PatternTransformation.
  • sdfg – If not None, searches for patterns on given SDFG.
  • options – An optional iterable of transformation parameters.
Returns:

List of matching PatternTransformation objects.

See:

PatternTransformation.

optimization_space()

Returns the optimization space of the current SDFG

optimize()
set_transformation_metadata(patterns: List[Type[dace.transformation.transformation.PatternTransformation]], options: Optional[List[Dict[str, Any]]] = None)

Caches transformation metadata for a certain set of patterns to match.

class dace.transformation.optimizer.SDFGOptimizer(sdfg, inplace=True)

Bases: dace.transformation.optimizer.Optimizer

optimize()

A command-line UI for applying patterns on the SDFG. :return: An optimized SDFG object

dace.transformation.testing module

class dace.transformation.testing.TransformationTester(sdfg: dace.sdfg.sdfg.SDFG, depth=1, validate=True, generate_code=True, compile=False, print_exception=True, halt_on_exception=False)

Bases: dace.transformation.optimizer.Optimizer

An SDFG optimizer that consecutively applies available transformations up to a fixed depth.

optimize()

Module contents