Blame src/mpi/coll/ialltoallw/ialltoallw_inter_pairwise_exchange.c

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