Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fortran: MPI_Alltoallw/MPI_Ialltoallw using MPI_IN_PLACE do not ignore sendtypes #5459

Closed
geimer opened this issue Jul 20, 2018 · 17 comments
Closed

Comments

@geimer
Copy link

geimer commented Jul 20, 2018

According to the standard, MPI_Alltoallw and MPI_Ialltoallw should ignore the sendcounts, sdispls, and sendtypes arguments if sendbuf is MPI_IN_PLACE. Open MPI (tested with 3.0.0) takes this into account for sendcounts and sdispls, but not for sendtypes. This leads to a segmentation fault with the following test code:

PROGRAM main
    USE mpi
    IMPLICIT NONE

    INTEGER :: size
    INTEGER :: rank
    INTEGER :: ierr
    INTEGER :: i

    INTEGER, ALLOCATABLE :: recvbuf(:)
    INTEGER, ALLOCATABLE :: recvcounts(:)
    INTEGER, ALLOCATABLE :: recvdispls(:)
    INTEGER, ALLOCATABLE :: recvtypes(:)
    INTEGER, ALLOCATABLE :: NULL(:)

    CALL MPI_Init(ierr)
    CALL MPI_Comm_size(MPI_COMM_WORLD, size, ierr)
    CALL MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)

    ALLOCATE(recvbuf(size))
    ALLOCATE(recvcounts(size))
    ALLOCATE(recvdispls(size))
    ALLOCATE(recvtypes(size))
    DO i = 1, size
        recvcounts(i) = 1
        recvdispls(i) = i * (storage_size(recvbuf) / 8)
        recvtypes(i)  = MPI_INTEGER
        recvbuf(i)    = rank
    END DO

    CALL MPI_Alltoallw(MPI_IN_PLACE, NULL, NULL, NULL, &
                       recvbuf, recvcounts, recvdispls, recvtypes, &
                       MPI_COMM_WORLD, ierr)

    CALL MPI_Finalize(ierr)
END PROGRAM

It seems that the loops at

while (size > 0) {
c_sendtypes[size - 1] = PMPI_Type_f2c(sendtypes[size - 1]);
c_recvtypes[size - 1] = PMPI_Type_f2c(recvtypes[size - 1]);
--size;
}
and
while (size > 0) {
c_sendtypes[size - 1] = PMPI_Type_f2c(sendtypes[size - 1]);
c_recvtypes[size - 1] = PMPI_Type_f2c(recvtypes[size - 1]);
--size;
}
are the culprit.

@ggouaillardet
Copy link
Contributor

thanks for the bug report !

do you want to issue a PR by yourself ?
If not, I will be happy to fix this bug and credit you for reporting it.

@geimer
Copy link
Author

geimer commented Jul 21, 2018

Thinking about a potential solution, I'm not quite sure why the conversions of sendcounts and sdispls don't segfault. I don't see any handling of NULL or MPI_IN_PLACE in the OMPI_ARRAY_FINT_2_INT macro... Feels like a more general issue that might require a deeper understanding of how things are usually tackled in Open MPI. Or am I missing something here?

@ggouaillardet
Copy link
Contributor

