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

SCC: Support for bounds aliases and derived type members as bounds #250

Merged
merged 12 commits into from
Apr 24, 2024

Conversation

awnawab
Copy link
Contributor

@awnawab awnawab commented Mar 18, 2024

This is the final PR needed to transform the SL. It consists of a series of fixes to the SCC transforms, the biggest of which is the ability to use aliased components of a derived-type as the horizontal loop bounds.

NB: this is stacked on top of #249.

Copy link

Documentation for this branch can be viewed at https://sites.ecmwf.int/docs/loki/250/index.html

Copy link

codecov bot commented Mar 18, 2024

Codecov Report

Attention: Patch coverage is 92.45283% with 4 lines in your changes are missing coverage. Please review.

Project coverage is 94.95%. Comparing base (59303e4) to head (aec79bf).

Files Patch % Lines
loki/dimension.py 69.23% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #250      +/-   ##
==========================================
- Coverage   94.95%   94.95%   -0.01%     
==========================================
  Files         153      153              
  Lines       32052    32086      +34     
==========================================
+ Hits        30436    30466      +30     
- Misses       1616     1620       +4     
Flag Coverage Δ
lint_rules 96.39% <ø> (ø)
loki 95.12% <84.61%> (-0.01%) ⬇️
transformations 92.17% <100.00%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@awnawab
Copy link
Contributor Author

awnawab commented Mar 18, 2024

Can I push a small fix to the dependency transform here or shall I file a separate PR for that?

@reuterbal
Copy link
Collaborator

Can I push a small fix to the dependency transform here or shall I file a separate PR for that?

I would hold off or make it a separate PR. That transforms has been reshuffled a bit on the new Scheduler branch.

@awnawab
Copy link
Contributor Author

awnawab commented Mar 25, 2024

@reuterbal I have rebased and fixed this PR and #249, please let me know when I can push changes to both.

@reuterbal
Copy link
Collaborator

@reuterbal I have rebased and fixed this PR and #249, please let me know when I can push changes to both.

I've merged the backlog of already reviewed PRs now, so now is likely a good point to rebase your PRs. Many thanks!

@reuterbal reuterbal added the rebase required Rebase required for the PR branch to resolve conflicts label Apr 11, 2024
@awnawab
Copy link
Contributor Author

awnawab commented Apr 12, 2024

This has a conflict now with #270, so I am turning this into a draft until that is reviewed and merged.

@awnawab awnawab marked this pull request as draft April 12, 2024 07:21
@awnawab awnawab force-pushed the naan-scc-fixes branch 6 times, most recently from 77ffee9 to ae61311 Compare April 12, 2024 16:14
@awnawab awnawab marked this pull request as ready for review April 19, 2024 14:00
@reuterbal reuterbal removed the rebase required Rebase required for the PR branch to resolve conflicts label Apr 19, 2024
Copy link
Collaborator

@reuterbal reuterbal left a comment

Choose a reason for hiding this comment

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

Thanks, this looks great!

I've left a few comments but no fundamental show stoppers.

Comment on lines +34 to +36
bounds_aliases : list or tuple of strings
String representations of alternative bounds variables that are
used to define loop ranges.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is really great, I was missing that functionality (and hacked around in the Fortran instead... 😬 )

Comment on lines 799 to 814
def resolve_typebound_var(name, variable_map):
"""
A small convenience utility to resolve type-bound variables.

Parameters
----------
name : str
The full name of the variable to be resolved, e.g., a%b%c%d.
variable_map : dict
A map of the variables defined in the current scope.
"""

name_parts = name.split('%', maxsplit=1)
if (var := variable_map.get(name_parts[0], None)) and len(name_parts) > 1:
var = var.get_derived_type_member(name_parts[1])
return var
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd prefer that an expression-specific utility like this lives in the loki.expression or loki.ir package. Could we not make this a method of Scope, for example, with the option to provide the variable_map as an optional argument. It could by default be initialized to self.variable_map but for frequent calls, providing as an argument speeds things up.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yes, that would be much cleaner, thanks! I assume you mean ProgramUnit though rather than Scope, because that is where the variables and variable_map are computed?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, thanks, ProgramUnit would be the right place.

