Open brandongc opened 2 years ago
I looked at this a bit. I am not sure it is possible to do what you want. Fortran is pretty strict on typing, so the abstract interface for the user function seems like it would have to be:
abstract interface
subroutine MPI_User_function_new(invec, inoutvec, len, datatype)
!use, intrinsic :: iso_c_binding, only : c_ptr
use mpi_f08, only : MPI_Datatype
implicit none
!type(c_ptr), value :: invec, inoutvec
type(*), dimension(..), intent(in) :: invec
type(*), dimension(..), intent(inout) :: inoutvec
integer, intent(in) :: len
type(MPI_Datatype), intent(in) :: datatype
end subroutine
end interface
Then this function becomes the trampoline, and the gymnastics to do the reduction business is no simpler than what you have above (and it seems to be less simple, without changes to Fortran, based on my reading of the standard and testing so far).
Specifically, you'd have to write your reduction with the following signature, and convert the assumed-type arguments as follows, where get_cptr
is a trivial C utility function, because it seems that one cannot convert directly to Fortran pointers (I am waiting to hear from J3 if I understand this correctly).
subroutine X_function(invec, inoutvec, len, datatype)
use, intrinsic :: iso_c_binding, only : c_ptr, c_f_pointer
use mpi_f08, only : MPI_Datatype
use f, only : get_cptr
implicit none
type(*), dimension(..), intent(in) :: invec
type(*), dimension(..), intent(inout) :: inoutvec
integer, intent(in) :: len
type(MPI_Datatype), intent(in) :: datatype
type(c_ptr) :: cpi, cpo
real, dimension(:), pointer :: fpi, fpo
call get_cptr(invec,cpi)
call get_cptr(inoutvec,cpo)
call c_f_pointer(cpi,fpi,[size(invec)])
call c_f_pointer(cpo,fpo,[size(inoutvec)])
...
end subroutine
It might be useful for you to discuss this in front of a whiteboard with Bill Long in February (J3 meeting at LBNL), if we don't have a clean resolution by then.
I got some help from Vipul in J3. I think I have a reasonable solution now.
The prototype that looks more like modern Fortran is:
abstract interface
subroutine MPI_User_function_f18(invec, inoutvec, len, datatype)
use mpi_f08, only : MPI_Datatype
implicit none
type(*), dimension(..), target, intent(in) :: invec
type(*), dimension(..), target, intent(inout) :: inoutvec
integer, intent(in) :: len
type(MPI_Datatype), intent(in) :: datatype
end subroutine
end interface
The user can then write a user-defined reduction that looks something like the following.
subroutine Y_function(invec, inoutvec, len, datatype)
use mpi_f08, only : MPI_Datatype
implicit none
real, dimension(:), target, intent(in) :: invec
real, dimension(:), target, intent(inout) :: inoutvec
integer, intent(in) :: len
type(MPI_Datatype), intent(in) :: datatype
inoutvec = inoutvec + invec
end subroutine
I am not 100% sure that this is strictly legal Fortran, but it works with ifx
.
I need to think of how to proceed from here.
Malcolm said Y_function
does not match. However, the following seems to be fully standard-compliant.
One thing we can do here is use SELECT RANK
and SELECT TYPE
to write a reduction that works for a variety of inputs, whereas with the current interface requires the user to figure this out from len
and datatype
.
On the other hand, for the cases where the user knows the input type and doesn't need to figure it out via Fortran or MPI datatypes, it's not better.
subroutine X_function(invec, inoutvec, len, datatype)
use, intrinsic :: iso_c_binding, only : c_ptr, c_loc, c_f_pointer
use mpi_f08, only : MPI_Datatype
implicit none
type(*), dimension(..), target, intent(in) :: invec
type(*), dimension(..), target, intent(inout) :: inoutvec
integer, intent(in) :: len
type(MPI_Datatype), intent(in) :: datatype
type(c_ptr) :: cpi, cpo
integer, dimension(:), pointer :: fpi, fpo
cpi = c_loc(invec)
cpo = c_loc(inoutvec)
call c_f_pointer(cpi,fpi,[size(invec)])
call c_f_pointer(cpo,fpo,[size(inoutvec)])
fpo = fpo + fpi
end subroutine
Problem
User defined reduction operations for
mpi_f08
are not natural to write in Fortran:Proposal
In MPI 5 enable users to write something like
Changes to the Text
At minimum change the abstract interface for user specified reductions.
Impact on Implementations
Add a Fortran internal callback trampoline or use ISO_Fortran_binding.h to derive a C representation of the user function?
Impact on Users
Users get to write "normal" Fortran reductions.