Hi,

My colleague tested MPI_IN_PLACE for MPI_ALLTOALL, MPI_ALLTOALLV,
and MPI_ALLTOALLW, which was implemented two months ago in Open MPI
trunk. And he found three bugs and created a patch.

Found bugs are:

(A) Missing MPI_IN_PLACE support in self COLL component

    The attached alltoall-self-inplace.c fails with MPI_ERR_ARG.
    self COLL component also must support MPI_IN_PLACE.

(B) Incorrect rcount[] index

    A trivial bug in the following code.

    for (i = 0, max_size = 0 ; i < size ; ++i) {
        size_t size = ext * rcounts[rank]; // should be rcounts[i]

        max_size = size > max_size ? size : max_size;
    }

    This causes SEGV or something.

(C) For MPI_ALLTOALLV, the unit of displacements is extent, not byte

    Though the unit of displacements is byte for MPI_ALLTOALLW,
    the unit of displacements is extent for MPI_ALLTOALLV.

    MPI-2.2 (page 171) says:

      The outcome is as if each process sent a message to every
      other process with,
        MPI_Send(sendbuf + sdispls[i] · extent(sendtype),
                 sendcounts[i], sendtype, i, ...),
      and received a message from every other process with a call to
        MPI_Recv(recvbuf + rdispls[i] · extent(recvtype),
                 recvcounts[i], recvtype, i, ...).

I attached his patch (alltoall-inplace.patch) to fix these three bugs.

Takahiro Kawashima,
MPI development team,
Fujitsu
Index: ompi/mca/coll/self/coll_self_alltoall.c
===================================================================
--- ompi/mca/coll/self/coll_self_alltoall.c	(revision 28967)
+++ ompi/mca/coll/self/coll_self_alltoall.c	(working copy)
@@ -37,6 +37,10 @@
                                  struct ompi_communicator_t *comm,
                                  mca_coll_base_module_t *module)
 {
+    if (MPI_IN_PLACE == sbuf) {
+        return MPI_SUCCESS;
+    }
+
     return ompi_datatype_sndrcv(sbuf, scount, sdtype,
                            rbuf, rcount, rdtype);
 }
