Open MPI logo

Open MPI User's Mailing List Archives

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

Subject: Re: [OMPI users] Fortran MPI Struct with Allocatable Array
From: Eugene Loh (eugene.loh_at_[hidden])
Date: 2010-08-02 14:54:44


I can't give you a complete answer, but I think this is less an MPI question and more of a Fortran question.  The question is if you have a Fortran derived type, one of whose components is a POINTER, what does the data structure look like in linear memory?  I could imagine the answer is implementation dependent.  Anyhow, here is a sample, non-MPI, Fortran program that illustrates the question:

% cat b.f90
      type :: small
          integer, pointer :: array(:)
      end type small
      type(small) :: lala

      integer, pointer :: array(:)

      n = 20

      allocate( lala%array(n) )
      allocate(      array(n) )

      lala%array = (/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 /)
           array = (/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 /)

      call sub(lala)
      call sub(lala%array)
      call sub(     array)
end

subroutine sub(x)
      integer x(20)
      write(6,*) x
end
% f90 b.f90
% a.out
 599376 20 4 599372 1 20 -4197508 1 2561 0 33 0 0 0 0 0 0 0 0 0
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
%

So, your model of 20 consecutive words does not work if you pass the derived type.  It does work if you pass the POINTER component.  This is with Oracle (Sun) Studio Fortran.  Again, I can imagine the behavior depends on the Fortran compiler.

I suspect what's going on is that a POINTER is a complicated data structure that has all sorts of metadata in it, but if you pass a POINTER the compiler knows to pass the thing you're pointing to rather than the metadata itself.

Jeremy Roberts wrote:
I'm trying to parallelize a Fortran code with rather complicated derived types full of pointer arrays.  When I build the MPI type for sending, all the static components are sent, but the pointer arrays are not (and retain initial values).  I imagine this has to do with memory addresses when creating the MPI struct, but I have no idea how to fix it.

I've included a simple code illustrating my issue below.  Any suggestions?

program mpi_struct_example
      use mpi
      implicit none
      ! declarations
      type :: small
          real, pointer :: array(:)
      end type small
      type(small) :: lala
      integer :: stat, counts(1), types(1), ierr, iam, n=0, MPI_SMALL
      integer (kind=MPI_ADDRESS_KIND) :: displs(1)
      ! initialize MPI and get my rank
      call MPI_INIT( ierr )
      call MPI_COMM_RANK( MPI_COMM_WORLD, iam, ierr )
      n = 20
      allocate( lala%array(n) )
      lala%array = 2.0
      ! build block counts, displacements, and oldtypes
      counts     = (/n/)
      displs     = (/0/)
      types      = (/MPI_REAL/)
      ! make and commit new type
      call MPI_TYPE_CREATE_STRUCT( 1, counts, displs, types, MPI_SMALL, ierr )
      call MPI_TYPE_COMMIT( MPI_SMALL, ierr )
      if (iam .eq. 0) then
            ! reset the value of the array
            lala%array  = 1.0
            call MPI_SEND( lala, 1, MPI_SMALL, 1, 1, MPI_COMM_WORLD, ierr)       ! this doesn't work
            !call MPI_SEND( lala%array, n, MPI_REAL, 1, 1, MPI_COMM_WORLD, ierr) ! this does work
            write (*,*) "iam ",iam," and lala%array(1)  = ", lala%array(1)
      else
            call MPI_RECV( lala, 1, MPI_SMALL, 0, 1, MPI_COMM_WORLD, stat, ierr )       ! this doesn't work
            !call MPI_RECV( lala%array, n, MPI_REAL, 0, 1, MPI_COMM_WORLD, stat, ierr ) ! this does work
            write (*,*) "iam ",iam," and lala%array(1)  = ", lala%array(1), " ( should be 1.0)"
      end if
      call MPI_FINALIZE(ierr)
end program mpi_struct_example