Open MPI logo

Open MPI User's Mailing List Archives

  |   Home   |   Support   |   FAQ   |   all Open MPI User's mailing list

From: Michael Kluskens (mkluskens_at_[hidden])
Date: 2006-05-30 15:39:39


Looking at limitations of the following:

   --with-mpi-f90-size=SIZE
                           specify the types of functions in the
Fortran 90 MPI
                           module, where size is one of: trivial (MPI-2
                           F90-specific functions only), small
(trivial + all
                           MPI functions without choice buffers),
medium (small
                           + all MPI functions with one choice
buffer), large
                           (medium + all MPI functions with 2 choice
buffers,
                           but only when both buffers are the same type)

Not sure what "same type" was intended to mean here, if same type
than reasonable, but if same type and dimension (and as implemented)
then I can't see where any generic installation, i.e. more than one
user, could use --with-mpi-f90-size=large. If fact I found one case
where a bunch of the generated interfaces are a waste of space and a
really bad idea as far as I can tell.

------------------------------------------------------------------------
------------------------------------------------
subroutine MPI_Gather0DI4(sendbuf, sendcount, sendtype, recvbuf,
recvcount, &
         recvtype, root, comm, ierr)
   include 'mpif-common.h'
   integer*4, intent(in) :: sendbuf
   integer, intent(in) :: sendcount
   integer, intent(in) :: sendtype
   integer*4, intent(out) :: recvbuf
   integer, intent(in) :: recvcount
   integer, intent(in) :: recvtype
   integer, intent(in) :: root
   integer, intent(in) :: comm
   integer, intent(out) :: ierr
end subroutine MPI_Gather0DI4

Think about it, all processes are sending data back to root, if each
sends a single integer where does the second, third, fourth, etc.
integer go?
------------------------------------------------------------------------
------------------------------------------------

The interfaces for MPI_GATHER do not include the possibility that the
sendbuf is an integer and the recvbuffer is an integer array, for
example the following does not exist but seems legal or should be
legal (and should at the very least replace the above interface):
------------------------------------------------------------------------
------------------------------------------------
subroutine MPI_Gather01DI4(sendbuf, sendcount, sendtype, recvbuf,
recvcount, &
         recvtype, root, comm, ierr)
   include 'mpif-common.h'
   integer*4, intent(in) :: sendbuf
   integer, intent(in) :: sendcount
   integer, intent(in) :: sendtype
   integer*4, dimension(:), intent(out) :: recvbuf
   integer, intent(in) :: recvcount
   integer, intent(in) :: recvtype
   integer, intent(in) :: root
   integer, intent(in) :: comm
   integer, intent(out) :: ierr
end subroutine MPI_Gather01DI4
------------------------------------------------------------------------
------------------------------------------------

Also, consider that there may be no reason to restrict sendbuf and
recvbuf have the same number of dimensions, but it is reasonable to
expect sendbuf to have the same or less dimensions as recvbuf (except
both being a scalar seems unreasonable). This does complicate the
issue from an order (N+1) problem to an order (N+1)*(N+2)/2 problem,
where is N = 4 unless otherwise restricted, but should be doable and
certain functions should have the 0,0 case eliminated.

Testing OpenMPI 1.2a1r10111 (g95 on OS X 10.4.6), configured with "./
configure F77=g95 FC=g95 LDFLAGS=-lSystemStubs --with-mpi-f90-
size=large --enable-static"

------------
call MPI_GATHER(nn,1,MPI_INTEGER,nno,1,MPI_INTEGER,0,allmpi,ier)
                                                                         
  1
Error: Generic subroutine 'mpi_gather' at (1) is not consistent with
a specific subroutine interface
----------

I'm doing my development on four different machines each with a
different compiler and a different MPI library, one of those (not
OpenMPI) spotted that I had forgotten ierr so it definitely was
checking the interfaces but was able to handle this problem (and
quickly too). In my Fortran 90 experience I'm not aware of a better
way to handle these generic interfaces but I have not studied this
issue closely enough.

Below is my solution for the generating scripts for MPI_Gather for
F90 (also switched to --with-f90-max-array-dim=2). It might be
acceptable to reduce the combinations to just equal or one dimension
less (00,01,11,12,22) but I pushed the limits of my shell scripting
abilities.

Michael

---------- mpi-f90-interfaces.h.sh
#-----------------------------------------------------------------------
-

output_120() {
     if test "$output" = "0"; then
         return 0
     fi
     procedure=$1
     rank=$2
     rank2=$3
     type=$5
     type2=$6
     proc="$1$2$3D$4"
     cat <<EOF

subroutine ${proc}(sendbuf, sendcount, sendtype, recvbuf, recvcount, &
         recvtype, root, comm, ierr)
   include 'mpif-common.h'
   ${type}, intent(in) :: sendbuf
   integer, intent(in) :: sendcount
   integer, intent(in) :: sendtype
   ${type2}, intent(out) :: recvbuf
   integer, intent(in) :: recvcount
   integer, intent(in) :: recvtype
   integer, intent(in) :: root
   integer, intent(in) :: comm
   integer, intent(out) :: ierr
end subroutine ${proc}

EOF
}

start MPI_Gather large

