1
1

Add support for MPI_IN_PLACE to MPI_Exscan. Required for MPI 2.2 compliance.

Reviewed by Jeff Squyres.  This fixes trac:2221.

This commit was SVN r25165.

The following Trac tickets were found above:
  Ticket 2221 --> https://svn.open-mpi.org/trac/ompi/ticket/2221
Этот коммит содержится в:
Rolf vandeVaart 2011-09-20 14:54:41 +00:00
родитель 51129cc2a8
Коммит 0749a220e8

Просмотреть файл

@ -9,6 +9,7 @@
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2011 NVIDIA Corporation. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -49,16 +50,18 @@ mca_coll_basic_exscan_intra(void *sbuf, void *rbuf, int count,
ptrdiff_t true_lb, true_extent, lb, extent;
char *free_buffer = NULL;
char *reduce_buffer = NULL;
char *source;
MPI_Request req = MPI_REQUEST_NULL;
/* Initialize. */
rank = ompi_comm_rank(comm);
size = ompi_comm_size(comm);
/* If we're rank 0, then we send our sbuf to the next rank */
/* For MPI_IN_PLACE, just adjust send buffer to point to
* receive buffer. */
if (MPI_IN_PLACE == sbuf) {
sbuf = rbuf;
}
/* If we're rank 0, then just send our sbuf to the next rank, and
* we are done. */
if (0 == rank) {
return MCA_PML_CALL(send(sbuf, count, dtype, rank + 1,
MCA_COLL_BASE_TAG_EXSCAN,
@ -66,8 +69,7 @@ mca_coll_basic_exscan_intra(void *sbuf, void *rbuf, int count,
}
/* If we're the last rank, then just receive the result from the
* prior rank */
* prior rank, and we are done. */
else if ((size - 1) == rank) {
return MCA_PML_CALL(recv(rbuf, count, dtype, rank - 1,
MCA_COLL_BASE_TAG_EXSCAN, comm,
@ -77,17 +79,8 @@ mca_coll_basic_exscan_intra(void *sbuf, void *rbuf, int count,
/* Otherwise, get the result from the prior rank, combine it with my
* data, and send it to the next rank */
/* Start the receive for the prior rank's answer */
err = MCA_PML_CALL(irecv(rbuf, count, dtype, rank - 1,
MCA_COLL_BASE_TAG_EXSCAN, comm, &req));
if (MPI_SUCCESS != err) {
goto error;
}
/* Get a temporary buffer to perform the reduction into. Rationale
* for malloc'ing this size is provided in coll_basic_reduce.c. */
ompi_datatype_get_extent(dtype, &lb, &extent);
ompi_datatype_get_true_extent(dtype, &true_lb, &true_extent);
@ -96,72 +89,29 @@ mca_coll_basic_exscan_intra(void *sbuf, void *rbuf, int count,
return OMPI_ERR_OUT_OF_RESOURCE;
}
reduce_buffer = free_buffer - lb;
err = ompi_datatype_copy_content_same_ddt(dtype, count,
reduce_buffer, (char*)sbuf);
if (ompi_op_is_commute(op)) {
/* If we're commutative, we can copy my sbuf into the reduction
* buffer before the receive completes */
err = ompi_datatype_copy_content_same_ddt(dtype, count,
reduce_buffer, (char*)sbuf);
if (MPI_SUCCESS != err) {
goto error;
}
/* Now setup the reduction */
source = (char*)rbuf;
/* Finally, wait for the receive to complete (so that we can do
* the reduction). */
err = ompi_request_wait(&req, MPI_STATUS_IGNORE);
if (MPI_SUCCESS != err) {
goto error;
}
} else {
/* Setup the reduction */
source = (char*)sbuf;
/* If we're not commutative, we have to wait for the receive to
* complete and then copy it into the reduce buffer */
err = ompi_request_wait(&req, MPI_STATUS_IGNORE);
if (MPI_SUCCESS != err) {
goto error;
}
err = ompi_datatype_copy_content_same_ddt(dtype, count,
reduce_buffer, (char*)rbuf);
if (MPI_SUCCESS != err) {
goto error;
}
/* Receive the reduced value from the prior rank */
err = MCA_PML_CALL(recv(rbuf, count, dtype, rank - 1,
MCA_COLL_BASE_TAG_EXSCAN, comm, MPI_STATUS_IGNORE));
if (MPI_SUCCESS != err) {
goto error;
}
/* Now reduce the received answer with my source into the answer
* that we send off to the next rank */
ompi_op_reduce(op, source, reduce_buffer, count, dtype);
/* Now reduce the prior rank's result with my source buffer. The source
* buffer had been previously copied into the temporary reduce_buffer. */
ompi_op_reduce(op, rbuf, reduce_buffer, count, dtype);
/* Send my result off to the next rank */
err = MCA_PML_CALL(send(reduce_buffer, count, dtype, rank + 1,
MCA_COLL_BASE_TAG_EXSCAN,
MCA_PML_BASE_SEND_STANDARD, comm));
/* Error */
error:
free(free_buffer);
if (MPI_REQUEST_NULL != req) {
ompi_request_cancel(req);
ompi_request_wait(&req, MPI_STATUS_IGNORE);
}
/* All done */
return err;
}