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

F2C: DeReferenceTrafo #273

Merged
merged 4 commits into from
Apr 11, 2024
Merged

F2C: DeReferenceTrafo #273

merged 4 commits into from
Apr 11, 2024

Conversation

MichaelSt98
Copy link
Collaborator

DeReferenceTrafo for and within FortranCTransformation to insert apply/insert Dereference = * and Reference/address-of = & operators.

Copy link

github-actions bot commented Apr 5, 2024

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

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 good. I've made some suggestions how to improve the readability of the implementation, but fundamentally no objections here.

Comment on lines 503 to 504
if isinstance(symbol, Array) and symbol.dimensions is not None\
and not all(dim == sym.RangeIndex((None, None)) for dim in symbol.dimensions):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Tthe creation of the symbol map is then simplified to

symbol_map = {
    symbol: Dereference(symbol.clone()) for symbol in self.retriever.retrieve()
    if symbol.name.lower() in self.vars2dereference
}

kernel.symbol_attrs[arg.name] = _type
kernel.body = SubstituteExpressions(var_map).visit(kernel.body)

class DeReferenceTrafo(Transformer):
Copy link
Collaborator

Choose a reason for hiding this comment

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

The criterion for a symbol that needs (de)referencing is the same throughout, so maybe it would make sense to capture this as a static method in the transformer:

@staticmethod
def is_reference(symbol):
    return (
        isinstance(symbol, Array) 
        and not (symbol.dimensions is None or all(dim == ':' for dim in symbol.dimensions))
    )

Comment on lines 496 to 497
self.retriever = ExpressionRetriever(lambda e: isinstance(e, (DerivedType, Array, Scalar))\
and e.name.lower() in vars2dereference)
Copy link
Collaborator

Choose a reason for hiding this comment

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

With the above method, you could use this directly in the retriever:

self.retriever = ExpressionRetriever(self.is_reference)
self.vars2dereference = vars2dereference

new_args = ()
call_arg_map = dict((v,k) for k,v in o.arg_map.items())
for arg in o.arguments:
if isinstance(arg, Array) and arg.dimensions\
Copy link
Collaborator

Choose a reason for hiding this comment

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

This conditional would then also become more readable as

if self.is_reference(arg) and (isinstance(call_arg_map[arg], Array) or call_arg_map[arg].type.intent.lower() != 'in'):

@@ -477,17 +478,51 @@ def generate_c_kernel(self, routine):
convert_to_lower_case(kernel)

# Force pointer on reference-passed arguments
var_map = {}
to_be_dereferenced = []
Copy link
Collaborator

Choose a reason for hiding this comment

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

Readability of the method might benefit from putting the reference/dereference handling into a utility method maybe, and then simply calling self.convert_args_to_references(kernel)

integer, intent(inout) :: a, c
integer, intent(in) :: b
integer, intent(in) :: len
integer, intent(inout) :: arr1(len, len)
Copy link
Collaborator

Choose a reason for hiding this comment

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

For my education: What is the intended outcome if we had (another) argument arr(:,:) here? Would this pre-empt the F2C transformation until we figure out the actual shape, or would it simply not be passed as a reference?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since we need the actual shape information for flattening (see flatten_arrays() - TypeError: Resolve shapes being of type RangeIndex, e.g., ":" before flattening!, raised if isinstance(shape[-2], sym.RangeIndex))arrays having more than one dimension, the DeReferenceTrafo wouldn't be executed.

However,

subroutine transpile_call_driver(a)
  use transpile_call_kernel_mod, only: transpile_call_kernel
    integer, parameter :: len = 5
    integer, intent(inout) :: arr1(len)
    integer, intent(inout) :: arr2(len)
    call transpile_call_kernel(arr1, arr2, len)
end subroutine transpile_call_driver

  subroutine transpile_call_kernel(arr1, arr2, len)
    integer, intent(in) :: len
    integer, intent(inout) :: arr1(len)
    integer, intent(inout) :: arr2(:)

    arr1(1) = 1
    arr2(1) = 1
  end subroutine transpile_call_kernel

is transformed/transpiled to:

int transpile_call_driver_c() {
  int len = 5;
  transpile_call_kernel(arr1, arr2, len);
  return 0;
}

int transpile_call_kernel_c(int * restrict arr1, int * restrict arr2, int len) {

  int arr1[len];
  int arr2[len];
  arr1[1 - 1] = 1;
  arr2[1 - 1] = 1;
  return 0;
}

if that answers your question?!

Copy link
Collaborator

Choose a reason for hiding this comment

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

It does, many thanks!

Copy link

codecov bot commented Apr 10, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.87%. Comparing base (beb848c) to head (92dcaf5).
Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #273      +/-   ##
==========================================
+ Coverage   92.81%   92.87%   +0.05%     
==========================================
  Files         102      102              
  Lines       18216    18243      +27     
==========================================
+ Hits        16908    16943      +35     
+ Misses       1308     1300       -8     
Flag Coverage Δ
lint_rules 96.39% <ø> (ø)
loki 92.84% <100.00%> (+0.06%) ⬆️
transformations 92.20% <ø> (ø)

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.

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, nothing further from me!

@reuterbal reuterbal added the ready for merge This PR has been approved and is ready to be merged label Apr 10, 2024
@reuterbal reuterbal merged commit e5eae78 into main Apr 11, 2024
13 checks passed
@reuterbal reuterbal deleted the nams_de_reference_trafo_f2c branch April 11, 2024 08:48
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.

2 participants