Blame src/mpi/coll/iallgather/iallgather.c

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *  (C) 2010 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
/*
Packit Service c5cf8c
=== BEGIN_MPI_T_CVAR_INFO_BLOCK ===
Packit Service c5cf8c
Packit Service c5cf8c
cvars:
Packit Service c5cf8c
    - name        : MPIR_CVAR_IALLGATHER_RECEXCH_KVAL
Packit Service c5cf8c
      category    : COLLECTIVE
Packit Service c5cf8c
      type        : int
Packit Service c5cf8c
      default     : 2
Packit Service c5cf8c
      class       : device
Packit Service c5cf8c
      verbosity   : MPI_T_VERBOSITY_USER_BASIC
Packit Service c5cf8c
      scope       : MPI_T_SCOPE_ALL_EQ
Packit Service c5cf8c
      description : >-
Packit Service c5cf8c
        k value for recursive exchange based iallgather
Packit Service c5cf8c
Packit Service c5cf8c
    - name        : MPIR_CVAR_IALLGATHER_BRUCKS_KVAL
Packit Service c5cf8c
      category    : COLLECTIVE
Packit Service c5cf8c
      type        : int
Packit Service c5cf8c
      default     : 2
Packit Service c5cf8c
      class       : device
Packit Service c5cf8c
      verbosity   : MPI_T_VERBOSITY_USER_BASIC
Packit Service c5cf8c
      scope       : MPI_T_SCOPE_ALL_EQ
Packit Service c5cf8c
      description : >-
Packit Service c5cf8c
        k value for radix in brucks based iallgather
Packit Service c5cf8c
Packit Service c5cf8c
    - name        : MPIR_CVAR_IALLGATHER_INTRA_ALGORITHM
Packit Service c5cf8c
      category    : COLLECTIVE
Packit Service c5cf8c
      type        : string
Packit Service c5cf8c
      default     : auto
Packit Service c5cf8c
      class       : device
Packit Service c5cf8c
      verbosity   : MPI_T_VERBOSITY_USER_BASIC
Packit Service c5cf8c
      scope       : MPI_T_SCOPE_ALL_EQ
Packit Service c5cf8c
      description : |-
Packit Service c5cf8c
        Variable to select iallgather algorithm
Packit Service c5cf8c
        auto               - Internal algorithm selection
Packit Service c5cf8c
        brucks             - Force brucks algorithm
Packit Service c5cf8c
        recursive_doubling - Force recursive doubling algorithm
Packit Service c5cf8c
        ring               - Force ring algorithm
Packit Service c5cf8c
        recexch_distance_doubling    - Force generic transport recursive exchange with neighbours doubling in distance in each phase
Packit Service c5cf8c
        recexch_distance_halving  - Force generic transport recursive exchange with neighbours halving in distance in each phase
Packit Service c5cf8c
        gentran_brucks     - Force generic transport based brucks algorithm
Packit Service c5cf8c
Packit Service c5cf8c
    - name        : MPIR_CVAR_IALLGATHER_INTER_ALGORITHM
Packit Service c5cf8c
      category    : COLLECTIVE
Packit Service c5cf8c
      type        : string
Packit Service c5cf8c
      default     : auto
Packit Service c5cf8c
      class       : device
Packit Service c5cf8c
      verbosity   : MPI_T_VERBOSITY_USER_BASIC
Packit Service c5cf8c
      scope       : MPI_T_SCOPE_ALL_EQ
Packit Service c5cf8c
      description : |-
Packit Service c5cf8c
        Variable to select iallgather algorithm
Packit Service c5cf8c
        auto                      - Internal algorithm selection
Packit Service c5cf8c
        local_gather_remote_bcast - Force local-gather-remote-bcast algorithm
Packit Service c5cf8c
Packit Service c5cf8c
    - name        : MPIR_CVAR_IALLGATHER_DEVICE_COLLECTIVE
Packit Service c5cf8c
      category    : COLLECTIVE
Packit Service c5cf8c
      type        : boolean
Packit Service c5cf8c
      default     : true
Packit Service c5cf8c
      class       : device
Packit Service c5cf8c
      verbosity   : MPI_T_VERBOSITY_USER_BASIC
Packit Service c5cf8c
      scope       : MPI_T_SCOPE_ALL_EQ
Packit Service c5cf8c
      description : >-
Packit Service c5cf8c
        If set to true, MPI_Iallgather will allow the device to override the
Packit Service c5cf8c
        MPIR-level collective algorithms. The device still has the
Packit Service c5cf8c
        option to call the MPIR-level algorithms manually.
Packit Service c5cf8c
        If set to false, the device-level iallgather function will not be
Packit Service c5cf8c
        called.
Packit Service c5cf8c
Packit Service c5cf8c
=== END_MPI_T_CVAR_INFO_BLOCK ===
Packit Service c5cf8c
*/
Packit Service c5cf8c
Packit Service c5cf8c
/* -- Begin Profiling Symbol Block for routine MPI_Iallgather */
Packit Service c5cf8c
#if defined(HAVE_PRAGMA_WEAK)
Packit Service c5cf8c
#pragma weak MPI_Iallgather = PMPI_Iallgather
Packit Service c5cf8c
#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
Packit Service c5cf8c
#pragma _HP_SECONDARY_DEF PMPI_Iallgather  MPI_Iallgather
Packit Service c5cf8c
#elif defined(HAVE_PRAGMA_CRI_DUP)
Packit Service c5cf8c
#pragma _CRI duplicate MPI_Iallgather as PMPI_Iallgather
Packit Service c5cf8c
#elif defined(HAVE_WEAK_ATTRIBUTE)
Packit Service c5cf8c
int MPI_Iallgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf,
Packit Service c5cf8c
                   int recvcount, MPI_Datatype recvtype, MPI_Comm comm, MPI_Request * request)
