Skip to content

perf[next-dace]: Enhance MoveDataflowIntoIfBody transformation#2514

Merged
iomaganaris merged 12 commits intomainfrom
enhance_move_dataflow_into_if
Mar 10, 2026
Merged

perf[next-dace]: Enhance MoveDataflowIntoIfBody transformation#2514
iomaganaris merged 12 commits intomainfrom
enhance_move_dataflow_into_if

Conversation

@iomaganaris
Copy link
Copy Markdown
Contributor

@iomaganaris iomaganaris commented Mar 5, 2026

Move nodes into the state of a ConditionalBlock even if they are marked by multiple Connectors

Needs:

  • Rebase on latest main

@iomaganaris iomaganaris requested a review from edopao March 5, 2026 15:50
Copy link
Copy Markdown
Contributor

@edopao edopao left a comment

Choose a reason for hiding this comment

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

LGTM, just one minor comment.

@iomaganaris iomaganaris force-pushed the enhance_move_dataflow_into_if branch from 0cfd5fb to 3ab44a0 Compare March 6, 2026 13:56
@iomaganaris iomaganaris marked this pull request as ready for review March 6, 2026 13:57
edopao
edopao previously approved these changes Mar 6, 2026
Copy link
Copy Markdown
Contributor

@edopao edopao left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Copy Markdown
Contributor

@philip-paul-mueller philip-paul-mueller left a comment

Choose a reason for hiding this comment

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

See my comment.

Copy link
Copy Markdown
Contributor

@philip-paul-mueller philip-paul-mueller left a comment

Choose a reason for hiding this comment

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

I have now looked at the changes and I have some suggestions.
A part of my comments are "adding todos for me" and suggestions about improving the comments, so it is not as much as it looks like.

My main concern is that some nodes are replicated (added to the nested state) multiple times.
However, I am not fully sure why the unit test passes, it is probably that I do not see the part that does it.

Comment on lines 234 to 236
# Gather all the already moved nodes to avoid that we move the same node multiple times
already_moved_nodes: set[dace_nodes.Node] = set()
# Finally relocate the dataflow
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
# Gather all the already moved nodes to avoid that we move the same node multiple times
already_moved_nodes: set[dace_nodes.Node] = set()
# Finally relocate the dataflow
# Relocate the dataflow, because the node sets listed in `relocatable_dataflow` are not disjoint we have to make sure that we relocate the nodes only once.
already_moved_nodes: set[dace_nodes.Node] = set()

sdfg: dace.SDFG,
) -> None:
if_block: dace_nodes.NestedSDFG = self.if_block
if_block_spec = self._partition_if_block(if_block)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I kind of have the feeling that this function should compute the mapping you compute in conn_name_to_access_node_map since it has to look at all nodes anyway.

However, I think a TODO in _partition_if_block()'s docstring should be sufficient.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It needs the relocatable_dataflow though so not sure if it's possible to do that there unless we do it for every node

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not necessarily.
Having relocatable_dataflow would just allow you skip some instances that are not needed, but I think it is still a net gain if we do it in one go and then reuse, because we have to look at every node anyway.
But it is for sure something for later.
I think I will create a PR that addresses this and some indeterminism.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Are you sure that here no filtering is needed?
This was possible because nodes_to_move where disjoint, which is no longer the case, thus I would expect that there is some filtering needed, when you create the nodes inside the branch, but not when you create the new_nodes mapping.
The same applies to where you create the new data descriptors.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I have added the old_to_new_nodes_map that takes care of copying the access nodes per branch only once

existing_connector = conn_name_to_access_node_map[oedge.dst_conn][1].data
if not inner_sdfg.arrays[existing_connector].transient:
inner_sdfg.arrays[existing_connector].transient = True
if_block.remove_in_connector(existing_connector)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I do not like this.
It is not "uniform" meaning now you remove the in connector in two different locations.
I would prefer if it only at one location, have you tried to just remove it here and then play the other thing out.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think it would actually complicate things if we removed it elsewhere because we would have to keep track of which connectors have to be removed from here or look for which connectors don't have any edges assigned to them

@edopao edopao dismissed their stale review March 9, 2026 10:58

Some changes were requested by Philip, removing my approval.

Copy link
Copy Markdown
Contributor

@philip-paul-mueller philip-paul-mueller left a comment

Choose a reason for hiding this comment

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

LGTM

][1].data
if not inner_sdfg.arrays[inner_access_node_of_connector_name].transient:
inner_sdfg.arrays[inner_access_node_of_connector_name].transient = True
if_block.remove_in_connector(inner_access_node_of_connector_name)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Have you tried to remove just this line.
I think it should still work, because this function is called for the connector anyway and at the end it is removed.
//Currently remove_in_connector() does not check if the connector exits or not and ALWAYS returns True.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This doesn't work because in the following case __arg1 will have no relocated_nodes due to the filter_nodes function that checks if all the outputs of the dataflow go to other nodes on the same dataflow
image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Actually I had a closer look and figure out that if we add another tasklet after the a2 AccessNode then the transformation doesn't move all the AccessNodes and Tasklets it could into the if. See the following SDFG.
The blocker is that _partition_if_block expects in the states of the ConditionalBlocks only nodes that are AccessNodes that have the names of the in/out connectors of the ConditionalBlock NestedSDFG.
Then _check_for_data_and_symbol_conflicts fails because it finds a2 inside the NestedSDFG.
I think the first blocker can be easily handled by relaxing the requirements. The second one however requires more work because we have to rename the AccessNodes in case we have to move them inside and there's an existing AccessNode with the same name. I think that this situation may arise only if we try to move inside the NestedSDFG of the ConditionalBlock an AccessNode that has the same name as one of the input Connectors and thus an AccessNode inside the NestedSDFG as well.
Currently thankfully we don't come across this case in the graupel case so we can avoid fixing this but I don't know if we should actually take care of this in this PR
image

@iomaganaris
Copy link
Copy Markdown
Contributor Author

I discussed with @philip-paul-mueller to get this merged and the added test with xfail added to this PR can be handled in a subsequent PR

@iomaganaris iomaganaris merged commit b088235 into main Mar 10, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants