/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ /* * (C) 2017 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */ #include "mpiimpl.h" #undef FUNCNAME #define FUNCNAME MPIR_Ialltoallw_sched_inter_pairwise_exchange #undef FCNAME #define FCNAME MPL_QUOTE(FUNCNAME) int MPIR_Ialltoallw_sched_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_Sched_t s) { /* Intercommunicator alltoallw. We use a pairwise exchange algorithm similar to the one used in intracommunicator alltoallw. Since the local and remote groups can be of different sizes, we first compute the max of local_group_size, remote_group_size. At step i, 0 <= i < max_size, each process receives from src = (rank - i + max_size) % max_size if src < remote_size, and sends to dst = (rank + i) % max_size if dst < remote_size. FIXME: change algorithm to match intracommunicator alltoallw */ int mpi_errno = MPI_SUCCESS; int local_size, remote_size, max_size, i; int src, dst, rank, sendcount, recvcount; char *sendaddr, *recvaddr; MPI_Datatype sendtype, recvtype; local_size = comm_ptr->local_size; remote_size = comm_ptr->remote_size; rank = comm_ptr->rank; /* Use pairwise exchange algorithm. */ max_size = MPL_MAX(local_size, remote_size); for (i = 0; i < max_size; i++) { src = (rank - i + max_size) % max_size; dst = (rank + i) % max_size; if (src >= remote_size) { src = MPI_PROC_NULL; recvaddr = NULL; recvcount = 0; recvtype = MPI_DATATYPE_NULL; } else { recvaddr = (char *) recvbuf + rdispls[src]; recvcount = recvcounts[src]; recvtype = recvtypes[src]; } if (dst >= remote_size) { dst = MPI_PROC_NULL; sendaddr = NULL; sendcount = 0; sendtype = MPI_DATATYPE_NULL; } else { sendaddr = (char *) sendbuf + sdispls[dst]; sendcount = sendcounts[dst]; sendtype = sendtypes[dst]; } mpi_errno = MPIR_Sched_send(sendaddr, sendcount, sendtype, dst, comm_ptr, s); if (mpi_errno) MPIR_ERR_POP(mpi_errno); /* sendrecv, no barrier here */ mpi_errno = MPIR_Sched_recv(recvaddr, recvcount, recvtype, src, comm_ptr, s); if (mpi_errno) MPIR_ERR_POP(mpi_errno); MPIR_SCHED_BARRIER(s); } fn_exit: return mpi_errno; fn_fail: goto fn_exit; }