Packit Service c5cf8c
    __attribute__ ((weak, alias("PMPI_Iallgather")));
Packit Service c5cf8c
#endif
Packit Service c5cf8c
/* -- End Profiling Symbol Block */
Packit Service c5cf8c
Packit Service c5cf8c
/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
Packit Service c5cf8c
   the MPI routines */
Packit Service c5cf8c
#ifndef MPICH_MPI_FROM_PMPI
Packit Service c5cf8c
#undef MPI_Iallgather
Packit Service c5cf8c
#define MPI_Iallgather PMPI_Iallgather
Packit Service c5cf8c
Packit Service c5cf8c
/* This is the machine-independent implementation of allgather. The algorithm is:
Packit Service c5cf8c
Packit Service c5cf8c
   Algorithm: MPI_Allgather
Packit Service c5cf8c
Packit Service c5cf8c
   For short messages and non-power-of-two no. of processes, we use
Packit Service c5cf8c
   the algorithm from the Jehoshua Bruck et al IEEE TPDS Nov 97
Packit Service c5cf8c
   paper. It is a variant of the disemmination algorithm for
Packit Service c5cf8c
   barrier. It takes ceiling(lg p) steps.
Packit Service c5cf8c
Packit Service c5cf8c
   Cost = lgp.alpha + n.((p-1)/p).beta
Packit Service c5cf8c
   where n is total size of data gathered on each process.
Packit Service c5cf8c
Packit Service c5cf8c
   For short or medium-size messages and power-of-two no. of
Packit Service c5cf8c
   processes, we use the recursive doubling algorithm.
Packit Service c5cf8c
Packit Service c5cf8c
   Cost = lgp.alpha + n.((p-1)/p).beta
Packit Service c5cf8c
Packit Service c5cf8c
   TODO: On TCP, we may want to use recursive doubling instead of the Bruck
Packit Service c5cf8c
   algorithm in all cases because of the pairwise-exchange property of
Packit Service c5cf8c
   recursive doubling (see Benson et al paper in Euro PVM/MPI
Packit Service c5cf8c
   2003).
Packit Service c5cf8c
Packit Service c5cf8c
   It is interesting to note that either of the above algorithms for
Packit Service c5cf8c
   MPI_Allgather has the same cost as the tree algorithm for MPI_Gather!
Packit Service c5cf8c
Packit Service c5cf8c
   For long messages or medium-size messages and non-power-of-two
Packit Service c5cf8c
   no. of processes, we use a ring algorithm. In the first step, each
Packit Service c5cf8c
   process i sends its contribution to process i+1 and receives
Packit Service c5cf8c
   the contribution from process i-1 (with wrap-around). From the
Packit Service c5cf8c
   second step onwards, each process i forwards to process i+1 the
Packit Service c5cf8c
   data it received from process i-1 in the previous step. This takes
Packit Service c5cf8c
   a total of p-1 steps.
Packit Service c5cf8c
Packit Service c5cf8c
   Cost = (p-1).alpha + n.((p-1)/p).beta
Packit Service c5cf8c
Packit Service c5cf8c
   We use this algorithm instead of recursive doubling for long
Packit Service c5cf8c
   messages because we find that this communication pattern (nearest
Packit Service c5cf8c
   neighbor) performs twice as fast as recursive doubling for long
Packit Service c5cf8c
   messages (on Myrinet and IBM SP).
Packit Service c5cf8c
Packit Service c5cf8c
   Possible improvements:
Packit Service c5cf8c
Packit Service c5cf8c
   End Algorithm: MPI_Allgather
Packit Service c5cf8c
*/
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Iallgather_sched_intra_auto
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
int MPIR_Iallgather_sched_intra_auto(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
Packit Service c5cf8c
                                     void *recvbuf, int recvcount, MPI_Datatype recvtype,
Packit Service c5cf8c
                                     MPIR_Comm * comm_ptr, MPIR_Sched_t s)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
    int comm_size, recvtype_size;
