[MPI3 Fortran] Fortran extra_state argument to MPIattributefunctions

Iain Bason Iain.Bason at Sun.COM
Thu May 28 08:55:20 CDT 2009

On 05/28/09 04:23, N.M. Maclaren wrote:
> On May 28 2009, Aleksandar Donev wrote:
>> Jeff Squyres wrote:
>>> I guess I should clarify here -- the intent for this parameter is 
>>> not to be interoperable with C.
>> I understand, but you were asking about a "neutral" type that can be 
>> "cast" into the "right type". The C void* can be used for such 
>> things, but Fortran does not have an equivalent, at least not unless 
>> you count Fortran 2003 object oriented features (where there are 
>> "unlimited polymorphic pointers" which provide a type-safe "castable" 
>> generic pointer). This is why using C interoperability is good 
>> here---it is legal and does what you want.
> While this is true, a reasonable alternative approach (which is what is
> actually done by must current implementations for MPI handles) is to use
> an integer token in Fortran, and have the using routines decode it.  That
> isn't exactly an unusual strategy in Fortran, and was common in the many
> compilers written in Fortran 66. 

There are two issues here:

1. How best to pass a void* equivalent type to an MPI routine; and

2. How to deal with the aliasing issues that arise due to callback routines.

I believe Nick and Aleksandar have addressed #1, but I don't think they 
have addressed
#2.  Look at this example program, which uses Cray pointers and LOC to deal
with issue #1:

      include 'mpif.h'

      implicit none
      external copyfunc, delfunc

      integer err, kvh, comm
      real extra(10)

      call mpi_init(err)

      extra(2:10) = 6
      extra(1) = 5
      call mpi_comm_create_keyval(copyfunc, delfunc, kvh, loc(extra),
     +     err)
      call mpi_comm_set_attr(mpi_comm_world, kvh, 1, err)
      call mpi_comm_dup(mpi_comm_world, comm, err)
      extra = 7
      call mpi_comm_free(comm, err)

      call mpi_finalize(err)

      subroutine copyfunc(oldcomm, kv, extra, val_in, val_out, flag,
     +     ierror)

      include 'mpif.h'

      implicit none
      integer oldcomm, kv, ierror
      integer(kind=mpi_address_kind) val_in, val_out
      real extra_val(10)
      pointer (extra, extra_val)
      logical flag

      print *, extra_val
      flag = 1
      val_out = val_in
      ierror = mpi_success
      end subroutine

      subroutine delfunc(oldcomm, kv, val, extra, ierror)

      include 'mpif.h'

      implicit none
      integer oldcomm, kv, ierror
      integer(kind=mpi_address_kind) val
      real extra_val(10)
      pointer (extra, extra_val)

      print *, extra_val
      ierror = mpi_success
      end subroutine

Now copyfunc is called from the MPI library during evaluation of the
call to mpi_comm_dup, while delfunc is called during the evaluation
of the call to mpi_comm_free.  Those routines are accessing extra, which
is a local variable in the main program.  The program has passed the
address of extra to mpi_comm_create_keyval, but not to mpi_comm_dup
or mpi_comm_free.

A compiler may choose to delete "extra = 7" as dead code, or to move
the assignment before the call to mpi_comm_dup or after the call to
mpi_comm_free. Or the compiler may decide that use of "loc(extra)"
means that extra may be accessed or modified by any call, and thus
be conservative about its optimizations.  The standard doesn't provide
any guidance, since LOC and Cray pointers are outside the standard.

Is there a standard-conformant way to indicate that extra may be accessed
or modified during the calls to mpi_comm_dup and mpi_comm_free?


More information about the mpiwg-fortran mailing list