-
Notifications
You must be signed in to change notification settings - Fork 13
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
Conversation
Documentation for this branch can be viewed at https://sites.ecmwf.int/docs/loki/273/index.html |
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.
Thanks, this looks good. I've made some suggestions how to improve the readability of the implementation, but fundamentally no objections here.
if isinstance(symbol, Array) and symbol.dimensions is not None\ | ||
and not all(dim == sym.RangeIndex((None, None)) for dim in symbol.dimensions): |
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.
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): |
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.
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))
)
self.retriever = ExpressionRetriever(lambda e: isinstance(e, (DerivedType, Array, Scalar))\ | ||
and e.name.lower() in vars2dereference) |
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 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\ |
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.
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 = [] |
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.
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) |
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.
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?
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.
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?!
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.
It does, many thanks!
Codecov ReportAll modified and coverable lines are covered by tests ✅
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
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
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.
Many thanks, nothing further from me!
DeReferenceTrafo
for and withinFortranCTransformation
to insert apply/insertDereference
=*
andReference
/address-of =&
operators.