Re: [MPI3 Fortran] Proposing changes to Fortran 2008
On Mar 12, 2008, at 3:24 PM, Aleksandar Donev wrote:
Hello,
I am just joining this group
Welcome Aleks.
The main issue is the handling of the void* arguments and avoiding the issues with type-kind-rank (TKR) matching between actuals and dummies. The first step in any proposal to J3 is to argue that what was already put in Fortran 2003 with C Interop is insufficient. Here is my argument, but other things can be added.
The mechanism for passing void* pointers is scalar arguments of type C_PTR. At the call site, C_LOC is used to get the address: CALL MPI_Send(C_LOC(buffer)...) The issues with this are: 1) buffer must have the TARGET attribute, affecting performance and existing codes
We discussed this at the MPI Forum meeting last week. In my opinion, unless we can get this fixed, users will revolt and not use the new interfaces as it may decrease performance.
2) one must add C_LOC at every call site, thus affecting existing codes. Number 1 is very serious, IMO. It cannot be relaxed without compromising the standard's internal consistency. So a new mechanism is needed.
A possible solution is something like:
interface subroutine mpi_send(buffer...) bind(c) type(c_void), dimension(*) :: buffer end subroutine end interface
or
interface subroutine mpi_send(buffer,N,...) bind(c) integer :: N type(c_void), dimension(N) :: buffer end subroutine end interface
The actual must be of interoperable type. The argument association rules are the same as for "normal" arrays (for example, in the first case the association is with all of the elements of the actual, in the second with the first N elements, the actual can be of higher rank, etc.). In particular, if the actual is not contiguous, a contiguous copy will be made at the call site. The corresponding C routine must have a void* argument.
I like this suggestion as it kill two birds with one stone: 1. It removes the need for explicit CLOCs at the call site; 2. More importantly, it allows semantic information to be provided in the interface about the usage of the void* pointer in a way that the CLOC indirection doesn't allow. If the target attribute isn't present, the burden is on the C implementor not to keep the pointer squirreled away someplace. However, I'm not sure about the copying if non- contiguous. I think it would be better if the user were forced to provide a contiguous array (same as your Isend example below).
The important thing here, which will be objected to in J3, is that such a type(c_void) argument can only appear in bind(c) interfaces for an assumed-size or explicit-shape array (we can discuss extensions to assumed-shape arrays later...we are working on a TR for that). One cannot write an actual Fortran routine that has a dummy with no type since it is ill-defined what that means in Fortran. This is not the case with existing Fortran---interfaces merely repeat what can be written in Fortran and any BIND(C) routine may be written in either C or Fortran. Bill Long has proposed that the syntax BIND(C,LANG="C99") be used for the new type of interface blocks.
Why can't c_void be used like c_ptr is now so that the interface is bi-directional (implementable in either C or Fortran)?
For non-blocking sends, a pointer to the actual must be retained. This requires matching TARGET attributes on *both* the dummy and actual:
interface subroutine mpi_Isend(buffer...) bind(c) type(c_void), dimension(*), target :: buffer end subroutine end interface
integer(c_int), target :: x(100)
call mpi_Isend(x...)
For the call to actually work as expected, the actual must be contiguous (this is a new defined term in Fortran 2008 with some intrinsics to test is an array is contiguous) and have the target attribute, and must be of interoperable type.
An alternative is to construct a Fortran interface to MPI that actually uses the full power of Fortran, rather then using the (IMHO) very low-level and very annoying to use in practice C interface. For example, a call to MPI_Send includes redundant information about the type and size of the buffer. This info is known to the compiler from the actual argument and can be automatically provided by the compiler thus increasing safety and usability greatly. This is done in Fortran using array descriptors, which contain info about the TKR of the array.
My dream interface to MPI_Send would be something like:
interface subroutine mpi_send(buffer...) class(*), dimension() :: buffer end subroutine end interface
This would pass a descriptor to the C routine, which can then get the TKR info from it and call the low-level MPI routine.
This is more for the future. I think getting the simple "no TKR matching" is more focused and important for now.
I've discussed the more natural solution with Jeff Squyres and he agrees that this can be done later. We can provide a "real" Fortran binding much like the C++ one. Cheers, Craig
participants (1)
-
Craig Rasmussen