Index: ompi/mca/coll/self/coll_self_alltoallv.c
===================================================================
--- ompi/mca/coll/self/coll_self_alltoallv.c	(revision 28967)
+++ ompi/mca/coll/self/coll_self_alltoallv.c	(working copy)
@@ -40,6 +40,11 @@
 {
     int err;        
     ptrdiff_t lb, rextent, sextent;
+
+    if (MPI_IN_PLACE == sbuf) {
+        return MPI_SUCCESS;
+    }
+
     err = ompi_datatype_get_extent(sdtype, &lb, &sextent);
     if (OMPI_SUCCESS != err) {
         return OMPI_ERROR;
Index: ompi/mca/coll/self/coll_self_alltoallw.c
===================================================================
--- ompi/mca/coll/self/coll_self_alltoallw.c	(revision 28967)
+++ ompi/mca/coll/self/coll_self_alltoallw.c	(working copy)
@@ -39,6 +39,11 @@
 {
     int err;        
     ptrdiff_t lb, rextent, sextent;
+
+    if (MPI_IN_PLACE == sbuf) {
+        return MPI_SUCCESS;
+    }
+
     err = ompi_datatype_get_extent(sdtypes[0], &lb, &sextent);
     if (OMPI_SUCCESS != err) {
         return OMPI_ERROR;
Index: ompi/mca/coll/basic/coll_basic_alltoallv.c
===================================================================
--- ompi/mca/coll/basic/coll_basic_alltoallv.c	(revision 28967)
+++ ompi/mca/coll/basic/coll_basic_alltoallv.c	(working copy)
@@ -56,7 +57,7 @@
     /* Find the largest receive amount */
     ompi_datatype_type_extent (rdtype, &ext);
     for (i = 0, max_size = 0 ; i < size ; ++i) {
-        size_t size = ext * rcounts[rank];
+        size_t size = ext * rcounts[i];
 
         max_size = size > max_size ? size : max_size;
     }
@@ -76,11 +77,11 @@
             if (i == rank && rcounts[j]) {
                 /* Copy the data into the temporary buffer */
                 err = ompi_datatype_copy_content_same_ddt (rdtype, rcounts[j],
-                                                           tmp_buffer, (char *) rbuf + rdisps[j]);
+                                                           tmp_buffer, (char *) rbuf + rdisps[j] * ext);
                 if (MPI_SUCCESS != err) { goto error_hndl; }
 
                 /* Exchange data with the peer */
-                err = MCA_PML_CALL(irecv ((char *) rbuf + rdisps[j], rcounts[j], rdtype,
+                err = MCA_PML_CALL(irecv ((char *) rbuf + rdisps[j] * ext, rcounts[j], rdtype,
                                           j, MCA_COLL_BASE_TAG_ALLTOALLV, comm, preq++));
                 if (MPI_SUCCESS != err) { goto error_hndl; }
 
@@ -91,11 +92,11 @@
             } else if (j == rank && rcounts[i]) {
                 /* Copy the data into the temporary buffer */
                 err = ompi_datatype_copy_content_same_ddt (rdtype, rcounts[i],
-                                                           tmp_buffer, (char *) rbuf + rdisps[i]);
+                                                           tmp_buffer, (char *) rbuf + rdisps[i] * ext);
                 if (MPI_SUCCESS != err) { goto error_hndl; }
 
                 /* Exchange data with the peer */
-                err = MCA_PML_CALL(irecv ((char *) rbuf + rdisps[i], rcounts[i], rdtype,
+                err = MCA_PML_CALL(irecv ((char *) rbuf + rdisps[i] * ext, rcounts[i], rdtype,
                                           i, MCA_COLL_BASE_TAG_ALLTOALLV, comm, preq++));
                 if (MPI_SUCCESS != err) { goto error_hndl; }
 
Index: ompi/mca/coll/basic/coll_basic_alltoallw.c
===================================================================
--- ompi/mca/coll/basic/coll_basic_alltoallw.c	(revision 28967)
+++ ompi/mca/coll/basic/coll_basic_alltoallw.c	(working copy)
@@ -56,7 +57,7 @@
     /* Find the largest receive amount */
     for (i = 0, max_size = 0 ; i < size ; ++i) {
         ompi_datatype_type_extent (rdtypes[i], &ext);
-        ext *= rcounts[rank];
+        ext *= rcounts[i];
 
         max_size = ext > max_size ? ext : max_size;
     }
Index: ompi/mca/coll/tuned/coll_tuned_alltoallv.c
===================================================================
--- ompi/mca/coll/tuned/coll_tuned_alltoallv.c	(revision 28967)
+++ ompi/mca/coll/tuned/coll_tuned_alltoallv.c	(working copy)
@@ -71,7 +72,7 @@
     /* Find the largest receive amount */
     ompi_datatype_type_extent (rdtype, &ext);
     for (i = 0, max_size = 0 ; i < size ; ++i) {
-        size_t size = ext * rcounts[rank];
+        size_t size = ext * rcounts[i];
 
         max_size = size > max_size ? size : max_size;
     }
@@ -91,11 +92,11 @@
             if (i == rank && rcounts[j]) {
                 /* Copy the data into the temporary buffer */
                 err = ompi_datatype_copy_content_same_ddt (rdtype, rcounts[j],
-                                                           tmp_buffer, (char *) rbuf + rdisps[j]);
+                                                           tmp_buffer, (char *) rbuf + rdisps[j] * ext);
                 if (MPI_SUCCESS != err) { goto error_hndl; }
 
                 /* Exchange data with the peer */
-                err = MCA_PML_CALL(irecv ((char *) rbuf + rdisps[j], rcounts[j], rdtype,
+                err = MCA_PML_CALL(irecv ((char *) rbuf + rdisps[j] * ext, rcounts[j], rdtype,
                                           j, MCA_COLL_BASE_TAG_ALLTOALLV, comm, preq++));
                 if (MPI_SUCCESS != err) { goto error_hndl; }
 
@@ -106,11 +107,11 @@
             } else if (j == rank && rcounts[i]) {
                 /* Copy the data into the temporary buffer */
                 err = ompi_datatype_copy_content_same_ddt (rdtype, rcounts[i],
-                                                           tmp_buffer, (char *) rbuf + rdisps[i]);
+                                                           tmp_buffer, (char *) rbuf + rdisps[i] * ext);
                 if (MPI_SUCCESS != err) { goto error_hndl; }
 
                 /* Exchange data with the peer */
-                err = MCA_PML_CALL(irecv ((char *) rbuf + rdisps[i], rcounts[i], rdtype,
+                err = MCA_PML_CALL(irecv ((char *) rbuf + rdisps[i] * ext, rcounts[i], rdtype,
                                           i, MCA_COLL_BASE_TAG_ALLTOALLV, comm, preq++));
                 if (MPI_SUCCESS != err) { goto error_hndl; }
 
#include <stdio.h>
#include <mpi.h>

int main(int argc, char *argv[])
{
    int buf;
    int counts[] = {1};
    int displs[] = {0};
    MPI_Datatype types[] = {MPI_INT};

    MPI_Init(&argc, &argv);

    buf = 1;
    MPI_Alltoall(MPI_IN_PLACE, 1, MPI_INT, &buf, 1, MPI_INT, MPI_COMM_SELF);
    if (buf != 1) {
        fprintf(stderr, "buf is not 1.\n");
    }

    buf = 1;
    MPI_Alltoallv(MPI_IN_PLACE, counts, displs, MPI_INT,
                  &buf, counts, displs, MPI_INT, MPI_COMM_SELF);
    if (buf != 1) {
        fprintf(stderr, "buf is not 1.\n");
    }

    buf = 1;
    MPI_Alltoallw(MPI_IN_PLACE, counts, displs, types,
                  &buf, counts, displs, types, MPI_COMM_SELF);
    if (buf != 1) {
        fprintf(stderr, "buf is not 1.\n");
    }

    MPI_Finalize();

    return 0;
}

Reply via email to