1 /*
2 * Copyright (C) by Argonne National Laboratory
3 * See COPYRIGHT in top-level directory
4 */
5
6 #include "mpiimpl.h"
7
8 /*
9 * Pairwise Exchange
10 *
11 * We use a pairwise exchange algorithm similar to the one used in
12 * intracommunicator alltoallw. Since the local and remote groups can
13 * be of different sizes, we first compute the max of
14 * local_group_size, remote_group_size. At step i, 0 <= i < max_size,
15 * each process receives from src = (rank - i + max_size) % max_size
16 * if src < remote_size, and sends to dst = (rank + i) % max_size if
17 * dst < remote_size.
18 *
19 * FIXME: change algorithm to match intracommunicator alltoallv
20 */
21
MPIR_Alltoallw_inter_pairwise_exchange(const void * sendbuf,const int sendcounts[],const int sdispls[],const MPI_Datatype sendtypes[],void * recvbuf,const int recvcounts[],const int rdispls[],const MPI_Datatype recvtypes[],MPIR_Comm * comm_ptr,MPIR_Errflag_t * errflag)22 int MPIR_Alltoallw_inter_pairwise_exchange(const void *sendbuf, const int sendcounts[],
23 const int sdispls[], const MPI_Datatype sendtypes[],
24 void *recvbuf, const int recvcounts[],
25 const int rdispls[], const MPI_Datatype recvtypes[],
26 MPIR_Comm * comm_ptr, MPIR_Errflag_t * errflag)
27 {
28 int local_size, remote_size, max_size, i;
29 int mpi_errno = MPI_SUCCESS;
30 int mpi_errno_ret = MPI_SUCCESS;
31 MPI_Status status;
32 int src, dst, rank, sendcount, recvcount;
33 char *sendaddr, *recvaddr;
34 MPI_Datatype sendtype, recvtype;
35
36 local_size = comm_ptr->local_size;
37 remote_size = comm_ptr->remote_size;
38 rank = comm_ptr->rank;
39
40 /* Use pairwise exchange algorithm. */
41 max_size = MPL_MAX(local_size, remote_size);
42 for (i = 0; i < max_size; i++) {
43 src = (rank - i + max_size) % max_size;
44 dst = (rank + i) % max_size;
45 if (src >= remote_size) {
46 src = MPI_PROC_NULL;
47 recvaddr = NULL;
48 recvcount = 0;
49 recvtype = MPI_DATATYPE_NULL;
50 } else {
51 recvaddr = (char *) recvbuf + rdispls[src];
52 recvcount = recvcounts[src];
53 recvtype = recvtypes[src];
54 }
55 if (dst >= remote_size) {
56 dst = MPI_PROC_NULL;
57 sendaddr = NULL;
58 sendcount = 0;
59 sendtype = MPI_DATATYPE_NULL;
60 } else {
61 sendaddr = (char *) sendbuf + sdispls[dst];
62 sendcount = sendcounts[dst];
63 sendtype = sendtypes[dst];
64 }
65
66 mpi_errno = MPIC_Sendrecv(sendaddr, sendcount, sendtype,
67 dst, MPIR_ALLTOALLW_TAG, recvaddr,
68 recvcount, recvtype, src,
69 MPIR_ALLTOALLW_TAG, comm_ptr, &status, errflag);
70 if (mpi_errno) {
71 /* for communication errors, just record the error but continue */
72 *errflag =
73 MPIX_ERR_PROC_FAILED ==
74 MPIR_ERR_GET_CLASS(mpi_errno) ? MPIR_ERR_PROC_FAILED : MPIR_ERR_OTHER;
75 MPIR_ERR_SET(mpi_errno, *errflag, "**fail");
76 MPIR_ERR_ADD(mpi_errno_ret, mpi_errno);
77 }
78 }
79 if (mpi_errno_ret)
80 mpi_errno = mpi_errno_ret;
81 else if (*errflag != MPIR_ERR_NONE)
82 MPIR_ERR_SET(mpi_errno, *errflag, "**coll_fail");
83 return mpi_errno;
84 }
85