Comment on lines 97 to 112
variables = routine.variables
bounds = as_tuple(horizontal.bounds[0])
bounds += as_tuple(horizontal.bounds[1])
try:
if bounds[0] not in variables:
raise RuntimeError(f'No horizontal start variable found in {routine.name}')
if bounds[1] not in variables:
raise RuntimeError(f'No horizontal end variable found in {routine.name}')
except RuntimeError as exc:
if horizontal._bounds_aliases:
bounds = as_tuple(horizontal._bounds_aliases[0])
bounds += as_tuple(horizontal._bounds_aliases[1])
if bounds[0].split('%', maxsplit=1)[0] not in variables:
raise RuntimeError(f'No horizontal start variable found in {routine.name}') from exc
if bounds[1].split('%', maxsplit=1)[0] not in variables:
raise RuntimeError(f'No horizontal end variable found in {routine.name}') from exc
Copy link
Collaborator

Choose a reason for hiding this comment

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

This looks a bit long-winded, with the use of exceptions instead of ifs. I would add a method bounds_expressions to Dimension, e.g.:

>>> d = Dimension('test_dim_alias', bounds=('istart', 'iend'), bounds_aliases=('bnds%start', 'bnds%end'))
>>> d.bounds_expressions
(('istart', 'bnds%start'), ('iend', 'bnds%end'))

and then rewrite the method as:

Suggested change
variables = routine.variables
bounds = as_tuple(horizontal.bounds[0])
bounds += as_tuple(horizontal.bounds[1])
try:
if bounds[0] not in variables:
raise RuntimeError(f'No horizontal start variable found in {routine.name}')
if bounds[1] not in variables:
raise RuntimeError(f'No horizontal end variable found in {routine.name}')
except RuntimeError as exc:
if horizontal._bounds_aliases:
bounds = as_tuple(horizontal._bounds_aliases[0])
bounds += as_tuple(horizontal._bounds_aliases[1])
if bounds[0].split('%', maxsplit=1)[0] not in variables:
raise RuntimeError(f'No horizontal start variable found in {routine.name}') from exc
if bounds[1].split('%', maxsplit=1)[0] not in variables:
raise RuntimeError(f'No horizontal end variable found in {routine.name}') from exc
variable_map = routine.variable_map
bounds = ()
for name, bounds in zip(['start', 'end'], horizontal.bounds_expressions):
for bound in bounds:
if bound in variable_map:
bounds += (bound,)
break
else:
raise RuntimeError(f'No horizontol {name} variable matching {horizontal.bounds_expressions[0]} found in {routine.name}')

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Many many thanks for this 🙏 this is much cleaner and simpler than what I original had 👌

@@ -275,7 +293,7 @@ def process_kernel(self, routine):
return

# check for horizontal loop bounds in subroutine symbol table
self.check_horizontal_var(routine, self.horizontal)
bounds = self.check_horizontal_var(routine, self.horizontal)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Might be sensible to rename this utility to get_horizontal_bound_var or something similar? Also, instead of routine you could directly pass the variable_map, I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes I agree with the name change, but I'll keep the routine as an argument because I would like to also print the routine name to have a more informative error message.

Comment on lines 381 to +383
demote_locals = item.config.get('demote_locals', self.demote_local_arrays)
self.process_kernel(routine, demote_locals=demote_locals)
preserve_arrays = item.config.get('preserve_arrays', [])
self.process_kernel(routine, demote_locals=demote_locals, preserve_arrays=preserve_arrays)
Copy link
Collaborator

Choose a reason for hiding this comment

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

These options should be documented. Would you mind adding a short paragraph in the class docstring?

Copy link
Collaborator

@mlange05 mlange05 left a comment

Choose a reason for hiding this comment

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

I agree with what @reuterbal pointed out, and have nothing further to add. I can confirm that this runs fine with ec-physics regression.

Copy link
Collaborator

@reuterbal reuterbal left a comment

Choose a reason for hiding this comment

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

Many thanks, very happy with this now!

@reuterbal reuterbal changed the title SCC fixes for SL SCC: Support for bounds aliases and derived type members as bounds Apr 23, 2024
@reuterbal reuterbal added the ready for merge This PR has been approved and is ready to be merged label Apr 23, 2024
@reuterbal reuterbal merged commit c212156 into main Apr 24, 2024
12 checks passed
@reuterbal reuterbal deleted the naan-scc-fixes branch April 24, 2024 08:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready for merge This PR has been approved and is ready to be merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants