Re: [MPI3 Fortran] MPI-2.1: Fortran 90 bindings
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
participants (1)
-
Jeff Squyres