Skip to content

Commit

Permalink
Strict Transformations -> Dataflow Coarsening
Browse files Browse the repository at this point in the history
  • Loading branch information
tbennun committed Dec 31, 2021
1 parent e71a02d commit 132c57e
Show file tree
Hide file tree
Showing 85 changed files with 369 additions and 332 deletions.
16 changes: 8 additions & 8 deletions .github/workflows/general-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
python-version: [3.7,'3.10']
strict-xforms: [0,1,autoopt]
coarsening: [0,1,autoopt]

steps:
- uses: actions/checkout@v2
Expand Down Expand Up @@ -43,12 +43,12 @@ jobs:
export DACE_testing_serialization=1
export DACE_cache=unique
export DACE_optimizer_interface=" "
if [ "${{ matrix.strict-xforms }}" = "autoopt" ]; then
export DACE_optimizer_automatic_strict_transformations=1
if [ "${{ matrix.coarsening }}" = "autoopt" ]; then
export DACE_optimizer_automatic_dataflow_coarsening=1
export DACE_optimizer_autooptimize=1
echo "Auto-optimization heuristics"
else
export DACE_optimizer_automatic_strict_transformations=${{ matrix.strict-xforms }}
export DACE_optimizer_automatic_dataflow_coarsening=${{ matrix.coarsening }}
fi
pytest -n auto --cov-report=xml --cov=dace --tb=short -m "not gpu and not verilator and not tensorflow and not mkl and not sve and not papi and not mlir and not lapack and not fpga and not mpi"
codecov
Expand All @@ -59,12 +59,12 @@ jobs:
export DACE_testing_serialization=1
export DACE_cache=unique
export DACE_optimizer_interface=" "
if [ "${{ matrix.strict-xforms }}" = "autoopt" ]; then
export DACE_optimizer_automatic_strict_transformations=1
if [ "${{ matrix.coarsening }}" = "autoopt" ]; then
export DACE_optimizer_automatic_dataflow_coarsening=1
export DACE_optimizer_autooptimize=1
echo "Auto-optimization heuristics"
else
export DACE_optimizer_automatic_strict_transformations=${{ matrix.strict-xforms }}
export DACE_optimizer_automatic_dataflow_coarsening=${{ matrix.coarsening }}
fi
pytest -n 1 --cov-report=xml --cov=dace --tb=short -m "lapack"
codecov
Expand All @@ -74,7 +74,7 @@ jobs:
export NOSTATUSBAR=1
export DACE_testing_serialization=1
export DACE_cache=single
export DACE_optimizer_automatic_strict_transformations=${{ matrix.strict-xforms }}
export DACE_optimizer_automatic_dataflow_coarsening=${{ matrix.coarsening }}
export PYTHON_BINARY="coverage run --source=dace --parallel-mode"
./tests/polybench_test.sh
./tests/xform_test.sh
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ FPGA programming:
SDFG interactive transformation:
* `DACE_optimizer_transform_on_call` (default: False): Uses the transformation command line interface every time a `@dace` function is called.
* `DACE_optimizer_interface` (default: `dace.transformation.optimizer.SDFGOptimizer`): Controls the SDFG optimization process if `transform_on_call` is enabled. By default, uses the transformation command line interface.
* `DACE_optimizer_automatic_strict_transformations` (default: True): If False, skips automatic strict transformations in the Python frontend (see transformations tutorial for more information).
* `DACE_optimizer_automatic_dataflow_coarsening` (default: True): If False, skips automatic dataflow coarsening in the Python frontend (see transformations tutorial for more information).

Profiling:
* `DACE_profiling` (default: False): Enables profiling measurement of the DaCe program runtime in milliseconds. Produces a log file and prints out median runtime.
Expand Down
7 changes: 3 additions & 4 deletions dace/config_schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,12 @@ required:
title: Save intermediate SDFGs
description: Save SDFG files after every transformation.

