[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