-
Notifications
You must be signed in to change notification settings - Fork 12
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
Disable default recursion for Transformation.apply #136
Disable default recursion for Transformation.apply #136
Conversation
Documentation for this branch can be viewed at https://sites.ecmwf.int/docs/loki/136/index.html |
18b61a4
to
47b86a8
Compare
Codecov Report
@@ Coverage Diff @@
## main #136 +/- ##
==========================================
- Coverage 92.12% 92.08% -0.04%
==========================================
Files 89 89
Lines 16508 16533 +25
==========================================
+ Hits 15208 15225 +17
- Misses 1300 1308 +8
Flags with carried forward coverage won't be shown. Click here to find out more.
|
47b86a8
to
562c63d
Compare
562c63d
to
9fd7318
Compare
… item if called via recursion
35f6390
to
2889c4a
Compare
Merged #137 and rebased over main |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, first of all many thanks for sticking with it through this change. This one was quite tricky, because the underlying assumptions of the DependencyTransformation
are basically broken and ill designed (for context, this transformation also predates most of the scheduler "smarts").
Nevertheless, full removing recursion and letting transformations implement the complex file=>module=>routine=>member recursion manually is a good move, for now, until we have more flexibility to configure transformations generically (the "manifest" idea).
But, there is a lot(!) of great housekeeping, testing and general quality of life stuff in here, so GT to merge this, and I'll attempt any simplification and clean-up on top of this.
is_member = isinstance(routine.parent, Subroutine) | ||
|
||
# Pick out correct item for current subroutine if processed via recursion | ||
if 'items' in kwargs: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand this logic here: Why are we recovering item
from items
if item
is given by the scheduler?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's gone after yesterday's push, the file entry point is the place now where we do the item-picking and dispatch to program unit-specific entry points.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, and after diving through this a little more, I think I understand how/why this was done.
@@ -29,9 +28,6 @@ | |||
) | |||
|
|||
# pylint: disable=wrong-import-order | |||
from transformations.argument_shape import ( | |||
ArgumentArrayShapeAnalysis, ExplicitArgumentArrayShapeTransformation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for blindly trusting the linter instead of using my brain...
@@ -638,9 +650,16 @@ def process(self, transformation, reverse=False, item_filter=SubroutineItem, use | |||
# Use entry from item_map to ensure the original item is used in transformation | |||
_item = self.item_map[item.name] | |||
|
|||
# Pick out the IR node to which to apply the transformation | |||
# TODO: should this become an Item property? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[no action] Yes, it should, but it requires the SGraph development to make this behaviour neat. So good for now.
if items: | ||
# Recursion into all subroutine items in the current file | ||
for item in items: | ||
self.transform_subroutine(item.routine, item=item, role=item.role, targets=item.targets, **kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[no action] This interwoven subtlety highlights that the DependencyTransform
is actually deeply flawed and needs to be re-designed. As already discussed offline, like as a combination of several individual transformations, so thanks for keeping this functional! 🙏
tests/test_transform_dependency.py
Outdated
driver = Sourcefile.from_source(driver_fcode, frontend=frontend) | ||
|
||
# Because the renaming is intended to be applied to the routines as well as the enclosing module, | ||
# we need to invoke the transformation on the full source file and activate recursion to contained nodes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the removal of the recurse_to_contained_nodes
option, this comment seems outdated. It's also repeated a few times throughout the test file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! I removed the branching in the test related to this but overlooked the comments. Will fix
fdf59cd
to
87bd488
Compare
This is a proposal to fix #131.
By default, the
Transformation
class recurses to all contained nodes, i.e., callingapply
on aSourcefile
recurses into allModule
andSubroutine
nodes in that file, and so on. Arguably, this was a questionable design choice, however, theScheduler.process
method relies on this behaviour to apply transformations. There, we invoke the transformation always on the source file that contains the IR node corresponding to anItem
. (And then do some silly filtering afterwards, which possibly even prevents us from applying transformations to contained member subroutines...? 🤔)This PR switches off the recursion by default but allows to retain current behaviour via the
recurse_to_contained_nodes
option.I'll file a separate PR on top of the current one that changes also the Scheduler behaviour by directly applying transformations only to the IR node corresponding to a scheduler graph item. This requires some more careful regression testing for ecphys, and therefore this might only be sensible to do with the new Scheduler (hence the separate PR).
Important to note is that the change does have API implications when not using the Scheduler, because it requires to be more careful to which IR node a Transformation is applied - by either explicitly applying it to the target file, module, or subroutine directly, or explicitly enabling the recursion.