feat[next-dace]: lowering to SchedTree - #2690
Conversation
6f99a07 to
057605c
Compare
057605c to
90d9ce6
Compare
There was a problem hiding this comment.
Pull request overview
This PR refactors the DaCe lowering pipeline for gt4py.next by renaming key lowering entry points and restructuring how builtin-function visitors are dispatched in both the fieldview and iterator lowering paths.
Changes:
- Renames/reshapes lowering entry points (e.g.,
build_sdfg_from_gtir→lower_program_to_sdfg) and adjusts imports/types accordingly. - Refactors builtin dispatch in
GTIRToSDFG(fieldview) andLambdaToDataflow(iterator) via centralized handler maps. - Updates scan/primitives/type helpers to use the split fieldview/iterator lowering modules.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/gt4py/next/program_processors/runners/dace/lowering/gtir_to_sdfg_types.py | Updates local-view helpers to return iterator-based IteratorExpr/MemletExpr types. |
| src/gt4py/next/program_processors/runners/dace/lowering/gtir_to_sdfg_scan.py | Switches scan lowering to the new fieldview/iterator module split and updated dataflow types. |
| src/gt4py/next/program_processors/runners/dace/lowering/gtir_to_sdfg_primitives.py | Retypes primitives to the split builders and iterator dataflow edges; small typing-related adjustments. |
| src/gt4py/next/program_processors/runners/dace/lowering/gtir_to_sdfg_iterator.py | Refactors builtin dispatch in lambda-to-dataflow and retargets builder typing to fieldview interfaces. |
| src/gt4py/next/program_processors/runners/dace/lowering/gtir_to_sdfg_fieldview.py | Refactors builtin dispatch in program lowering; introduces _visit_* helpers; renames program lowering entry point. |
| src/gt4py/next/program_processors/runners/dace/lowering/gtir_to_sdfg_concat_where.py | Updates concat_where lowering to use the fieldview lowering module split. |
| src/gt4py/next/program_processors/runners/dace/lowering/init.py | Updates lowering package exports to point at the refactored lowering entry points. |
Comments suppressed due to low confidence (3)
src/gt4py/next/program_processors/runners/dace/lowering/gtir_to_sdfg_iterator.py:58
gtir_to_sdfg_iterator.pyimportsgtir_to_sdfg_fieldviewusing thesrc.gt4py...package path, which will fail at runtime outside the repository checkout layout. Also, since this module usesfrom __future__ import annotations, this import is only needed for type checking and can be placed underTYPE_CHECKINGto avoid creating an import cycle (fieldview -> primitives -> iterator -> fieldview).
src/gt4py/next/program_processors/runners/dace/lowering/gtir_to_sdfg_iterator.py:18- The new
TYPE_CHECKING-guarded import forgtir_to_sdfg_fieldview(recommended below) requiresTYPE_CHECKINGto be imported fromtypingin this module.
src/gt4py/next/program_processors/runners/dace/lowering/init.py:23 lowering/__init__.pyre-exportsbuild_sdfg_from_gtirfromgtir_to_sdfg_fieldview, but that function was renamed tolower_program_to_sdfg(andbuild_sdfg_from_gtirno longer exists). This currently breaks imports likegtx_dace_lowering.build_sdfg_from_gtir(...)used elsewhere in the codebase.
from gt4py.next.program_processors.runners.dace.lowering.gtir_to_sdfg_fieldview import (
build_sdfg_from_gtir,
)
from gt4py.next.program_processors.runners.dace.lowering.gtir_to_sdfg_utils import (
flatten_tuple_fields,
get_map_variable,
)
__all__ = [
"build_sdfg_from_gtir",
"flatten_tuple_fields",
"get_map_variable",
]
4d8ca3b to
e92eade
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
src/gt4py/next/program_processors/runners/dace/lowering/gtir_to_sdfg_fieldview.py:1231
- This comment line has a stray "to." at the end (likely meant to be "symbols."), which makes the sentence ungrammatical.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/gt4py/next/program_processors/runners/dace/lowering/gtir_to_sdfg_iterator.py:52
gtir_to_sdfg_fieldviewis imported here only to satisfy type annotations, but this creates an avoidable import edge (and contributes to circular imports: fieldview -> primitives -> iterator -> fieldview). Since this module usesfrom __future__ import annotations, you can move the import behindtyping.TYPE_CHECKING(or otherwise defer it) to keep runtime imports acyclic.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…ifts Follow-up to 1e3f353, which made shift sources match on the non-staggered base dimension so that a dynamic `as_offset` declared on `KDim` can consume an index already replaced by `_StaggeredKDim`. Matching that loosely for *every* shift also dropped a backstop: a shift that changes the dimension — a half-shift, or an unstructured hop through a connectivity — moves between index spaces, and an ill-formed chain (e.g. two half-shifts on the same axis) would silently emit wrong indices instead of raising "Unable to compose shifts". Only an identity shift (`new_dim == old_dim`) is interchangeable between a base dimension and its staggered counterpart, which share an index space (ADR 0026); dimension-changing shifts must match their source exactly, and do so in well-typed IR. Fold both scans into `_find_shift_source`, which returns the consumed `indices` key, so the selection predicate is no longer duplicated and cannot drift. Assert that one axis has at most one entry in `indices` rather than letting `next()` pick by dict order. Also fix a typo in the error message ("consumers" -> "consumes"). No behaviour change on well-typed programs: test_staggered.py is green (143 passed, 78 skipped). Claude-Session: https://claude.ai/code/session_01VqXRdgfWnHkVAgpS2XciP2
|
cscs-ci run default |
|
cscs-ci run default |
|
cscs-ci run default |
1 similar comment
|
cscs-ci run default |
|
cscs-ci run default |
|
cscs-ci run default |
|
cscs-ci run default |
|
cscs-ci run default |
|
cscs-ci run default |
|
cscs-ci run default |
|
cscs-ci run default |
|
cscs-ci run default |
Summary
Adds a second GTIR→SDFG lowering path for the
gt4py.nextDaCe backend that goes throughDaCe's schedule tree (
ScheduleTreeRoot) instead of building the SDFG directly, andwires six new
run_dace_stree_*backends into the test matrix:run_dace_stree_fview_{cpu,gpu}[_noopt]— fieldview pipeline (as today)run_dace_stree_iview_{cpu,gpu}[_noopt]— with the ITIR common-transforms pipeline(
apply_common_transforms), which is now supported only on the stree loweringThis follows the direction set by the cartesian schedule-tree decision
(ADR: DaCe backends – schedule tree):
express the program's execution schedule at tree level and let
ScheduleTreeRoot.as_sdfg()produce the state machine, so that macro-level optimizations (loop merging, re-ordering)
can later operate on the tree instead of pattern-matching SDFGs.
Design
Direct GTIR → schedule-tree lowering (no intermediate TreeIR), in the new
runners/dace/lowering_stree/module (+5144 lines), alongside the existinglowering/:gtir_to_stree.py—GTIRToScheduleTreevisitor: statements, storage, let-lambdas,dispatch. All program storage is pre-allocated on
root.containers/root.symbols;let-lambdas are inlined into the same root (dict-union shadowing, call stack = implicit
push/pop) — no nested SDFGs produced by the lowering itself. (
as_sdfg()may stillintroduce them downstream; see
scan_carry_scalarization.py.)gtir_to_stree_codegen.py—StreePythonCodegen: each stencil body becomes one Pythoncode string inside a
TaskletNode. No library nodes — reductions are lowereddirectly to tasklet code.
ForScopeinside aMapScope. For scalar leaves the carry lives in ascalar transient that is pre-initialized with
initbefore the loop and read/writteneach iteration. List-typed leaves still read their carry from the result array at the
previous index and therefore keep a
carry if k > start else initternary to guard thefirst iteration. Backward scans are handled as well.
The legacy lowering is untouched by this PR and remains the default.
Test coverage
tests/next_tests/definitions.py, each mapped to a dedicatedDACE_STREE_SKIP_TEST_LISTinBACKEND_SKIP_TEST_MATRIX, so the full next test suiteruns against the stree backends in the
test_next (dace, *)nox sessions.Currently unsupported there (skipped):
USES_LIFT,USES_SCAN_IN_STENCIL,USES_SPARSE_FIELDS,USES_TUPLE_ITERATOR.pytest.mark.uses_dacemarker (GPU onesalso
requires_gpu), so the established nox matrix selection applies to them unchanged.Dependencies
This branch bundles the following transformation-layer fixes, which are still open as
standalone PRs: #2811, #2812, #2813, #2815, #2816, #2817, #2818. Each is a latent hazard
that the stree-lowered SDFGs — structured around regions and boundary states — trip and
that the legacy lowering never produced. They appear in this diff
(
transformations/{simplify,state_fusion,redundant_array_removers,utils}.pyandtest_distributed_buffer_relocator.py); once they merge individually, rebasing will dropthem from here.
The visitor-dispatch refactor this builds on, #2824, has already merged. Note that it
renamed
gtir_dataflow.py→gtir_to_sdfg_lambda.py;gtir_to_sdfg.pykept its name.