automatic_strict_transformations:
automatic_dataflow_coarsening:
type: bool
default: true
title: Automatic strict transformations
title: Automatic dataflow coarsening
description: >
Automatically performs strict transformations
that are considered to be safe.
Automatically performs dataflow coarsening on programs.
detect_control_flow:
type: bool
Expand Down
6 changes: 3 additions & 3 deletions dace/frontend/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ There is also upcoming support for NumPy ufuncs. You may preview ufunc support w

## Known Issues

### Issues when automatic strict transformations are enabled
### Issues when automatic dataflow coarsening is enabled

When automatic strict transformations are enabled, SDFGs created using the
When automatic dataflow coarsening is enabled, SDFGs created using the
Python-Frontend are automatically transformed using:
- InlineSDFG
- EndStateElimination
Expand All @@ -67,4 +67,4 @@ ranges, leading to RW/WR/WW dependencies, InlineSDFG and StateFusion may violate
- When there are sequential dependencies between statements due to updating a loop variable,
StateFusion may erroneously lead to concurrent execution of those statements (see [#315](https://github.com/spcl/dace/issues/315)).

Temporary workaround: Disable the automatic strict transformations flag in the configuration file `.dace.conf`.
Temporary workaround: Disable the automatic dataflow coarsening flag in the configuration file `.dace.conf`.
14 changes: 7 additions & 7 deletions dace/frontend/python/newast.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,14 @@ def parse_dace_program(name: str,
argtypes: Dict[str, data.Data],
constants: Dict[str, Any],
closure: SDFGClosure,
strict: Optional[bool] = None,
coarsen: Optional[bool] = None,
save=True) -> SDFG:
""" Parses a `@dace.program` function into an SDFG.
:param src_ast: The AST of the Python program to parse.
:param visitor: A ProgramVisitor object returned from
``preprocess_dace_program``.
:param closure: An object that contains the @dace.program closure.
:param strict: If True, strict transformations will be performed.
:param coarsen: If True, dataflow coarsening will be performed.
:param save: If True, saves source mapping data for this SDFG.
:return: A 2-tuple of SDFG and its reduced (used) closure.
"""
Expand All @@ -164,7 +164,7 @@ def parse_dace_program(name: str,
scope_arrays=argtypes,
scope_vars={},
closure=closure,
strict=strict)
coarsen=coarsen)

sdfg, _, _, _ = visitor.parse_program(
preprocessed_ast.preprocessed_ast.body[0])
Expand Down Expand Up @@ -1065,7 +1065,7 @@ def __init__(self,
closure: SDFGClosure = None,
nested: bool = False,
tmp_idx: int = 0,
strict: Optional[bool] = None):
coarsen: Optional[bool] = None):
""" ProgramVisitor init method
Arguments:
Expand All @@ -1078,7 +1078,7 @@ def __init__(self,
scope_arrays {Dict[str, data.Data]} -- Scope arrays
scope_vars {Dict[str, str]} -- Scope variables
closure {SDFGClosure} -- The closure of this program
strict {bool} -- Whether to apply strict transforms after parsing nested dace programs
coarsen {bool} -- Whether to apply dataflow coarsening after parsing nested dace programs
Keyword Arguments:
nested {bool} -- True, if SDFG is nested (default: {False})
Expand All @@ -1099,7 +1099,7 @@ def __init__(self,
self.globals = global_vars
self.closure = closure
self.nested = nested
self.strict = strict
self.coarsen = coarsen

# Keeps track of scope arrays, numbers, variables and accesses
self.scope_arrays = OrderedDict()
Expand Down Expand Up @@ -3689,7 +3689,7 @@ def _parse_sdfg_call(self, funcname: str,
fcopy.signature = copy.deepcopy(func.signature)
sdfg = fcopy.to_sdfg(*fargs,
**fkwargs,
strict=self.strict,
coarsen=self.coarsen,
save=False)
else:
sdfg = fcopy.__sdfg__(*fargs, **fkwargs)
Expand Down
31 changes: 15 additions & 16 deletions dace/frontend/python/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def _auto_optimize(self,

def to_sdfg(self,
*args,
strict=None,
coarsen=None,
save=False,
validate=False,
use_cache=False,
Expand Down Expand Up @@ -234,7 +234,7 @@ def to_sdfg(self,

sdfg = self._parse(args,
kwargs,
strict=strict,
coarsen=coarsen,
save=save,
validate=validate)

Expand All @@ -244,17 +244,16 @@ def to_sdfg(self,

return sdfg


def __sdfg__(self, *args, **kwargs) -> SDFG:
return self._parse(args,
kwargs,
strict=None,
coarsen=None,
save=False,
validate=False)

def compile(self, *args, strict=None, save=False, **kwargs):
def compile(self, *args, coarsen=None, save=False, **kwargs):
""" Convenience function that parses and compiles a DaCe program. """
sdfg = self._parse(args, kwargs, strict=strict, save=save)
sdfg = self._parse(args, kwargs, coarsen=coarsen, save=save)

# Invoke auto-optimization as necessary
if Config.get_bool('optimizer', 'autooptimize') or self.auto_optimize:
Expand Down Expand Up @@ -457,7 +456,7 @@ def __call__(self, *args, **kwargs):
def _parse(self,
args,
kwargs,
strict=None,
coarsen=None,
save=False,
validate=False) -> SDFG:
"""
Expand All @@ -467,7 +466,7 @@ def _parse(self,
decorator).
:param args: The given arguments to the function.
:param kwargs: The given keyword arguments to the function.
:param strict: Whether to apply strict transformations or not (None
:param coarsen: Whether to apply dataflow coarsening or not (None
uses configuration-defined value).
:param save: If True, saves the generated SDFG to
``_dacegraphs/program.sdfg`` after parsing.
Expand All @@ -479,20 +478,20 @@ def _parse(self,
from dace.transformation import helpers as xfh

# Obtain DaCe program as SDFG
sdfg, cached = self._generate_pdp(args, kwargs, strict=strict)
sdfg, cached = self._generate_pdp(args, kwargs, coarsen=coarsen)

# Apply strict transformations automatically
# Apply dataflow coarsening automatically
if not cached and (
strict == True or (strict is None and Config.get_bool(
'optimizer', 'automatic_strict_transformations'))):
coarsen == True or (coarsen is None and Config.get_bool(
'optimizer', 'automatic_dataflow_coarsening'))):

# Promote scalars to symbols as necessary
promoted = scal2sym.promote_scalars_to_symbols(sdfg)
if Config.get_bool('debugprint') and len(promoted) > 0:
print('Promoted scalars {%s} to symbols.' %
', '.join(p for p in sorted(promoted)))

sdfg.apply_strict_transformations()
sdfg.coarsen_dataflow()

# Split back edges with assignments and conditions to allow richer
# control flow detection in code generation
Expand Down Expand Up @@ -728,11 +727,11 @@ def load_precompiled_sdfg(self, path: str, *args, **kwargs) -> None:
# Update SDFG cache with the SDFG and compiled version
self._cache.add(cachekey, csdfg.sdfg, csdfg)

def _generate_pdp(self, args, kwargs, strict=None) -> SDFG:
def _generate_pdp(self, args, kwargs, coarsen=None) -> SDFG:
""" Generates the parsed AST representation of a DaCe program.
:param args: The given arguments to the program.
:param kwargs: The given keyword arguments to the program.
:param strict: Whether to apply strict transforms when parsing
:param coarsen: Whether to apply dataflow coarsening when parsing
nested dace programs.
:return: A 2-tuple of (parsed SDFG object, was the SDFG retrieved
from cache).
Expand Down Expand Up @@ -820,7 +819,7 @@ def _generate_pdp(self, args, kwargs, strict=None) -> SDFG:
argtypes,
self.dec_kwargs,
closure,
strict=strict)
coarsen=coarsen)

# Set SDFG argument names, filtering out constants
sdfg.arg_names = [a for a in self.argnames if a in argtypes]
Expand Down
2 changes: 1 addition & 1 deletion dace/frontend/python/preprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@ def preprocess_dace_program(
:param modules: A dictionary from an imported module name to the
module itself.
:param constants: A dictionary from a name to a constant value.
:param strict: Whether to apply strict transformations after parsing nested dace programs.
:param strict: Whether to apply dataflow coarsening after parsing nested dace programs.
:param resolve_functions: If True, treats all global functions defined
outside of the program as returning constant
values.
Expand Down
2 changes: 1 addition & 1 deletion dace/frontend/tensorflow/tensorflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ def train(

print("Adding connectors")
self.graph.fill_scope_connectors()
# self.graph.apply_strict_transformations(validate=False)
# self.graph.coarsen_dataflow(validate=False)
if gpu:
self.graph.apply_gpu_transformations()

Expand Down
2 changes: 1 addition & 1 deletion dace/libraries/blas/nodes/gemv.py
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ def _gemTv_pblas(_A: dtype[m, n], _x: dtype[m], _y: dtype[n]):
sdfg = _gemTv_pblas.to_sdfg(strict=False)
else:
sdfg = _gemNv_pblas.to_sdfg(strict=False)
sdfg.apply_strict_transformations()
sdfg.coarsen_dataflow()
return sdfg


Expand Down
28 changes: 21 additions & 7 deletions dace/sdfg/sdfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@
from dace.sdfg.state import SDFGState
from dace.sdfg.propagation import propagate_memlets_sdfg
from dace.dtypes import validate_name
from dace.properties import (DebugInfoProperty, EnumProperty, ListProperty, make_properties,
Property, CodeProperty, TransformationHistProperty,
SDFGReferenceProperty, DictProperty,
OrderedDictProperty, CodeBlock)
from dace.properties import (DebugInfoProperty, EnumProperty, ListProperty,
make_properties, Property, CodeProperty,
TransformationHistProperty, SDFGReferenceProperty,
DictProperty, OrderedDictProperty, CodeBlock)


def _arrays_to_json(arrays):
Expand Down Expand Up @@ -2016,6 +2016,20 @@ def is_valid(self) -> bool:
return True

def apply_strict_transformations(self, validate=True, validate_all=False):
"""
This method is DEPRECATED in favor of ``coarsen_dataflow``.
Applies safe transformations (that will surely increase the
performance) on the SDFG. For example, this fuses redundant states
(safely) and removes redundant arrays.
B{Note:} This is an in-place operation on the SDFG.
"""
warnings.warn(
'SDFG.apply_strict_transformations is deprecated, use SDFG.coarsen_dataflow instead.',
DeprecationWarning)
return self.coarsen_dataflow(validate, validate_all)

def coarsen_dataflow(self, validate=True, validate_all=False):
""" Applies safe transformations (that will surely increase the
performance) on the SDFG. For example, this fuses redundant states
(safely) and removes redundant arrays.
Expand All @@ -2028,14 +2042,14 @@ def apply_strict_transformations(self, validate=True, validate_all=False):
RedundantWriteSlice)
# This is imported here to avoid an import loop
from dace.transformation.transformation import (Transformation,
strict_transformations)
coarsening_transformations)

self.apply_transformations_repeated(
[RedundantReadSlice, RedundantWriteSlice],
validate=validate,
strict=True,
validate_all=validate_all)
self.apply_transformations_repeated(strict_transformations(),
self.apply_transformations_repeated(coarsening_transformations(),
validate=validate,
strict=True,
validate_all=validate_all)
Expand Down Expand Up @@ -2255,7 +2269,7 @@ def apply_gpu_transformations(self,
generate GPU code.
:note: It is recommended to apply redundant array removal
transformation after this transformation. Alternatively,
you can apply_strict_transformations() after this transformation.
you can coarsen_dataflow() after this transformation.
:note: This is an in-place operation on the SDFG.
"""
# Avoiding import loops
Expand Down
2 changes: 1 addition & 1 deletion dace/transformation/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .transformation import strict_transformations, Transformation, ExpandTransformation
from .transformation import coarsening_transformations, Transformation, ExpandTransformation
Loading

0 comments on commit 132c57e

Please sign in to comment.