for rank in $allranks
do
   case "$rank" in 0) dim='' ; esac
   case "$rank" in 1) dim=', dimension(:)' ; esac
   case "$rank" in 2) dim=', dimension(:,:)' ; esac
   case "$rank" in 3) dim=', dimension(:,:,:)' ; esac
   case "$rank" in 4) dim=', dimension(:,:,:,:)' ; esac
   case "$rank" in 5) dim=', dimension(:,:,:,:,:)' ; esac
   case "$rank" in 6) dim=', dimension(:,:,:,:,:,:)' ; esac
   case "$rank" in 7) dim=', dimension(:,:,:,:,:,:,:)' ; esac

   for rank2 in $allranks
   do
     case "$rank2" in 0) dim2='' ; esac
     case "$rank2" in 1) dim2=', dimension(:)' ; esac
     case "$rank2" in 2) dim2=', dimension(:,:)' ; esac
     case "$rank2" in 3) dim2=', dimension(:,:,:)' ; esac
     case "$rank2" in 4) dim2=', dimension(:,:,:,:)' ; esac
     case "$rank2" in 5) dim2=', dimension(:,:,:,:,:)' ; esac
     case "$rank2" in 6) dim2=', dimension(:,:,:,:,:,:)' ; esac
     case "$rank2" in 7) dim2=', dimension(:,:,:,:,:,:,:)' ; esac

     if [ ${rank2} != "0" ] && [ ${rank2} -ge ${rank} ]; then

     output_120 MPI_Gather ${rank} ${rank2} CH "character${dim}"
"character${dim2}"
     output_120 MPI_Gather ${rank} ${rank2} L "logical${dim}" "logical
${dim2}"
     for kind in $ikinds
     do
       output_120 MPI_Gather ${rank} ${rank2} I${kind} "integer*$
{kind}${dim}" "integer*${kind}${dim2}"
     done
     for kind in $rkinds
     do
       output_120 MPI_Gather ${rank} ${rank2} R${kind} "real*${kind}$
{dim}" "real*${kind}${dim2}"
     done
     for kind in $ckinds
     do
       output_120 MPI_Gather ${rank} ${rank2} C${kind} "complex*$
{kind}${dim}" "complex*${kind}${dim2}"
     done

     fi
   done
done
end MPI_Gather
----------
--- mpi_gather_f90.f90.sh
output() {
     procedure=$1
     rank=$2
     rank2=$3
     type=$5
     type2=$6
     proc="$1$2$3D$4"
     cat <<EOF

subroutine ${proc}(sendbuf, sendcount, sendtype, recvbuf, recvcount, &
         recvtype, root, comm, ierr)
   include "mpif-common.h"
   ${type}, intent(in) :: sendbuf
   integer, intent(in) :: sendcount
   integer, intent(in) :: sendtype
   ${type2}, intent(out) :: recvbuf
   integer, intent(in) :: recvcount
   integer, intent(in) :: recvtype
   integer, intent(in) :: root
   integer, intent(in) :: comm
   integer, intent(out) :: ierr
   call ${procedure}(sendbuf, sendcount, sendtype, recvbuf, recvcount, &
         recvtype, root, comm, ierr)
end subroutine ${proc}

EOF
}

for rank in $allranks
do
   case "$rank" in 0) dim='' ; esac
   case "$rank" in 1) dim=', dimension(:)' ; esac
   case "$rank" in 2) dim=', dimension(:,:)' ; esac
   case "$rank" in 3) dim=', dimension(:,:,:)' ; esac
   case "$rank" in 4) dim=', dimension(:,:,:,:)' ; esac
   case "$rank" in 5) dim=', dimension(:,:,:,:,:)' ; esac
   case "$rank" in 6) dim=', dimension(:,:,:,:,:,:)' ; esac
   case "$rank" in 7) dim=', dimension(:,:,:,:,:,:,:)' ; esac

   for rank2 in $allranks
   do
     case "$rank2" in 0) dim2='' ; esac
     case "$rank2" in 1) dim2=', dimension(:)' ; esac
     case "$rank2" in 2) dim2=', dimension(:,:)' ; esac
     case "$rank2" in 3) dim2=', dimension(:,:,:)' ; esac
     case "$rank2" in 4) dim2=', dimension(:,:,:,:)' ; esac
     case "$rank2" in 5) dim2=', dimension(:,:,:,:,:)' ; esac
     case "$rank2" in 6) dim2=', dimension(:,:,:,:,:,:)' ; esac
     case "$rank2" in 7) dim2=', dimension(:,:,:,:,:,:,:)' ; esac

     if [ ${rank2} != "0" ] && [ ${rank2} -ge ${rank} ]; then

       output MPI_Gather ${rank} ${rank2} CH "character${dim}"
"character${dim2}"
       output MPI_Gather ${rank} ${rank2} L "logical${dim}" "logical$
{dim2}"
       for kind in $ikinds
       do
         output MPI_Gather ${rank} ${rank2} I${kind} "integer*${kind}$
{dim}" "integer*${kind}${dim2}"
       done
       for kind in $rkinds
       do
         output MPI_Gather ${rank} ${rank2} R${kind} "real*${kind}$
{dim}" "real*${kind}${dim2}"
       done
       for kind in $ckinds
       do
         output MPI_Gather ${rank} ${rank2} C${kind} "complex*${kind}$
{dim}" "complex*${kind}${dim2}"
       done

     fi
   done
done