Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hierarchical Control Flow / Control Flow Regions #1404

Merged
merged 23 commits into from
Nov 2, 2023
Merged

Conversation

phschaad
Copy link
Collaborator

@phschaad phschaad commented Oct 18, 2023

This introduces hierarchical control flow to SDFGs in the form of control flow regions.

The number of new tests in this PR is currently limited since it only introduces the basic structure change and should hence be covered by existing tests. It is currently not yet possible to actually use or interact with hierarchical SDFGs in any manner besides using the SDFG creation API, since even validation is not yet capable of properly interpreting such an SDFG. This will be handled piece-wise in a number of subsequent PRs (see https://github.com/orgs/spcl/projects/10 for details and the roadmap).

In this PR:

  • Introduces control flow regions and turns the SDFG into one
  • Refactors SDFGStates to be a form of control flow block
  • Documentation for control flow regions
  • Basic test for is_start_state deprecation
  • Fix requirements.txt for Python 3.12
  • Remove a redundant setter function for setting the label of SDFGStates.

Note: this does not change anything about how you interact with SDFGs and provides complete backwards compatibility. No hierarchical control flow regions can currently be added, since there is no concrete implementation that extends them yet besides SDFGs themselves.

@phschaad phschaad added enhancement New feature or request core wip labels Oct 19, 2023
@phschaad phschaad changed the title Adds just the framework for integral loops Hierarchical Control Flow / Control Flow Regions Oct 20, 2023
@phschaad phschaad removed the wip label Oct 20, 2023
@phschaad phschaad marked this pull request as ready for review October 20, 2023 13:09
Copy link
Contributor

@alexnick83 alexnick83 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good in general. The changes are many, and we will need some time to get used to them and clean up issues that may arise. Since we recently had a new release that non-developers can use, I am in favor of merging to master ASAP to uncover problems that tests don't expose.

dace/sdfg/replace.py Show resolved Hide resolved
e.data.replace_dict(repl, replace_keys=False)

for block in cf.nodes():
if isinstance(block, dace.SDFGState):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the block is not an SDFGState, don't we also need to call replace on the block itself?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed @phschaad is there a need to replace inside a block? Does it have its own properties? Right now it's only is_collapsed and label, but I imagine loops would have other symbols in them.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general yes, it would need such a replacement as well. However, this is only replace_datadesc_names. There are currently no plans of having blocks (other than states) access data descriptors directly. They should all operate on symbols.

dace/sdfg/sdfg.py Show resolved Hide resolved
dace/sdfg/sdfg.py Outdated Show resolved Hide resolved
e.data.replace_dict(repl, replace_keys=False)

for block in cf.nodes():
if isinstance(block, dace.SDFGState):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed @phschaad is there a need to replace inside a block? Does it have its own properties? Right now it's only is_collapsed and label, but I imagine loops would have other symbols in them.

dace/sdfg/sdfg.py Outdated Show resolved Hide resolved
dace/sdfg/sdfg.py Show resolved Hide resolved
dace/sdfg/sdfg.py Outdated Show resolved Hide resolved
dace/sdfg/state.py Outdated Show resolved Hide resolved
dace/sdfg/state.py Show resolved Hide resolved
dace/sdfg/state.py Outdated Show resolved Hide resolved
dace/sdfg/state.py Show resolved Hide resolved
dace/sdfg/state.py Show resolved Hide resolved
dace/sdfg/state.py Show resolved Hide resolved
@phschaad phschaad requested a review from tbennun October 31, 2023 12:31
@phschaad phschaad enabled auto-merge (squash) November 2, 2023 09:35
@phschaad phschaad merged commit d947bf8 into master Nov 2, 2023
9 checks passed
@tbennun tbennun deleted the first_class_loops branch November 2, 2023 16:12
@phschaad phschaad mentioned this pull request Nov 3, 2023
4 tasks
phschaad added a commit that referenced this pull request Nov 27, 2023
This PR adds `LoopRegion`s to SDFGs. This forms the second core element
of the [plan to make loops first class citizens of
SDFGs](https://github.com/orgs/spcl/projects/10).
`LoopRegion`s are a special class of `ControlFlowRegion`s that represent
different types of loops, meaning the control flow region inside them is
executed a parametric number of times.
A `LoopRegion` _must_ have a conditional expression that determines
whether the region is executed or not. It may additionally have:
- an initialization expression that is run when the region is first
executed (even if the condition to execute its contents does not hold)
- an update expression, executed each time the execution of the region
contents is finished
- a flag indicating that it's inverted, meaning the contents are
executed once before the condition is checked (condition is checked
again after every execution)
- a set of control flow blocks in its contents that, when reached,
finish the execution of the region and do not execute it again even if
the condition still holds (equivalent to `break` in C/Python)
- a set of control flow blocks that end the execution of its contents
and execute the update statement if there is one. After this, the
condition is checked again and the contents may be run again (equivalent
to `continue` in C/Python)

For more general information on control flow regions please refer to
[the
documentation](https://spcldace.readthedocs.io/en/latest/sdfg/ir.html#elements)
or the [PR that introduced
them](#1404).

An example of a tripple loop nest of regular for loops can be seen in
the GEMM program below, showing that a proof-of-concept visualization
for the introduced concepts is already available in the latest release
version of the [VSCode
extension](https://marketplace.visualstudio.com/items?itemName=phschaad.sdfv)
(version 1.6.0 and upwards):


![image](https://github.com/spcl/dace/assets/9193712/9955e3f4-3356-4c52-b715-323330a0e4e4)

As outlined by the [project
plan](https://github.com/orgs/spcl/projects/10), these `LoopRegion`s are
currently _not_ being used by any frontend. They can, however, already
be manually used through the SDFG builder API. According to plan, most
passes and transformations are not currently able to handle the use of
such `LoopRegion`s yet, so their use is still highly experimental. To
allow traditional transformations and passes to work, as well as to be
able to generate codes for SDFGs containing `LoopRegion`s, a
compatibility pass (`InlineLoopRegions`) is available, together with a
utility function `dace.sdfg.utils.inline_loop_blocks` that inlines any
`LoopRegion`s to traditional state machine loops.

In summary, the PR includes:
- [x] Add `LoopRegion`s to SDFGs, a special control flow region to
represent loops
- [x] Pass / Utility function to remove all loop regions from a graph,
turning them back into regular state machine loops (a.k.a., inlining)
- [x] Tests for inlining of loops
- [x] Tests for the functional correctness of different types of loops
(regular for, while, do-while, do-for) and nested loops (gemm - tripple
nested loop)

---------

Co-authored-by: Tal Ben-Nun <[email protected]>
github-merge-queue bot pushed a commit that referenced this pull request Feb 23, 2024
Refactors the SDFG list and SDFG ids to a more general CFG list and CFG
id.
This change provides a further step towards compatibility with the
[hierarchical, multi-level
SDFGs](#1404).

The change is accompanied by a deprecation warning on the old interfaces
(`sdfg_list`, `sdfg_id`, `reset_sdfg_list`, and `update_sdfg_list`).
Until removal, the legacy methods continue to work as expected for
single level SDFGs.

---------

Co-authored-by: alexnick83 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core enhancement New feature or request
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

3 participants