MPI Forum Meetings logo

MPI Forum: mpi3-fortran Mailing List Archives

all MPI Forum: mpi3-fortran mailing list

Subject: Re: [MPI3 Fortran] MPI-2.1: Fortran 90 bindings
From: Jeff Squyres (jsquyres_at_[hidden])
Date: 2008-03-06 20:33:49


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