/* -*- 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" /* Algorithm: Linear Scatterv * * Since the array of sendcounts is valid only on the root, we cannot do a tree * algorithm without first communicating the sendcounts to other processes. * Therefore, we simply use a linear algorithm for the scatter, which takes * (p-1) steps versus lgp steps for the tree algorithm. The bandwidth * requirement is the same for both algorithms. * * Cost = (p-1).alpha + n.((p-1)/p).beta */ #undef FUNCNAME #define FUNCNAME MPIR_Iscatterv_sched_allcomm_linear #undef FCNAME #define FCNAME MPL_QUOTE(FUNCNAME) int MPIR_Iscatterv_sched_allcomm_linear(const void *sendbuf, const int sendcounts[], const int displs[], MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPIR_Comm * comm_ptr, MPIR_Sched_t s) { int mpi_errno = MPI_SUCCESS; int rank, comm_size; MPI_Aint extent; int i; rank = comm_ptr->rank; /* If I'm the root, then scatter */ if (((comm_ptr->comm_kind == MPIR_COMM_KIND__INTRACOMM) && (root == rank)) || ((comm_ptr->comm_kind == MPIR_COMM_KIND__INTERCOMM) && (root == MPI_ROOT))) { if (comm_ptr->comm_kind == MPIR_COMM_KIND__INTRACOMM) comm_size = comm_ptr->local_size; else comm_size = comm_ptr->remote_size; MPIR_Datatype_get_extent_macro(sendtype, extent); /* We need a check to ensure extent will fit in a * pointer. That needs extent * (max count) but we can't get * that without looping over the input data. This is at least * a minimal sanity check. Maybe add a global var since we do * loop over sendcount[] in MPI_Scatterv before calling * this? */ MPIR_Ensure_Aint_fits_in_pointer(MPIR_VOID_PTR_CAST_TO_MPI_AINT sendbuf + extent); for (i = 0; i < comm_size; i++) { if (sendcounts[i]) { if ((comm_ptr->comm_kind == MPIR_COMM_KIND__INTRACOMM) && (i == rank)) { if (recvbuf != MPI_IN_PLACE) { mpi_errno = MPIR_Sched_copy(((char *) sendbuf + displs[rank] * extent), sendcounts[rank], sendtype, recvbuf, recvcount, recvtype, s); if (mpi_errno) MPIR_ERR_POP(mpi_errno); } } else { mpi_errno = MPIR_Sched_send(((char *) sendbuf + displs[i] * extent), sendcounts[i], sendtype, i, comm_ptr, s); if (mpi_errno) MPIR_ERR_POP(mpi_errno); } } } } else if (root != MPI_PROC_NULL) { /* non-root nodes, and in the intercomm. case, non-root nodes on remote side */ if (recvcount) { mpi_errno = MPIR_Sched_recv(recvbuf, recvcount, recvtype, root, comm_ptr, s); if (mpi_errno) MPIR_ERR_POP(mpi_errno); } } fn_exit: return mpi_errno; fn_fail: goto fn_exit; }