Packit Service c5cf8c
    int tot_bytes;
Packit Service c5cf8c
Packit Service c5cf8c
    if (((sendcount == 0) && (sendbuf != MPI_IN_PLACE)) || (recvcount == 0))
Packit Service c5cf8c
        return MPI_SUCCESS;
Packit Service c5cf8c
Packit Service c5cf8c
    comm_size = comm_ptr->local_size;
Packit Service c5cf8c
Packit Service c5cf8c
    MPIR_Datatype_get_size_macro(recvtype, recvtype_size);
Packit Service c5cf8c
    tot_bytes = (MPI_Aint) recvcount *comm_size * recvtype_size;
Packit Service c5cf8c
Packit Service c5cf8c
    if ((tot_bytes < MPIR_CVAR_ALLGATHER_LONG_MSG_SIZE) && !(comm_size & (comm_size - 1))) {
Packit Service c5cf8c
        mpi_errno =
Packit Service c5cf8c
            MPIR_Iallgather_sched_intra_recursive_doubling(sendbuf, sendcount, sendtype, recvbuf,
Packit Service c5cf8c
                                                           recvcount, recvtype, comm_ptr, s);
Packit Service c5cf8c
    } else if (tot_bytes < MPIR_CVAR_ALLGATHER_SHORT_MSG_SIZE) {
Packit Service c5cf8c
        mpi_errno =
Packit Service c5cf8c
            MPIR_Iallgather_sched_intra_brucks(sendbuf, sendcount, sendtype, recvbuf, recvcount,
Packit Service c5cf8c
                                               recvtype, comm_ptr, s);
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        mpi_errno =
Packit Service c5cf8c
            MPIR_Iallgather_sched_intra_ring(sendbuf, sendcount, sendtype, recvbuf, recvcount,
Packit Service c5cf8c
                                             recvtype, comm_ptr, s);
Packit Service c5cf8c
    }
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
}
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Iallgather_sched_inter_auto
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
int MPIR_Iallgather_sched_inter_auto(const void *sendbuf, int sendcount,
Packit Service c5cf8c
                                     MPI_Datatype sendtype, void *recvbuf, int recvcount,
Packit Service c5cf8c
                                     MPI_Datatype recvtype, MPIR_Comm * comm_ptr, MPIR_Sched_t s)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
Packit Service c5cf8c
    mpi_errno = MPIR_Iallgather_sched_inter_local_gather_remote_bcast(sendbuf, sendcount,
Packit Service c5cf8c
                                                                      sendtype, recvbuf, recvcount,
Packit Service c5cf8c
                                                                      recvtype, comm_ptr, s);
Packit Service c5cf8c
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Iallgather_sched_impl
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
int MPIR_Iallgather_sched_impl(const void *sendbuf, int sendcount,
Packit Service c5cf8c
                               MPI_Datatype sendtype, void *recvbuf,
Packit Service c5cf8c
                               int recvcount, MPI_Datatype recvtype,
Packit Service c5cf8c
                               MPIR_Comm * comm_ptr, MPIR_Sched_t s)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
