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

Inline elemental functions: skip calls with args being array (slices) #401

Merged
merged 4 commits into from
Oct 18, 2024

Conversation

MichaelSt98
Copy link
Collaborator

We have a problem for things like:

elemental function elem(x, y)
    real :: x, y, elem, tmp
    temp = y * 2.0
    elem = x + tmp
end function elem

real :: x_scalar, b_scalar, res_scalar
real :: x_arr(10). y_arr(10), res_arr(10)
real :: x_arr_2(12). y_arr_2(12), res_arr_2(12)

res_scalar = elem(x_scalar, y_scalar)
res_arr = elem(x_arr, y_arr)
res_arr = elem(x_arr, y_scalar)
res_arr = elem(y_scalar, x_arr)
res_arr_2 = elem(x_arr_2, y_arr_2)
...

As the fix is not straight-forward/trivial, this PR makes the inline to skip the problematic calls (for now). Thus, this is not a fix to make those problematic calls being inlined correctly!

A more detailed description of the problem: #400

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 for this!

For readability, we could make the checks a bit shorter (suggestions in inline comments).

The test is blowing a bit out of proportion this way and I would prefer splitting the completely separate "array" case into a separate test. I left a suggestion how you can avoid code duplication by moving the module into a joint fixture.

Finally, this requires a rebase due to the refactoring of inline and extract packages.

Comment on lines 169 to 182
fcode_arr = """
subroutine transform_inline_elemental_functions_extended_array(v1, v2, v3, len)
use iso_fortran_env, only: real64
use multiply_extended_mod, only: multiply, multiply_single_line, add
integer, intent(in) :: len
real(kind=real64), intent(in) :: v1(len)
real(kind=real64), intent(inout) :: v2(len), v3(len)
real(kind=real64), parameter :: param1 = 100.
integer, parameter :: arr_index = 1

v2 = multiply(v1(:), 6._real64) + multiply_single_line(v1(:), 3._real64)
v3 = add(param1, 200._real64) + add(v1, 150._real64) + multiply(v1(arr_index), v2(1))
end subroutine transform_inline_elemental_functions_extended_array
"""
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's make the array case a separate test, please.

You can still avoid replicating the module code etc using the following pattern:

@pytest.fixture(name='multiply_extended_mod', params=available_frontends())
def fixture_multiply_extended_mod(request, tmp_path):
    fcode_module = """
...
    """

    frontend = request.param
    module = Module.from_source(fcode_module, frontend=frontend, xmods=[tmp_path])
    return module, frontend

def test_transform_inline_elemental_functions_extended_scalar(multiply_extended_mod, tmp_path):
    module, frontend = multiply_extended_mod

    fcode = "..."

    routine = Subroutine.from_source(fcode, frontend=frontend, definitions=[module], xmods=[tmp_path])
    ...

def test_transform_inline_elemental_functions_extended_arr(multiply_extended_mod, tmp_path):
    module, frontend = multiply_extended_mod

    fcode_arr = "..."

    routine = Subroutine.from_source(fcode_arr, frontend=frontend, definitions=[module], xmods=[tmp_path])
    ...

return
if (expr.procedure_type.is_function and expr.procedure_type.is_elemental):
if any(is_array(val) for val in expr.arg_map.values()):
warning(f'Call to elemental function \'{expr.routine.name}\' with array arguments.'
Copy link
Collaborator

Choose a reason for hiding this comment

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

You can avoid escaping if you mix quotation marks:

Suggested change
warning(f'Call to elemental function \'{expr.routine.name}\' with array arguments.'
warning(f"Call to elemental function '{expr.routine.name}' with array arguments."

@@ -389,6 +393,19 @@ def __init__(self, query, recurse_query=None, inline_elementals_only=False,
def map_inline_call(self, expr, *args, **kwargs):
if not self.visit(expr, *args, **kwargs):
return
if expr.procedure_type is BasicType.DEFERRED or isinstance(expr.routine, StatementFunction):
return
Copy link
Collaborator

Choose a reason for hiding this comment

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

We could add here a bailout for non-functions and save a few checks further down:

Suggested change
return
return
if not expr.procedure_type.is_function:
return

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hmm this ends up with errors like:

AttributeError: 'BasicType' object has no attribute 'is_function'

Copy link
Collaborator

Choose a reason for hiding this comment

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

You should add this below the checks in ll. 396-397

Comment on lines 398 to 399
if self.inline_elementals_only:
if not (expr.procedure_type.is_function and expr.procedure_type.is_elemental):
Copy link
Collaborator

Choose a reason for hiding this comment

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

This would then become

Suggested change
if self.inline_elementals_only:
if not (expr.procedure_type.is_function and expr.procedure_type.is_elemental):
if self.inline_elementals_only and not expr.procedure_type.is_elemental:

if functions:
if expr.routine not in functions:
return
if (expr.procedure_type.is_function and expr.procedure_type.is_elemental):
Copy link
Collaborator

Choose a reason for hiding this comment

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

And this would simplify to

Suggested change
if (expr.procedure_type.is_function and expr.procedure_type.is_elemental):
if expr.procedure_type.is_elemental:

@MichaelSt98
Copy link
Collaborator Author

Thanks for the quick review!

@MichaelSt98 MichaelSt98 force-pushed the nams-inline-skip-elemental-functions-array-args branch from 4739c2c to 3346735 Compare October 14, 2024 17:38
Copy link

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

Copy link

codecov bot commented Oct 15, 2024

Codecov Report

Attention: Patch coverage is 98.11321% with 1 line in your changes missing coverage. Please review.

Project coverage is 95.58%. Comparing base (b6eb817) to head (06a810e).
Report is 51 commits behind head on main.

Files with missing lines Patch % Lines
loki/transformations/inline/functions.py 91.66% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #401   +/-   ##
=======================================
  Coverage   95.57%   95.58%           
=======================================
  Files         201      201           
  Lines       39810    39874   +64     
=======================================
+ Hits        38050    38112   +62     
- Misses       1760     1762    +2     
Flag Coverage Δ
lint_rules 96.39% <ø> (ø)
loki 95.56% <98.11%> (+<0.01%) ⬆️

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.

@MichaelSt98 MichaelSt98 requested a review from reuterbal October 16, 2024 13:22
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 for taking care of the suggested changes. Looks great now!

@reuterbal reuterbal added the ready to merge This PR has been approved and is ready to be merged label Oct 18, 2024
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.

Yes, looks good to me. GTG

@reuterbal reuterbal merged commit cc30c9e into main Oct 18, 2024
13 checks passed
@reuterbal reuterbal deleted the nams-inline-skip-elemental-functions-array-args branch October 18, 2024 12:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready to 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