[MPI3 Fortran] MPI-2.1: Fortran 90 bindings

Jeff Squyres jsquyres at cisco.com
Thu Mar 6 19:33:49 CST 2008


On Mar 6, 2008, at 4:33 PM, Harald Klimach wrote:

> OK, sorry I should have done this earlier!
> I just had a look into openmpi, and how it's done there, and found,
> that there already assumed size is used.

w00t.  I wouldn't have know that that was what it was called.  :-)

> Looking at the standard I found it is also everywhere talking of  
> assumed
> size only.
> For example in openmpi-1.2.5/ompi/mpi/f90/mpi_buffer_attach_f90.f90.sh
> a construct like this is used:
> for rank in $allranks
> do
>  case "$rank" in  0)  dim=''  ;  esac
>  case "$rank" in  1)  dim=', dimension(*)'  ;  esac
>  case "$rank" in  2)  dim=', dimension(1,*)'  ;  esac
>  case "$rank" in  3)  dim=', dimension(1,1,*)'  ;  esac
>  case "$rank" in  4)  dim=', dimension(1,1,1,*)'  ;  esac
>  case "$rank" in  5)  dim=', dimension(1,1,1,1,*)'  ;  esac
>  case "$rank" in  6)  dim=', dimension(1,1,1,1,1,*)'  ;  esac
>  case "$rank" in  7)  dim=', dimension(1,1,1,1,1,1,*)'  ;  esac
>
> The only 2 meaningful options are the first two. $rank = 0 provides  
> the
> possibility to provide the routine with a scalar. $rank = 1 enables  
> the
> routine to take an array of any rank.
> The rest is just not needed. At least to my understanding.

It did not work for us to *only* provide (*); we found that we had to  
list all the dimensions.  Here's a relatively simple example that  
shows the problem with both gfortran and ifort on my system:

------------------
[17:23] svbu-mpi:~/tmp/f90 % cat module.f90
module my_function_module

interface my_function

subroutine my_function_scalar(arg)
   integer, intent(in) :: arg
end subroutine my_function_scalar

subroutine my_function_1d(arg)
   integer, dimension(*), intent(in) :: arg
end subroutine my_function_1d

end interface my_function

end module my_function_module
[17:23] svbu-mpi:~/tmp/f90 % gfortran -c module.f90
[17:23] svbu-mpi:~/tmp/f90 % cat arrays.f90
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Subroutines
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
subroutine my_function_scalar(arg)
   implicit none
   integer, intent(in) :: arg
   print *, "This is the scalar my_function"
end subroutine my_function_scalar

subroutine my_function_1d(arg)
   implicit none
   integer, dimension(*), intent(in) :: arg
   print *, "This is the 1d my_function"
end subroutine my_function_1d

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! All good.  Now try to use them
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
program f90_is_confusing
   use my_function_module
   implicit none
   integer :: a
   integer, dimension(1) :: b
   integer, dimension(2,3) :: c

   call my_function(a)
   call my_function(b)
   call my_function(c)

end program f90_is_confusing

[17:23] svbu-mpi:~/tmp/f90 % gfortran arrays.f90 -I.
  In file arrays.f90:28

   call my_function(c)
                     1
Error: Generic subroutine 'my_function' at (1) is not an intrinsic  
subroutine
[17:23] svbu-mpi:~/tmp/f90 %
------------------

So it didn't allow calling my_function with a 2D array (c).  Just to  
make sure this is not a gfortran weird-ism, I tried compiling the same  
stuff with ifort:

------------------
[17:23] svbu-mpi:~/tmp/f90 % ifort --version
ifort (IFORT) 10.1 20071116
Copyright (C) 1985-2007 Intel Corporation.  All rights reserved.

[17:23] svbu-mpi:~/tmp/f90 % ifort module.f90 -c
[17:23] svbu-mpi:~/tmp/f90 % ifort arrays.f90 -I.
fortcom: Error: arrays.f90, line 28: There is no matching specific  
subroutine for this generic subroutine call.   [MY_FUNCTION]
   call my_function(c)
-------^
compilation aborted for arrays.f90 (code 1)
[17:23] svbu-mpi:~/tmp/f90 %
-------------------

This is why we have all the dimensions explicitly specified in Open MPI.

> I would even doubt, that the first option is really necessary, as the
> standard states buffer for MPI_BUFFER_ATTACH to be:
> <type> BUFFER(*)
> To my reading that would mean it has to be an array. From the options

I think we were just covering all possible bases with  
MPI_BUFFER_ATTACH -- you *could* specify a buffer of size 1.  But s/ 
MPI_BUFFER_ATTACH/MPI_SEND/ and the issue is the same (i.e., it does  
make sense to pass a scalar to MPI_SEND).

> above $rank = 1 would then be the only one, that is really needed. The
> MPI-2 standard is talking about this issue on page 285 in the  
> paragraph
> "Problems Due to Strong Typing". As I read it, it is expected to only
> use the array. The user can always just use an array of size 1.
> However it is very convenient to just put the scalar in the argument
> list ;)

Either way, the back-end C function gets a pointer.  So I think we  
were likely a) going above and beyond the spec, and b) fitting  
MPI_BUFFER_ATTACH into the same OMPI F90 infrastructure as everything  
else.

> So it certainly is a nice thing to have the additional interface (but
> requires to double the work by the implementor).
>
> Actually you could even an explicit shape array:
> subroutine MPI_BUFFER_ATTACH(buffer, size, ierror)
>  integer :: size, iError
>  integer :: buffer(size)
> end subroutine MPI_BUFFER_ATTACH
>
> and call it with any integer array, that fits into size. Just try it
> with the sample program I sent in my first mail ;). This would ensure
> that the actual argument for buffer isn't larger than size.

But the type is variable, right?  Hence, if you use an explicit size,  
the *real* size of the buffer (in bytes) is sizeof(type)*size.  The  
"size" parameter is supposed to be specified in bytes, not increments  
of type size.  So I don't think the above binding would yield correct  
results for non-character types.  Right?

> Regarding the functions with two choice parameters:
> Is there any function which actually would make it necessary to allow
> two different types?
> By a brief glance at the standard, I only found constructs like in
> MPI_Allreduce:
>
> MPI_ALLREDUCE(sendbuf, recvbuf, count, datatype, op, comm, ierror)
> <type> sendbuf(*), recvbuf(*)
> integer count, datatype, op, comm, ierror
>
> To my understanding this means, that sendbuf and recvbuf have to of  
> the
> same type. It won't make any sense in the programs logic otherwise
> anyway.

Actually, MPI explicitly allows you to mix-n-match the types.  :-\

> If they are really allowed to be of different types, I would expect
> them to be on two lines:
> <type> sendbuf(*)
> <type> recvbuf(*)
> But perhaps that's just a bad interpretation by me.
>
> No Fortran program should want to get different typed values then it
> sent.
>
> Are there really any MPI functions, where it is sensible to use two
> different types for the two choice parameters?

It's unfortunately not for us to say; the standard allows it, so we  
have to allow it (because *some* app out there is likely using it in a  
weird-o way that is valid for their situation).

Certainly, there are cases that are non-sensical (e.g., sending its  
and receiving floats), but you *could* send complexes and receive  
twice as many floats, and that would be fine.

-- 
Jeff Squyres
Cisco Systems




More information about the mpiwg-fortran mailing list