Packit Service c5cf8c
    if (comm_ptr->comm_kind == MPIR_COMM_KIND__INTRACOMM) {
Packit Service c5cf8c
        /* intracommunicator */
Packit Service c5cf8c
        switch (MPIR_Iallgather_intra_algo_choice) {
Packit Service c5cf8c
            case MPIR_IALLGATHER_INTRA_ALGO_BRUCKS:
Packit Service c5cf8c
                mpi_errno = MPIR_Iallgather_sched_intra_brucks(sendbuf, sendcount, sendtype,
Packit Service c5cf8c
                                                               recvbuf, recvcount, recvtype,
Packit Service c5cf8c
                                                               comm_ptr, s);
Packit Service c5cf8c
                break;
Packit Service c5cf8c
            case MPIR_IALLGATHER_INTRA_ALGO_RECURSIVE_DOUBLING:
Packit Service c5cf8c
                mpi_errno = MPIR_Iallgather_sched_intra_recursive_doubling(sendbuf, sendcount,
Packit Service c5cf8c
                                                                           sendtype, recvbuf,
Packit Service c5cf8c
                                                                           recvcount, recvtype,
Packit Service c5cf8c
                                                                           comm_ptr, s);
Packit Service c5cf8c
                break;
Packit Service c5cf8c
            case MPIR_IALLGATHER_INTRA_ALGO_RING:
Packit Service c5cf8c
                mpi_errno = MPIR_Iallgather_sched_intra_ring(sendbuf, sendcount, sendtype, recvbuf,
Packit Service c5cf8c
                                                             recvcount, recvtype, comm_ptr, s);
Packit Service c5cf8c
                break;
Packit Service c5cf8c
            case MPIR_IALLGATHER_INTRA_ALGO_AUTO:
Packit Service c5cf8c
                MPL_FALLTHROUGH;
Packit Service c5cf8c
            default:
Packit Service c5cf8c
                mpi_errno = MPIR_Iallgather_sched_intra_auto(sendbuf, sendcount, sendtype, recvbuf,
Packit Service c5cf8c
                                                             recvcount, recvtype, comm_ptr, s);
Packit Service c5cf8c
                break;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        /* intercommunicator */
Packit Service c5cf8c
        switch (MPIR_Iallgather_inter_algo_choice) {
Packit Service c5cf8c
            case MPIR_IALLGATHER_INTER_ALGO_LOCAL_GATHER_REMOTE_BCAST:
Packit Service c5cf8c
                mpi_errno =
Packit Service c5cf8c
                    MPIR_Iallgather_sched_inter_local_gather_remote_bcast(sendbuf, sendcount,
Packit Service c5cf8c
                                                                          sendtype, recvbuf,
Packit Service c5cf8c
                                                                          recvcount, recvtype,
Packit Service c5cf8c
                                                                          comm_ptr, s);
Packit Service c5cf8c
                break;
Packit Service c5cf8c
            case MPIR_IALLGATHER_INTER_ALGO_AUTO:
Packit Service c5cf8c
                MPL_FALLTHROUGH;
Packit Service c5cf8c
            default:
Packit Service c5cf8c
                mpi_errno = MPIR_Iallgather_sched_inter_auto(sendbuf, sendcount, sendtype,
Packit Service c5cf8c
                                                             recvbuf, recvcount, recvtype, comm_ptr,
Packit Service c5cf8c
                                                             s);
Packit Service c5cf8c
                break;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Iallgather_sched
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
int MPIR_Iallgather_sched(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf,
Packit Service c5cf8c
                          int recvcount, MPI_Datatype recvtype, MPIR_Comm * comm_ptr,
Packit Service c5cf8c
                          MPIR_Sched_t s)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
Packit Service c5cf8c
    if (MPIR_CVAR_IALLGATHER_DEVICE_COLLECTIVE && MPIR_CVAR_DEVICE_COLLECTIVES) {
Packit Service c5cf8c
        mpi_errno = MPID_Iallgather_sched(sendbuf, sendcount, sendtype, recvbuf, recvcount,
Packit Service c5cf8c
                                          recvtype, comm_ptr, s);
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        mpi_errno = MPIR_Iallgather_sched_impl(sendbuf, sendcount, sendtype, recvbuf, recvcount,
Packit Service c5cf8c
                                               recvtype, comm_ptr, s);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Iallgather_impl
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
int MPIR_Iallgather_impl(const void *sendbuf, int sendcount,
Packit Service c5cf8c
                         MPI_Datatype sendtype, void *recvbuf, int recvcount,
Packit Service c5cf8c
                         MPI_Datatype recvtype, MPIR_Comm * comm_ptr, MPIR_Request ** request)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
    int tag = -1;
Packit Service c5cf8c
    MPIR_Sched_t s = MPIR_SCHED_NULL;
Packit Service c5cf8c
Packit Service c5cf8c
    *request = NULL;
Packit Service c5cf8c
Packit Service c5cf8c
    /* If the user picks one of the transport-enabled algorithms, branch there
Packit Service c5cf8c
     * before going down to the MPIR_Sched-based algorithms. */
Packit Service c5cf8c
    /* TODO - Eventually the intention is to replace all of the
Packit Service c5cf8c
     * MPIR_Sched-based algorithms with transport-enabled algorithms, but that
Packit Service c5cf8c
     * will require sufficient performance testing and replacement algorithms. */
Packit Service c5cf8c
    if (comm_ptr->comm_kind == MPIR_COMM_KIND__INTRACOMM) {
Packit Service c5cf8c
        /* intracommunicator */
Packit Service c5cf8c
        switch (MPIR_Iallgather_intra_algo_choice) {
Packit Service c5cf8c
            case MPIR_IALLGATHER_INTRA_ALGO_GENTRAN_RECEXCH_DISTANCE_DOUBLING:
Packit Service c5cf8c
                mpi_errno =
Packit Service c5cf8c
                    MPIR_Iallgather_intra_recexch_distance_doubling(sendbuf, sendcount, sendtype,
Packit Service c5cf8c
                                                                    recvbuf, recvcount, recvtype,
Packit Service c5cf8c
                                                                    comm_ptr, request);
Packit Service c5cf8c
                if (mpi_errno)
Packit Service c5cf8c
                    MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
                goto fn_exit;
Packit Service c5cf8c
                break;
Packit Service c5cf8c
            case MPIR_IALLGATHER_INTRA_ALGO_GENTRAN_RECEXCH_DISTANCE_HALVING:
Packit Service c5cf8c
                mpi_errno =
Packit Service c5cf8c
                    MPIR_Iallgather_intra_recexch_distance_halving(sendbuf, sendcount, sendtype,
Packit Service c5cf8c
                                                                   recvbuf, recvcount, recvtype,
Packit Service c5cf8c
                                                                   comm_ptr, request);
Packit Service c5cf8c
                if (mpi_errno)
Packit Service c5cf8c
                    MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
                goto fn_exit;
Packit Service c5cf8c
                break;
Packit Service c5cf8c
            case MPIR_IALLGATHER_INTRA_ALGO_GENTRAN_BRUCKS:
Packit Service c5cf8c
                mpi_errno =
Packit Service c5cf8c
                    MPIR_Iallgather_intra_gentran_brucks(sendbuf, sendcount, sendtype, recvbuf,
Packit Service c5cf8c
                                                         recvcount, recvtype, comm_ptr, request);
Packit Service c5cf8c
                if (mpi_errno)
Packit Service c5cf8c
                    MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
                goto fn_exit;
Packit Service c5cf8c
                break;
Packit Service c5cf8c
            default:
Packit Service c5cf8c
                /* go down to the MPIR_Sched-based algorithms */
Packit Service c5cf8c
                break;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    mpi_errno = MPIR_Sched_next_tag(comm_ptr, &tag;;
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
    mpi_errno = MPIR_Sched_create(&s);
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
Packit Service c5cf8c
    mpi_errno =
Packit Service c5cf8c
        MPIR_Iallgather_sched(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm_ptr,
Packit Service c5cf8c
                              s);
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
Packit Service c5cf8c
    mpi_errno = MPIR_Sched_start(&s, comm_ptr, tag, request);
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
}
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Iallgather
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
int MPIR_Iallgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
Packit Service c5cf8c
                    void *recvbuf, int recvcount, MPI_Datatype recvtype,
Packit Service c5cf8c
                    MPIR_Comm * comm_ptr, MPIR_Request ** request)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
Packit Service c5cf8c
    if (MPIR_CVAR_IALLGATHER_DEVICE_COLLECTIVE && MPIR_CVAR_DEVICE_COLLECTIVES) {
Packit Service c5cf8c
        mpi_errno = MPID_Iallgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype,
Packit Service c5cf8c
                                    comm_ptr, request);
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        mpi_errno = MPIR_Iallgather_impl(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype,
Packit Service c5cf8c
                                         comm_ptr, request);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#endif /* MPICH_MPI_FROM_PMPI */
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPI_Iallgather
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
/*@
Packit Service c5cf8c
MPI_Iallgather - Gathers data from all tasks and distribute the combined data
Packit Service c5cf8c
                 to all tasks in a nonblocking way
Packit Service c5cf8c
Packit Service c5cf8c
Input Parameters:
Packit Service c5cf8c
+ sendbuf - starting address of the send buffer (choice)
Packit Service c5cf8c
. sendcount - number of elements in send buffer (non-negative integer)
Packit Service c5cf8c
. sendtype - data type of send buffer elements (handle)
Packit Service c5cf8c
. recvcount - number of elements in receive buffer (non-negative integer)
Packit Service c5cf8c
. recvtype - data type of receive buffer elements (handle)
Packit Service c5cf8c
- comm - communicator (handle)
Packit Service c5cf8c
Packit Service c5cf8c
Output Parameters:
Packit Service c5cf8c
+ recvbuf - starting address of the receive buffer (choice)
Packit Service c5cf8c
- request - communication request (handle)
Packit Service c5cf8c
Packit Service c5cf8c
.N ThreadSafe
Packit Service c5cf8c
Packit Service c5cf8c
.N Fortran
Packit Service c5cf8c
Packit Service c5cf8c
.N Errors
Packit Service c5cf8c
@*/
Packit Service c5cf8c
int MPI_Iallgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
Packit Service c5cf8c
                   void *recvbuf, int recvcount, MPI_Datatype recvtype,
Packit Service c5cf8c
                   MPI_Comm comm, MPI_Request * request)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
    MPIR_Comm *comm_ptr = NULL;
Packit Service c5cf8c
    MPIR_Request *request_ptr = NULL;
Packit Service c5cf8c
    MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_IALLGATHER);
Packit Service c5cf8c
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
    MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_IALLGATHER);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Validate parameters, especially handles needing to be converted */
Packit Service c5cf8c
#ifdef HAVE_ERROR_CHECKING
Packit Service c5cf8c
    {
Packit Service c5cf8c
        MPID_BEGIN_ERROR_CHECKS;
Packit Service c5cf8c
        {
Packit Service c5cf8c
            if (sendbuf != MPI_IN_PLACE) {
Packit Service c5cf8c
                MPIR_ERRTEST_DATATYPE(sendtype, "sendtype", mpi_errno);
Packit Service c5cf8c
                MPIR_ERRTEST_COUNT(sendcount, mpi_errno);
Packit Service c5cf8c
            }
Packit Service c5cf8c
            MPIR_ERRTEST_DATATYPE(recvtype, "recvtype", mpi_errno);
Packit Service c5cf8c
            MPIR_ERRTEST_COMM(comm, mpi_errno);
Packit Service c5cf8c
Packit Service c5cf8c
            /* TODO more checks may be appropriate */
Packit Service c5cf8c
        }
Packit Service c5cf8c
        MPID_END_ERROR_CHECKS;
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif /* HAVE_ERROR_CHECKING */
Packit Service c5cf8c
Packit Service c5cf8c
    /* Convert MPI object handles to object pointers */
Packit Service c5cf8c
    MPIR_Comm_get_ptr(comm, comm_ptr);
Packit Service c5cf8c
    MPIR_Assert(comm_ptr != NULL);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Validate parameters and objects (post conversion) */
Packit Service c5cf8c
#ifdef HAVE_ERROR_CHECKING
Packit Service c5cf8c
    {
Packit Service c5cf8c
        MPID_BEGIN_ERROR_CHECKS;
Packit Service c5cf8c
        {
Packit Service c5cf8c
            MPIR_Comm_valid_ptr(comm_ptr, mpi_errno, FALSE);
Packit Service c5cf8c
            if (sendbuf != MPI_IN_PLACE && HANDLE_GET_KIND(sendtype) != HANDLE_KIND_BUILTIN) {
Packit Service c5cf8c
                MPIR_Datatype *sendtype_ptr = NULL;
Packit Service c5cf8c
                MPIR_Datatype_get_ptr(sendtype, sendtype_ptr);
Packit Service c5cf8c
                MPIR_Datatype_valid_ptr(sendtype_ptr, mpi_errno);
Packit Service c5cf8c
                if (mpi_errno != MPI_SUCCESS)
Packit Service c5cf8c
                    goto fn_fail;
Packit Service c5cf8c
                MPIR_Datatype_committed_ptr(sendtype_ptr, mpi_errno);
Packit Service c5cf8c
                if (mpi_errno != MPI_SUCCESS)
Packit Service c5cf8c
                    goto fn_fail;
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            if (HANDLE_GET_KIND(recvtype) != HANDLE_KIND_BUILTIN) {
Packit Service c5cf8c
                MPIR_Datatype *recvtype_ptr = NULL;
Packit Service c5cf8c
                MPIR_Datatype_get_ptr(recvtype, recvtype_ptr);
Packit Service c5cf8c
                MPIR_Datatype_valid_ptr(recvtype_ptr, mpi_errno);
Packit Service c5cf8c
                if (mpi_errno != MPI_SUCCESS)
Packit Service c5cf8c
                    goto fn_fail;
Packit Service c5cf8c
                MPIR_Datatype_committed_ptr(recvtype_ptr, mpi_errno);
Packit Service c5cf8c
                if (mpi_errno != MPI_SUCCESS)
Packit Service c5cf8c
                    goto fn_fail;
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            MPIR_ERRTEST_ARGNULL(request, "request", mpi_errno);
Packit Service c5cf8c
Packit Service c5cf8c
            /* catch common aliasing cases */
Packit Service c5cf8c
            if (comm_ptr->comm_kind == MPIR_COMM_KIND__INTRACOMM && recvbuf != MPI_IN_PLACE &&
Packit Service c5cf8c
                sendtype == recvtype && sendcount == recvcount && sendcount != 0) {
Packit Service c5cf8c
                int recvtype_size;
Packit Service c5cf8c
                MPIR_Datatype_get_size_macro(recvtype, recvtype_size);
Packit Service c5cf8c
                MPIR_ERRTEST_ALIAS_COLL(sendbuf,
Packit Service c5cf8c
                                        (char *) recvbuf +
Packit Service c5cf8c
                                        comm_ptr->rank * recvcount * recvtype_size, mpi_errno);
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            /* TODO more checks may be appropriate (counts, in_place, etc) */
Packit Service c5cf8c
        }
Packit Service c5cf8c
        MPID_END_ERROR_CHECKS;
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif /* HAVE_ERROR_CHECKING */
Packit Service c5cf8c
Packit Service c5cf8c
    /* ... body of routine ...  */
Packit Service c5cf8c
Packit Service c5cf8c
    mpi_errno = MPIR_Iallgather(sendbuf, sendcount, sendtype, recvbuf, recvcount,
Packit Service c5cf8c
                                recvtype, comm_ptr, &request_ptr);
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
Packit Service c5cf8c
    /* create a complete request, if needed */
Packit Service c5cf8c
    if (!request_ptr)
Packit Service c5cf8c
        request_ptr = MPIR_Request_create_complete(MPIR_REQUEST_KIND__COLL);
Packit Service c5cf8c
    /* return the handle of the request to the user */
Packit Service c5cf8c
    *request = request_ptr->handle;
Packit Service c5cf8c
Packit Service c5cf8c
    /* ... end of body of routine ... */
Packit Service c5cf8c
Packit Service c5cf8c
  fn_exit:
Packit Service c5cf8c
    MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_IALLGATHER);
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
Packit Service c5cf8c
  fn_fail:
Packit Service c5cf8c
    /* --BEGIN ERROR HANDLING-- */
Packit Service c5cf8c
#ifdef HAVE_ERROR_CHECKING
Packit Service c5cf8c
    {
Packit Service c5cf8c
        mpi_errno =
Packit Service c5cf8c
            MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER,
Packit Service c5cf8c
                                 "**mpi_iallgather", "**mpi_iallgather %p %d %D %p %d %D %C %p",
Packit Service c5cf8c
                                 sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm,
Packit Service c5cf8c
                                 request);
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    mpi_errno = MPIR_Err_return_comm(comm_ptr, FCNAME, mpi_errno);
Packit Service c5cf8c
    goto fn_exit;
Packit Service c5cf8c
    /* --END ERROR HANDLING-- */
Packit Service c5cf8c
}