-
Notifications
You must be signed in to change notification settings - Fork 10
FAQ
These are needed whenever the user invokes a language feature that requires remapping the cobounds of an existing coarray.
This can optionally happen in a CHANGE TEAM
construct, if the user included a coarray-association-list in the CHANGE TEAM
invocation. However not every CHANGE TEAM
needs this.
It may also be needed when invoking a procedure with a coarray dummy argument that specifies different cobounds. See F23 15.5.2.9 "Coarray dummy variables":

alias_lcobounds
and alias_ucobounds
determine the cobounds for the returned alias_handle
. The alias is not bound to any particular team, although of course later indexing into the alias using prif_image_index()
will be relative to some team.
Basically the coarray should be allocated by the initial team using a call analogous to:
prif_allocate_coarray(lcobounds=[1], ucobounds=[num_images()], size_in_bytes=sizeof(prif_critical_type) )
The compiler is free to either create one prif_critical_type
coarray per CRITICAL
construct, or take the simpler approach of having exactly one prif_critical_type
coarray for the whole program and conflating all the CRITICAL
constructs together (which oversynchronizes, but is still a valid implementation). I'd suggest the latter approach for simplicity in your initial implementation, especially since CRITICAL
is not a heavily used feature.
The short answer is that if your code generation has no need for context information, then you can simply pass a null pointer for cdata
.
The cdata
argument is entirely for your own use (as the compiler writer and client of PRIF), and the contents are entirely up to you. The prif_co_reduce
call accepts cdata
which is an arbitrary 64-bit value that is entirely opaque to the PRIF library. The PRIF library is the one that later invokes the operation_wrapper
callback while computing the reduction, and the PRIF library will pass the same cdata
value back to your generated code as the fourth argument to that operation_wrapper
invocation when the corresponding reduction operation callback needs to be invoked. The value is associated with a particular image's current invocation of prif_co_reduce
. So for example if you needed to pass a pointer to a compiler-generated stack frame closure or other metadata from the code around the user's call to CO_REDUCE
into the code which marshals the invocation of the user-provided operation callback, you could pass that pointer in the cdata
argument. The second example in the prif_co_reduce
section of the PRIF 0.5 specification shows how that could be used to support a user-provided operation over a (non-interoperable) derived type with length type parameters.
As another example, if the user-provided operation is known to be an interoperable procedure (or the compilers knows it can safely create a usable procedure pointer to it with a 64-bit representation), then you could pass that pointer in the cdata
argument and invoke it from within the generated operation_wrapper.
The short answer is "We made these changes to ensure PRIF can be portably implemented for any Fortran-compliant compiler". We encountered problems in practice when attempting to implement prif_co_{min,max}
as specified in PRIF 0.4 for character arguments with LLVM flang.
The Fortran-level CO_MIN
and CO_MAX
are required to accept arguments of any integer, real, or character type (including any non-interoperable type kind variants). It's worth noting that the actual computational requirements are rather different for value comparison operations between numerical types (which always have a static width, usually 1..8 bytes) and alphabetical comparison between character strings (which can have arbitrary dynamic length).
In PRIF 0.4 we conflated all these argument types together in a single PRIF entry point with a type(*)
dummy argument, and also included non-interoperable inputs. The main problem with this approach is that Fortran provides no guaranteed portable way for a callee (the PRIF library implementation) to disambiguate the exact underlying type and type parameters (i.e. character string length) once it's been conflated into a type(*)
dummy argument. This problem becomes even worse if the input is a non-interoperable numerical or non-interoperable character type.
PRIF 0.5 solves this problem via two changes:
- Constrain argument type for argument
a
toprif_co_{min,max,sum}
to only accept interoperable types. Compilers are not required to provide non-interoperable numerical or character types, but if they do thenprif_co_reduce
can be called to support any reductions invoked on those. Given the element storage size andCFI_type_t
code (from a CFI descriptor), this is enough for the PRIF implementation to uniquely disambiguate a matching interoperable numerical type. - Statically separate character typed inputs into
prif_co_max_character
andprif_co_min_character
entry points. This makes it easy for the PRIF implementation ofco_{min,max}
to disambiguate when it's asked to perform alphabetic character comparisons on dynamic-length strings, and should ensure it can correctly infer the character length type parameter by inspecting the CFI descriptor.
PRIF 0.5 also overhauled the interface to prif_co_reduce
. The problems with the old interface are discussed in section III-G of our LLVM-HPC paper. In a nutshell, the user-provided reduction callback function in general can accept non-interoperable types and might not be bind(C)
. For both reasons, the user-provided callback cannot be safely/portably invoked from C code in a type-erased manner based on a type(*)
dummy argument, it must be invoked from Fortran code with properly concretely typed actual arguments. The PRIF interface deliberately omits detailed Fortran-level type information, and the PRIF implementation cannot generate Fortran caller code with argument types matching user-defined derived types, thus the compiler must take on that responsibility. The new operation_wrapper
argument ensures the call to the user-provided function is made from Fortran with properly matching concrete actual argument types. We realize this complicates the calling convention for prif_co_reduce
, but we felt it was important to ensure PRIF implementations can strictly adhere to the Fortran standard.
With these interface changes in place, we believe the C interop features in the Fortran standard guarantee sufficient information so that the PRIF collective subroutines can be portably implemented for any compliant compiler.