|
Packit Service |
c5cf8c |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* (C) 2012 by Argonne National Laboratory.
|
|
Packit Service |
c5cf8c |
* See COPYRIGHT in top-level directory.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include "mpiimpl.h"
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Local utility macro: takes an two args and sets lvalue cr_ equal to the rank
|
|
Packit Service |
c5cf8c |
* in comm_ptr corresponding to rvalue gr_ */
|
|
Packit Service |
c5cf8c |
#define to_comm_rank(cr_, gr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int gr_tmp_ = (gr_); \
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Group_translate_ranks_impl(group_ptr, 1, &(gr_tmp_), comm_ptr->local_group, &(cr_)); \
|
|
Packit Service |
c5cf8c |
if (mpi_errno) MPIR_ERR_POP(mpi_errno); \
|
|
Packit Service |
c5cf8c |
MPIR_Assert((cr_) != MPI_UNDEFINED); \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPII_Allreduce_group_intra
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPII_Allreduce_group_intra(void *sendbuf, void *recvbuf, int count,
|
|
Packit Service |
c5cf8c |
MPI_Datatype datatype, MPI_Op op, MPIR_Comm * comm_ptr,
|
|
Packit Service |
c5cf8c |
MPIR_Group * group_ptr, int tag, MPIR_Errflag_t * errflag)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPI_Aint type_size;
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
int mpi_errno_ret = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
/* newrank is a rank in group_ptr */
|
|
Packit Service |
c5cf8c |
int mask, dst, is_commutative, pof2, newrank, rem, newdst, i,
|
|
Packit Service |
c5cf8c |
send_idx, recv_idx, last_idx, send_cnt, recv_cnt, *cnts, *disps;
|
|
Packit Service |
c5cf8c |
MPI_Aint true_extent, true_lb, extent;
|
|
Packit Service |
c5cf8c |
void *tmp_buf;
|
|
Packit Service |
c5cf8c |
int group_rank, group_size;
|
|
Packit Service |
c5cf8c |
int cdst, csrc;
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_DECL(3);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
group_rank = group_ptr->rank;
|
|
Packit Service |
c5cf8c |
group_size = group_ptr->size;
|
|
Packit Service |
c5cf8c |
MPIR_ERR_CHKANDJUMP(group_rank == MPI_UNDEFINED, mpi_errno, MPI_ERR_OTHER, "**rank");
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
is_commutative = MPIR_Op_is_commutative(op);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* need to allocate temporary buffer to store incoming data */
|
|
Packit Service |
c5cf8c |
MPIR_Type_get_true_extent_impl(datatype, &true_lb, &true_extent);
|
|
Packit Service |
c5cf8c |
MPIR_Datatype_get_extent_macro(datatype, extent);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Ensure_Aint_fits_in_pointer(count * MPL_MAX(extent, true_extent));
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_MALLOC(tmp_buf, void *, count * (MPL_MAX(extent, true_extent)), mpi_errno,
|
|
Packit Service |
c5cf8c |
"temporary buffer", MPL_MEM_BUFFER);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* adjust for potential negative lower bound in datatype */
|
|
Packit Service |
c5cf8c |
tmp_buf = (void *) ((char *) tmp_buf - true_lb);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* copy local data into recvbuf */
|
|
Packit Service |
c5cf8c |
if (sendbuf != MPI_IN_PLACE) {
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Localcopy(sendbuf, count, datatype, recvbuf, count, datatype);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Datatype_get_size_macro(datatype, type_size);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* get nearest power-of-two less than or equal to comm_size */
|
|
Packit Service |
c5cf8c |
pof2 = MPL_pof2(group_size);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
rem = group_size - pof2;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* In the non-power-of-two case, all even-numbered
|
|
Packit Service |
c5cf8c |
* processes of rank < 2*rem send their data to
|
|
Packit Service |
c5cf8c |
* (rank+1). These even-numbered processes no longer
|
|
Packit Service |
c5cf8c |
* participate in the algorithm until the very end. The
|
|
Packit Service |
c5cf8c |
* remaining processes form a nice power-of-two. */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (group_rank < 2 * rem) {
|
|
Packit Service |
c5cf8c |
if (group_rank % 2 == 0) { /* even */
|
|
Packit Service |
c5cf8c |
to_comm_rank(cdst, group_rank + 1);
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIC_Send(recvbuf, count, datatype, cdst, tag, comm_ptr, errflag);
|
|
Packit Service |
c5cf8c |
if (mpi_errno) {
|
|
Packit Service |
c5cf8c |
/* for communication errors, just record the error but continue */
|
|
Packit Service |
c5cf8c |
*errflag =
|
|
Packit Service |
c5cf8c |
MPIX_ERR_PROC_FAILED ==
|
|
Packit Service |
c5cf8c |
MPIR_ERR_GET_CLASS(mpi_errno) ? MPIR_ERR_PROC_FAILED : MPIR_ERR_OTHER;
|
|
Packit Service |
c5cf8c |
MPIR_ERR_SET(mpi_errno, *errflag, "**fail");
|
|
Packit Service |
c5cf8c |
MPIR_ERR_ADD(mpi_errno_ret, mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* temporarily set the rank to -1 so that this
|
|
Packit Service |
c5cf8c |
* process does not pariticipate in recursive
|
|
Packit Service |
c5cf8c |
* doubling */
|
|
Packit Service |
c5cf8c |
newrank = -1;
|
|
Packit Service |
c5cf8c |
} else { /* odd */
|
|
Packit Service |
c5cf8c |
to_comm_rank(csrc, group_rank - 1);
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIC_Recv(tmp_buf, count,
|
|
Packit Service |
c5cf8c |
datatype, csrc, tag, comm_ptr, MPI_STATUS_IGNORE, errflag);
|
|
Packit Service |
c5cf8c |
if (mpi_errno) {
|
|
Packit Service |
c5cf8c |
/* for communication errors, just record the error but continue */
|
|
Packit Service |
c5cf8c |
*errflag =
|
|
Packit Service |
c5cf8c |
MPIX_ERR_PROC_FAILED ==
|
|
Packit Service |
c5cf8c |
MPIR_ERR_GET_CLASS(mpi_errno) ? MPIR_ERR_PROC_FAILED : MPIR_ERR_OTHER;
|
|
Packit Service |
c5cf8c |
MPIR_ERR_SET(mpi_errno, *errflag, "**fail");
|
|
Packit Service |
c5cf8c |
MPIR_ERR_ADD(mpi_errno_ret, mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* do the reduction on received data. since the
|
|
Packit Service |
c5cf8c |
* ordering is right, it doesn't matter whether
|
|
Packit Service |
c5cf8c |
* the operation is commutative or not. */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Reduce_local(tmp_buf, recvbuf, count, datatype, op);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* change the rank */
|
|
Packit Service |
c5cf8c |
newrank = group_rank / 2;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else /* rank >= 2*rem */
|
|
Packit Service |
c5cf8c |
newrank = group_rank - rem;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* If op is user-defined or count is less than pof2, use
|
|
Packit Service |
c5cf8c |
* recursive doubling algorithm. Otherwise do a reduce-scatter
|
|
Packit Service |
c5cf8c |
* followed by allgather. (If op is user-defined,
|
|
Packit Service |
c5cf8c |
* derived datatypes are allowed and the user could pass basic
|
|
Packit Service |
c5cf8c |
* datatypes on one process and derived on another as long as
|
|
Packit Service |
c5cf8c |
* the type maps are the same. Breaking up derived
|
|
Packit Service |
c5cf8c |
* datatypes to do the reduce-scatter is tricky, therefore
|
|
Packit Service |
c5cf8c |
* using recursive doubling in that case.) */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (newrank != -1) {
|
|
Packit Service |
c5cf8c |
if ((count * type_size <= MPIR_CVAR_ALLREDUCE_SHORT_MSG_SIZE) ||
|
|
Packit Service |
c5cf8c |
(HANDLE_GET_KIND(op) != HANDLE_KIND_BUILTIN) || (count < pof2)) {
|
|
Packit Service |
c5cf8c |
/* use recursive doubling */
|
|
Packit Service |
c5cf8c |
mask = 0x1;
|
|
Packit Service |
c5cf8c |
while (mask < pof2) {
|
|
Packit Service |
c5cf8c |
newdst = newrank ^ mask;
|
|
Packit Service |
c5cf8c |
/* find real rank of dest */
|
|
Packit Service |
c5cf8c |
dst = (newdst < rem) ? newdst * 2 + 1 : newdst + rem;
|
|
Packit Service |
c5cf8c |
to_comm_rank(cdst, dst);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Send the most current data, which is in recvbuf. Recv
|
|
Packit Service |
c5cf8c |
* into tmp_buf */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIC_Sendrecv(recvbuf, count, datatype,
|
|
Packit Service |
c5cf8c |
cdst, tag, tmp_buf,
|
|
Packit Service |
c5cf8c |
count, datatype, cdst,
|
|
Packit Service |
c5cf8c |
tag, comm_ptr, MPI_STATUS_IGNORE, errflag);
|
|
Packit Service |
c5cf8c |
if (mpi_errno) {
|
|
Packit Service |
c5cf8c |
/* for communication errors, just record the error but continue */
|
|
Packit Service |
c5cf8c |
*errflag =
|
|
Packit Service |
c5cf8c |
MPIX_ERR_PROC_FAILED ==
|
|
Packit Service |
c5cf8c |
MPIR_ERR_GET_CLASS(mpi_errno) ? MPIR_ERR_PROC_FAILED : MPIR_ERR_OTHER;
|
|
Packit Service |
c5cf8c |
MPIR_ERR_SET(mpi_errno, *errflag, "**fail");
|
|
Packit Service |
c5cf8c |
MPIR_ERR_ADD(mpi_errno_ret, mpi_errno);
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* tmp_buf contains data received in this step.
|
|
Packit Service |
c5cf8c |
* recvbuf contains data accumulated so far */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (is_commutative || (dst < group_rank)) {
|
|
Packit Service |
c5cf8c |
/* op is commutative OR the order is already right */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Reduce_local(tmp_buf, recvbuf, count, datatype, op);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* op is noncommutative and the order is not right */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Reduce_local(recvbuf, tmp_buf, count, datatype, op);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* copy result back into recvbuf */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Localcopy(tmp_buf, count, datatype,
|
|
Packit Service |
c5cf8c |
recvbuf, count, datatype);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
mask <<= 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
else {
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* do a reduce-scatter followed by allgather */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* for the reduce-scatter, calculate the count that
|
|
Packit Service |
c5cf8c |
* each process receives and the displacement within
|
|
Packit Service |
c5cf8c |
* the buffer */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_MALLOC(cnts, int *, pof2 * sizeof(int), mpi_errno, "counts",
|
|
Packit Service |
c5cf8c |
MPL_MEM_BUFFER);
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_MALLOC(disps, int *, pof2 * sizeof(int), mpi_errno, "displacements",
|
|
Packit Service |
c5cf8c |
MPL_MEM_BUFFER);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (i = 0; i < (pof2 - 1); i++)
|
|
Packit Service |
c5cf8c |
cnts[i] = count / pof2;
|
|
Packit Service |
c5cf8c |
cnts[pof2 - 1] = count - (count / pof2) * (pof2 - 1);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (pof2)
|
|
Packit Service |
c5cf8c |
disps[0] = 0;
|
|
Packit Service |
c5cf8c |
for (i = 1; i < pof2; i++)
|
|
Packit Service |
c5cf8c |
disps[i] = disps[i - 1] + cnts[i - 1];
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mask = 0x1;
|
|
Packit Service |
c5cf8c |
send_idx = recv_idx = 0;
|
|
Packit Service |
c5cf8c |
last_idx = pof2;
|
|
Packit Service |
c5cf8c |
while (mask < pof2) {
|
|
Packit Service |
c5cf8c |
newdst = newrank ^ mask;
|
|
Packit Service |
c5cf8c |
/* find real rank of dest */
|
|
Packit Service |
c5cf8c |
dst = (newdst < rem) ? newdst * 2 + 1 : newdst + rem;
|
|
Packit Service |
c5cf8c |
to_comm_rank(cdst, dst);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
send_cnt = recv_cnt = 0;
|
|
Packit Service |
c5cf8c |
if (newrank < newdst) {
|
|
Packit Service |
c5cf8c |
send_idx = recv_idx + pof2 / (mask * 2);
|
|
Packit Service |
c5cf8c |
for (i = send_idx; i < last_idx; i++)
|
|
Packit Service |
c5cf8c |
send_cnt += cnts[i];
|
|
Packit Service |
c5cf8c |
for (i = recv_idx; i < send_idx; i++)
|
|
Packit Service |
c5cf8c |
recv_cnt += cnts[i];
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
recv_idx = send_idx + pof2 / (mask * 2);
|
|
Packit Service |
c5cf8c |
for (i = send_idx; i < recv_idx; i++)
|
|
Packit Service |
c5cf8c |
send_cnt += cnts[i];
|
|
Packit Service |
c5cf8c |
for (i = recv_idx; i < last_idx; i++)
|
|
Packit Service |
c5cf8c |
recv_cnt += cnts[i];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Send data from recvbuf. Recv into tmp_buf */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIC_Sendrecv((char *) recvbuf +
|
|
Packit Service |
c5cf8c |
disps[send_idx] * extent,
|
|
Packit Service |
c5cf8c |
send_cnt, datatype,
|
|
Packit Service |
c5cf8c |
cdst, tag,
|
|
Packit Service |
c5cf8c |
(char *) tmp_buf +
|
|
Packit Service |
c5cf8c |
disps[recv_idx] * extent,
|
|
Packit Service |
c5cf8c |
recv_cnt, datatype, cdst,
|
|
Packit Service |
c5cf8c |
tag, comm_ptr, MPI_STATUS_IGNORE, errflag);
|
|
Packit Service |
c5cf8c |
if (mpi_errno) {
|
|
Packit Service |
c5cf8c |
/* for communication errors, just record the error but continue */
|
|
Packit Service |
c5cf8c |
*errflag =
|
|
Packit Service |
c5cf8c |
MPIX_ERR_PROC_FAILED ==
|
|
Packit Service |
c5cf8c |
MPIR_ERR_GET_CLASS(mpi_errno) ? MPIR_ERR_PROC_FAILED : MPIR_ERR_OTHER;
|
|
Packit Service |
c5cf8c |
MPIR_ERR_SET(mpi_errno, *errflag, "**fail");
|
|
Packit Service |
c5cf8c |
MPIR_ERR_ADD(mpi_errno_ret, mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* tmp_buf contains data received in this step.
|
|
Packit Service |
c5cf8c |
* recvbuf contains data accumulated so far */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* This algorithm is used only for predefined ops
|
|
Packit Service |
c5cf8c |
* and predefined ops are always commutative. */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Reduce_local(((char *) tmp_buf + disps[recv_idx] * extent),
|
|
Packit Service |
c5cf8c |
((char *) recvbuf + disps[recv_idx] * extent),
|
|
Packit Service |
c5cf8c |
recv_cnt, datatype, op);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* update send_idx for next iteration */
|
|
Packit Service |
c5cf8c |
send_idx = recv_idx;
|
|
Packit Service |
c5cf8c |
mask <<= 1;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* update last_idx, but not in last iteration
|
|
Packit Service |
c5cf8c |
* because the value is needed in the allgather
|
|
Packit Service |
c5cf8c |
* step below. */
|
|
Packit Service |
c5cf8c |
if (mask < pof2)
|
|
Packit Service |
c5cf8c |
last_idx = recv_idx + pof2 / mask;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* now do the allgather */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mask >>= 1;
|
|
Packit Service |
c5cf8c |
while (mask > 0) {
|
|
Packit Service |
c5cf8c |
newdst = newrank ^ mask;
|
|
Packit Service |
c5cf8c |
/* find real rank of dest */
|
|
Packit Service |
c5cf8c |
dst = (newdst < rem) ? newdst * 2 + 1 : newdst + rem;
|
|
Packit Service |
c5cf8c |
to_comm_rank(cdst, dst);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
send_cnt = recv_cnt = 0;
|
|
Packit Service |
c5cf8c |
if (newrank < newdst) {
|
|
Packit Service |
c5cf8c |
/* update last_idx except on first iteration */
|
|
Packit Service |
c5cf8c |
if (mask != pof2 / 2)
|
|
Packit Service |
c5cf8c |
last_idx = last_idx + pof2 / (mask * 2);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
recv_idx = send_idx + pof2 / (mask * 2);
|
|
Packit Service |
c5cf8c |
for (i = send_idx; i < recv_idx; i++)
|
|
Packit Service |
c5cf8c |
send_cnt += cnts[i];
|
|
Packit Service |
c5cf8c |
for (i = recv_idx; i < last_idx; i++)
|
|
Packit Service |
c5cf8c |
recv_cnt += cnts[i];
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
recv_idx = send_idx - pof2 / (mask * 2);
|
|
Packit Service |
c5cf8c |
for (i = send_idx; i < last_idx; i++)
|
|
Packit Service |
c5cf8c |
send_cnt += cnts[i];
|
|
Packit Service |
c5cf8c |
for (i = recv_idx; i < send_idx; i++)
|
|
Packit Service |
c5cf8c |
recv_cnt += cnts[i];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIC_Sendrecv((char *) recvbuf +
|
|
Packit Service |
c5cf8c |
disps[send_idx] * extent,
|
|
Packit Service |
c5cf8c |
send_cnt, datatype,
|
|
Packit Service |
c5cf8c |
cdst, tag,
|
|
Packit Service |
c5cf8c |
(char *) recvbuf +
|
|
Packit Service |
c5cf8c |
disps[recv_idx] * extent,
|
|
Packit Service |
c5cf8c |
recv_cnt, datatype, cdst,
|
|
Packit Service |
c5cf8c |
tag, comm_ptr, MPI_STATUS_IGNORE, errflag);
|
|
Packit Service |
c5cf8c |
if (mpi_errno) {
|
|
Packit Service |
c5cf8c |
/* for communication errors, just record the error but continue */
|
|
Packit Service |
c5cf8c |
*errflag =
|
|
Packit Service |
c5cf8c |
MPIX_ERR_PROC_FAILED ==
|
|
Packit Service |
c5cf8c |
MPIR_ERR_GET_CLASS(mpi_errno) ? MPIR_ERR_PROC_FAILED : MPIR_ERR_OTHER;
|
|
Packit Service |
c5cf8c |
MPIR_ERR_SET(mpi_errno, *errflag, "**fail");
|
|
Packit Service |
c5cf8c |
MPIR_ERR_ADD(mpi_errno_ret, mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (newrank > newdst)
|
|
Packit Service |
c5cf8c |
send_idx = recv_idx;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mask >>= 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* In the non-power-of-two case, all odd-numbered
|
|
Packit Service |
c5cf8c |
* processes of rank < 2*rem send the result to
|
|
Packit Service |
c5cf8c |
* (rank-1), the ranks who didn't participate above. */
|
|
Packit Service |
c5cf8c |
if (group_rank < 2 * rem) {
|
|
Packit Service |
c5cf8c |
if (group_rank % 2) { /* odd */
|
|
Packit Service |
c5cf8c |
to_comm_rank(cdst, group_rank - 1);
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIC_Send(recvbuf, count, datatype, cdst, tag, comm_ptr, errflag);
|
|
Packit Service |
c5cf8c |
} else { /* even */
|
|
Packit Service |
c5cf8c |
to_comm_rank(csrc, group_rank + 1);
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIC_Recv(recvbuf, count,
|
|
Packit Service |
c5cf8c |
datatype, csrc, tag, comm_ptr, MPI_STATUS_IGNORE, errflag);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (mpi_errno) {
|
|
Packit Service |
c5cf8c |
/* for communication errors, just record the error but continue */
|
|
Packit Service |
c5cf8c |
*errflag =
|
|
Packit Service |
c5cf8c |
MPIX_ERR_PROC_FAILED ==
|
|
Packit Service |
c5cf8c |
MPIR_ERR_GET_CLASS(mpi_errno) ? MPIR_ERR_PROC_FAILED : MPIR_ERR_OTHER;
|
|
Packit Service |
c5cf8c |
MPIR_ERR_SET(mpi_errno, *errflag, "**fail");
|
|
Packit Service |
c5cf8c |
MPIR_ERR_ADD(mpi_errno_ret, mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_FREEALL();
|
|
Packit Service |
c5cf8c |
if (mpi_errno_ret)
|
|
Packit Service |
c5cf8c |
mpi_errno = mpi_errno_ret;
|
|
Packit Service |
c5cf8c |
else if (*errflag != MPIR_ERR_NONE)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_SET(mpi_errno, *errflag, "**coll_fail");
|
|
Packit Service |
c5cf8c |
return (mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPII_Allreduce_group
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPII_Allreduce_group(void *sendbuf, void *recvbuf, int count,
|
|
Packit Service |
c5cf8c |
MPI_Datatype datatype, MPI_Op op, MPIR_Comm * comm_ptr,
|
|
Packit Service |
c5cf8c |
MPIR_Group * group_ptr, int tag, MPIR_Errflag_t * errflag)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_ERR_CHKANDJUMP(comm_ptr->comm_kind != MPIR_COMM_KIND__INTRACOMM, mpi_errno, MPI_ERR_OTHER,
|
|
Packit Service |
c5cf8c |
"**commnotintra");
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno = MPII_Allreduce_group_intra(sendbuf, recvbuf, count, datatype,
|
|
Packit Service |
c5cf8c |
op, comm_ptr, group_ptr, tag, errflag);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|