there is no conversion when MPI_Fint and int have the same size (and this is the most common case), feel free to refer to the (#ifdef'ed) macro definition(s) in ompi/mpi/fortran/base/fint_2_int.h.

If you build Open MPI with 8 bytes integer (-i8 option with Intel compilers, -fdefault-integer-8 with GNU compilers), then it will very likely crash. Since c_sendcounts will be ignored, I think the easiest way is not to invoke OMPI_ARRAY_FINT_2_INT when MPI_IN_PLACE is used.

note you also need to fix ompi/mpi/fortran/mpif-h/[i]neighbor_alltoallw (even if MPI_IN_PLACE is not allowed here, this error case should not result in a crash, but should be passed and handled to PMPI_{In,N}eighbor_alltoallw().

you will also need to apply similar fixes to the persistent collectives extensions in ompi/mpiext/pcollreq/mpif-h

last but not least, your commits have to be signed-off in order to be accepted,
make sure you understand the implications (IANAL, at the very least, make sure your management
is OK with you contributing to Open MPI)

@geimer
Copy link
Author

geimer commented Jul 21, 2018

Ah, OK, I've missed that there are multiple definitions of OMPI_ARRAY_FINT_2_INT.

Regarding MPI_{In,N}eighbor_alltoallw: I'm not entirely sure I understand what you are suggesting. IMHO these functions aren't affected, as all arguments are significant on all ranks. And if one passes in an invalid pointer, the program is erroneous. I also quickly checked some other routines that need to do handle conversion on arrays (MPI_Waitall, MPI_Waitsome); they don't handle this case either.

@jsquyres jsquyres added the bug label Aug 3, 2018
@jsquyres jsquyres added this to the v4.0.0 milestone Aug 3, 2018
@jsquyres
Copy link
Member

jsquyres commented Aug 3, 2018

I didn't see a pull request go by -- did this get fixed?

@jsquyres
Copy link
Member

jsquyres commented Aug 3, 2018

Sorry -- I should clarify: we're making the v2.1.4rc in the immediate future (probably Monday). It will likely be the last release in the v2.1.x series. If we get a fix for this right quick, we might be able to include it in v2.1.4.

More releases are coming shortly after that (see https://github.com/open-mpi/ompi/milestones?direction=asc&sort=due_date&state=open), so the sooner we get a PR for this, the better.

@geimer
Copy link
Author

geimer commented Aug 3, 2018

@jsquyres I haven't found the time yet to work on a PR. And it is very unlikely that it will happen over the weekend (which starts for me in a couple of minutes)...

@jsquyres
Copy link
Member

jsquyres commented Aug 3, 2018

No worries -- have a great weekend!

(if this missed the v2.1.4 release, that's not a tragedy -- we can always slot it in the upcoming v3.0.x / v3.1.x / v4.0.0 releases)

@jsquyres
Copy link
Member

@geimer Were you ever able to make progress on this, perchance?

@geimer
Copy link
Author

geimer commented Sep 18, 2018

@jsquyres I got distracted by vacation ;-) And now I'm behind schedule on my primary project... In other words: I don't believe I can find the time to look into this in the near future. Sorry!

@gpaulsen
Copy link
Member

@geimer What is the status of this issue?

@geimer
Copy link
Author

geimer commented Jul 13, 2019

@gpaulsen The state on my side is still unchanged: I couldn't find time to work on this. Sorry. Note that I hit this issue just by accident - and since I'm a C/C++ programmer, Fortran stuff gets very low priority on my TODO list. That is, if you want to see this fixed anytime soon, I suggest that someone else takes care of it.

@ggouaillardet ggouaillardet self-assigned this Jul 13, 2019
ggouaillardet added a commit to ggouaillardet/ompi that referenced this issue Jul 13, 2019
 - ignore sendcounts, sendispls and sendtypes arguments when MPI_IN_PLACE is used
 - use the right size when an inter-communicator is used.

Thanks Markus Geimer for reporting this.

Refs. open-mpi#5459

Signed-off-by: Gilles Gouaillardet <gilles@rist.or.jp>
@ggouaillardet
Copy link
Contributor

@geimer i fixed this in #6813. Meanwhile, you can manually download and apply the patch at https://github.com/open-mpi/ompi/pull/6813.patch

ggouaillardet added a commit to ggouaillardet/ompi that referenced this issue Jul 13, 2019
 - ignore sendcounts, sendispls and sendtypes arguments when MPI_IN_PLACE is used
 - use the right size when an inter-communicator is used.

Thanks Markus Geimer for reporting this.

Refs. open-mpi#5459

Signed-off-by: Gilles Gouaillardet <gilles@rist.or.jp>
@ggouaillardet
Copy link
Contributor

note to myself :
MPI_Ialltoallw() and MPI_Ineighbor_alltoallw() mpif-h bindings are not correct since some parameters passed to the C bindings are free'd before the request completes.
A similar mechanism to #2154 can be implemented to solve this correctly.

ggouaillardet added a commit to ggouaillardet/ompi that referenced this issue Jul 24, 2019
 - ignore sendcounts, sendispls and sendtypes arguments when MPI_IN_PLACE is used
 - use the right size when an inter-communicator is used.

Thanks Markus Geimer for reporting this.

Refs. open-mpi#5459

Signed-off-by: Gilles Gouaillardet <gilles@rist.or.jp>

(cherry picked from commit open-mpi/ompi@cdaed89)
@gpaulsen
Copy link
Member

gpaulsen commented Nov 4, 2020

@ggouaillardet Hi. In #6813 (comment) (master only, not yet backported to v4.1.x, v4.0.x, or earlier), you mentioned that this is a bigger issue than you thought, and that you were working on a PR for release branches, but that it kept growing.

Could you summarize the status in this issue? Cherry-picking 6813 looks straight forward enough, but it sounds like that's just the tip of the iceberg. Thoughts?

@ggouaillardet
Copy link
Contributor

The commit can be backported, but does not address all the issues described in my previous comments:

  1. the MPI_Ialltoallw() Fortran binding explicitly dynamically allocates c_sendtypes and c_recvtypes, and might allocate under the hood c_sdispls, c_sendcounts, c_rdispls and c_recvcounts. These pointers are then passed to the C PMPI_Ialltoallw() binding and free'd right away. This is not correct since according to the standard, these pointers can only be free'd after the non blocking collective completes. I guess the persistent collectives have the same issue.
    In an other (large) PR, I added some mechanism to automatically free some data once a non blocking collective completes, similar mechanism could/should be used here.
    IIRC coll/libnbc does not access these pointers once ialltoallw() returns, so that could hide the bug.
  2. In the case of neighbor collectives, MPI_IN_PLACE is not a valid parameter. C bindings do check that and error with a user friendly error message. IIRC, the Fortran binding won't pass MPI_IN_PLACE, resulting into a non user friendly crash.

@hppritcha
Copy link
Member

fixed in v4.0.x via #6838. closing since we're not going to patch v3.1.x and v3.0.x

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants