-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/coll/red_scat_block.c
        -:    0:Graph:red_scat_block.gcno
        -:    0:Data:red_scat_block.gcda
        -:    0:Runs:530
        -:    0:Programs:138
        -:    1:/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
        -:    2:/*
        -:    3: *
        -:    4: *  (C) 2009 by Argonne National Laboratory.
        -:    5: *      See COPYRIGHT in top-level directory.
        -:    6: */
        -:    7:
        -:    8:#include "mpiimpl.h"
        -:    9:
        -:   10:/* -- Begin Profiling Symbol Block for routine MPI_Reduce_scatter_block */
        -:   11:#if defined(HAVE_PRAGMA_WEAK)
        -:   12:#pragma weak MPI_Reduce_scatter_block = PMPI_Reduce_scatter_block
        -:   13:#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
        -:   14:#pragma _HP_SECONDARY_DEF PMPI_Reduce_scatter_block  MPI_Reduce_scatter_block
        -:   15:#elif defined(HAVE_PRAGMA_CRI_DUP)
        -:   16:#pragma _CRI duplicate MPI_Reduce_scatter_block as PMPI_Reduce_scatter_block
        -:   17:#endif
        -:   18:/* -- End Profiling Symbol Block */
        -:   19:
        -:   20:/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
        -:   21:   the MPI routines */
        -:   22:#ifndef MPICH_MPI_FROM_PMPI
        -:   23:#undef MPI_Reduce_scatter_block
        -:   24:#define MPI_Reduce_scatter_block PMPI_Reduce_scatter_block
        -:   25:/* any utility functions should go here, usually prefixed with PMPI_LOCAL to
        -:   26: * correctly handle weak symbols and the profiling interface */
        -:   27:#endif
        -:   28:
        -:   29:#undef FUNCNAME
        -:   30:#define FUNCNAME MPI_Reduce_scatter_block
        -:   31:#undef FCNAME
        -:   32:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -:   33:/*@
        -:   34:MPI_Reduce_scatter_block - Combines values and scatters the results
        -:   35:
        -:   36:Input Parameters:
        -:   37:+ sendbuf - starting address of send buffer (choice)
        -:   38:. recvcount - element count per block (non-negative integer)
        -:   39:. datatype - datatype of elements of send and receive buffers (handle)
        -:   40:. op - operation (handle)
        -:   41:- comm - communicator (handle)
        -:   42:
        -:   43:Output Parameter:
        -:   44:. recvbuf - starting address of receive buffer (choice)
        -:   45:
        -:   46:.N ThreadSafe
        -:   47:
        -:   48:.N Fortran
        -:   49:
        -:   50:.N collops
        -:   51:
        -:   52:.N Errors
        -:   53:.N MPI_SUCCESS
        -:   54:.N MPI_ERR_COMM
        -:   55:.N MPI_ERR_COUNT
        -:   56:.N MPI_ERR_TYPE
        -:   57:.N MPI_ERR_BUFFER
        -:   58:.N MPI_ERR_OP
        -:   59:.N MPI_ERR_BUFFER_ALIAS
        -:   60:@*/
        -:   61:int MPI_Reduce_scatter_block(void *sendbuf, void *recvbuf, int recvcount,
        -:   62:                             MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
      354:   63:{
      354:   64:    int mpi_errno = MPI_SUCCESS;
      354:   65:    MPID_Comm *comm_ptr = NULL;
      354:   66:    MPID_Comm *scatter_comm_ptr = NULL;
        -:   67:    void *tmp_buf;
        -:   68:    MPI_Aint extent, true_extent, true_lb;
      354:   69:    MPIU_THREADPRIV_DECL;
      354:   70:    MPIU_CHKLMEM_DECL(1);
        -:   71:    MPID_MPI_STATE_DECL(MPID_STATE_MPI_REDUCE_SCATTER_BLOCK);
        -:   72:
      354:   73:    MPIR_ERRTEST_INITIALIZED_ORDIE();
        -:   74:
      354:   75:    MPIU_THREAD_CS_ENTER(ALLFUNC,);
        -:   76:    MPID_MPI_COLL_FUNC_ENTER(MPID_STATE_MPI_REDUCE_SCATTER_BLOCK);
        -:   77:
        -:   78:    /* Validate parameters, especially handles needing to be converted */
        -:   79:#   ifdef HAVE_ERROR_CHECKING
        -:   80:    {
        -:   81:        MPID_BEGIN_ERROR_CHECKS;
        -:   82:        {
      354:   83:            MPIR_ERRTEST_COMM(comm, mpi_errno);
      354:   84:            if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:   85:        }
        -:   86:        MPID_END_ERROR_CHECKS;
        -:   87:    }
        -:   88:#   endif /* HAVE_ERROR_CHECKING */
        -:   89:
        -:   90:    /* Convert MPI object handles to object pointers */
      354:   91:    MPID_Comm_get_ptr(comm, comm_ptr);
        -:   92:
        -:   93:    /* Validate parameters and objects (post conversion) */
        -:   94:#   ifdef HAVE_ERROR_CHECKING
        -:   95:    {
        -:   96:        MPID_BEGIN_ERROR_CHECKS;
        -:   97:        {
      354:   98:            MPID_Datatype *datatype_ptr = NULL;
      354:   99:            MPID_Op *op_ptr = NULL;
        -:  100:            int size;
        -:  101:
      354:  102:            MPID_Comm_valid_ptr(comm_ptr, mpi_errno);
      354:  103:            if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:  104:
      354:  105:            size = comm_ptr->local_size;
        -:  106:
      354:  107:            MPIR_ERRTEST_DATATYPE(datatype, "datatype", mpi_errno);
      354:  108:            if (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN) {
    #####:  109:                MPID_Datatype_get_ptr(datatype, datatype_ptr);
    #####:  110:                MPID_Datatype_valid_ptr(datatype_ptr, mpi_errno);
    #####:  111:                MPID_Datatype_committed_ptr(datatype_ptr, mpi_errno);
        -:  112:            }
        -:  113:
      354:  114:            MPIR_ERRTEST_RECVBUF_INPLACE(recvbuf, recvcount, mpi_errno);
      354:  115:            if (comm_ptr->comm_kind == MPID_INTERCOMM)
    #####:  116:                MPIR_ERRTEST_SENDBUF_INPLACE(sendbuf, recvcount, mpi_errno);
        -:  117:
      354:  118:            MPIR_ERRTEST_USERBUFFER(recvbuf,recvcount,datatype,mpi_errno);
      354:  119:            MPIR_ERRTEST_USERBUFFER(sendbuf,recvcount*size,datatype,mpi_errno);
        -:  120:
      354:  121:            MPIR_ERRTEST_OP(op, mpi_errno);
        -:  122:
      354:  123:            if (mpi_errno != MPI_SUCCESS) goto fn_fail;
      354:  124:            if (HANDLE_GET_KIND(op) != HANDLE_KIND_BUILTIN) {
    #####:  125:                MPID_Op_get_ptr(op, op_ptr);
    #####:  126:                MPID_Op_valid_ptr(op_ptr, mpi_errno);
        -:  127:            }
      354:  128:            if (HANDLE_GET_KIND(op) == HANDLE_KIND_BUILTIN) {
      354:  129:                mpi_errno = (*MPIR_Op_check_dtype_table[op%16 - 1])(datatype);
        -:  130:            }
      354:  131:            if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  132:        }
        -:  133:        MPID_END_ERROR_CHECKS;
        -:  134:    }
        -:  135:#   endif /* HAVE_ERROR_CHECKING */
        -:  136:
        -:  137:    /* ... body of routine ...  */
        -:  138:
        -:  139:    /* Use a naive implementation for now (reduce followed by scatter).
        -:  140:     *
        -:  141:     * FIXME We should adapt one or more of the existing MPI_Reduce_scatter
        -:  142:     * algorithms to work here as well. */
      354:  143:    MPIU_THREADPRIV_GET;
      354:  144:    MPIR_Nest_incr();
        -:  145:
      354:  146:    MPID_Datatype_get_extent_macro(datatype, extent);
      354:  147:    mpi_errno = NMPI_Type_get_true_extent(datatype, &true_lb, &true_extent);
      354:  148:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  149:
      354:  150:    MPIU_CHKLMEM_MALLOC(tmp_buf, void *, true_extent * recvcount * comm_ptr->local_size, mpi_errno, "tmp_buf");
      354:  151:    tmp_buf = (void *)((char*)tmp_buf - true_lb);
        -:  152:
      354:  153:    mpi_errno = NMPI_Reduce((sendbuf == MPI_IN_PLACE ? recvbuf : sendbuf), tmp_buf,
        -:  154:                            (recvcount * comm_ptr->local_size), datatype, op,
        -:  155:                            0/*root*/, comm);
      354:  156:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  157:
      354:  158:    scatter_comm_ptr = comm_ptr;
      354:  159:    if (comm_ptr->comm_kind == MPID_INTERCOMM) {
        -:  160:        /* Get the local intracommunicator */
    #####:  161:        if (!comm_ptr->local_comm)
    #####:  162:            MPIR_Setup_intercomm_localcomm(comm_ptr);
    #####:  163:        scatter_comm_ptr = comm_ptr->local_comm;
        -:  164:    }
      354:  165:    mpi_errno = NMPI_Scatter(tmp_buf, recvcount, datatype,
        -:  166:                             recvbuf, recvcount, datatype,
        -:  167:                             0/*root*/, scatter_comm_ptr->handle);
      354:  168:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  169:
        -:  170:    /* ... end of body of routine ... */
        -:  171:  fn_exit:
      354:  172:    MPIU_CHKLMEM_FREEALL();
      354:  173:    MPIR_Nest_decr();
        -:  174:    MPID_MPI_COLL_FUNC_EXIT(MPID_STATE_MPI_REDUCE_SCATTER_BLOCK);
      354:  175:    MPIU_THREAD_CS_EXIT(ALLFUNC,);
      354:  176:    return mpi_errno;
        -:  177:
    #####:  178:  fn_fail:
        -:  179:    /* --BEGIN ERROR HANDLING-- */
        -:  180:#   ifdef HAVE_ERROR_CHECKING
        -:  181:    {
    #####:  182:        mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__,
        -:  183:                                         MPI_ERR_OTHER, "**mpi_reduce_scatter_block",
        -:  184:                                         "**mpi_reduce_scatter_block %p %p %d %D %O %C",
        -:  185:                                         sendbuf, recvbuf, recvcount, datatype, op, comm);
        -:  186:    }
        -:  187:#   endif
    #####:  188:    mpi_errno = MPIR_Err_return_comm( comm_ptr, FCNAME, mpi_errno );
    #####:  189:    goto fn_exit;
        -:  190:    /* --END ERROR HANDLING-- */
        -:  191:}
        -:  192: