-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/coll/gatherv.c
        -:    0:Graph:gatherv.gcno
        -:    0:Data:gatherv.gcda
        -:    0:Runs:739
        -:    0:Programs:199
        -:    1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
        -:    2:/*
        -:    3: *
        -:    4: *  (C) 2001 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_Gatherv */
        -:   11:#if defined(HAVE_PRAGMA_WEAK)
        -:   12:#pragma weak MPI_Gatherv = PMPI_Gatherv
        -:   13:#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
        -:   14:#pragma _HP_SECONDARY_DEF PMPI_Gatherv  MPI_Gatherv
        -:   15:#elif defined(HAVE_PRAGMA_CRI_DUP)
        -:   16:#pragma _CRI duplicate MPI_Gatherv as PMPI_Gatherv
        -:   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_Gatherv
        -:   24:#define MPI_Gatherv PMPI_Gatherv
        -:   25:
        -:   26:/* This is the default implementation of gatherv. The algorithm is:
        -:   27:   
        -:   28:   Algorithm: MPI_Gatherv
        -:   29:
        -:   30:   Since the array of recvcounts is valid only on the root, we cannot
        -:   31:   do a tree algorithm without first communicating the recvcounts to
        -:   32:   other processes. Therefore, we simply use a linear algorithm for the
        -:   33:   gather, which takes (p-1) steps versus lgp steps for the tree
        -:   34:   algorithm. The bandwidth requirement is the same for both algorithms.
        -:   35:
        -:   36:   Cost = (p-1).alpha + n.((p-1)/p).beta
        -:   37:
        -:   38:   Possible improvements: 
        -:   39:
        -:   40:   End Algorithm: MPI_Gatherv
        -:   41:*/
        -:   42:
        -:   43:/* not declared static because it is called in intercommunicator allgatherv */
        -:   44:int MPIR_Gatherv ( 
        -:   45:	void *sendbuf, 
        -:   46:	int sendcnt,  
        -:   47:	MPI_Datatype sendtype, 
        -:   48:	void *recvbuf, 
        -:   49:	int *recvcnts, 
        -:   50:	int *displs, 
        -:   51:	MPI_Datatype recvtype, 
        -:   52:	int root, 
        -:   53:	MPID_Comm *comm_ptr )
    11805:   54:{
        -:   55:    static const char FCNAME[] = "MPIR_Gatherv";
        -:   56:    int        comm_size, rank;
    11805:   57:    int        mpi_errno = MPI_SUCCESS;
        -:   58:    MPI_Comm comm;
        -:   59:    MPI_Aint       extent;
        -:   60:    int            i, reqs;
        -:   61:    int min_procs;
        -:   62:    char *min_procs_str;
        -:   63:    MPI_Request *reqarray;
        -:   64:    MPI_Status *starray;
    11805:   65:    MPIU_CHKLMEM_DECL(2);
        -:   66:    
    11805:   67:    comm = comm_ptr->handle;
    11805:   68:    rank = comm_ptr->rank;
        -:   69:    
        -:   70:    /* check if multiple threads are calling this collective function */
        -:   71:    MPIDU_ERR_CHECK_MULTIPLE_THREADS_ENTER( comm_ptr );
        -:   72:
        -:   73:    /* If rank == root, then I recv lots, otherwise I send */
    11805:   74:    if (((comm_ptr->comm_kind == MPID_INTRACOMM) && (root == rank)) ||
        -:   75:        ((comm_ptr->comm_kind == MPID_INTERCOMM) && (root == MPI_ROOT))) {
     4032:   76:        if (comm_ptr->comm_kind == MPID_INTRACOMM)
     2752:   77:            comm_size = comm_ptr->local_size;
        -:   78:        else
     1280:   79:            comm_size = comm_ptr->remote_size;
        -:   80:
     4032:   81:        MPID_Datatype_get_extent_macro(recvtype, extent);
        -:   82:	/* each node can make sure it is not going to overflow aint */
        -:   83:        MPID_Ensure_Aint_fits_in_pointer(MPI_VOID_PTR_CAST_TO_MPI_AINT recvbuf +
        -:   84:					 displs[rank] * extent);
        -:   85:
     4032:   86:        MPIU_CHKLMEM_MALLOC(reqarray, MPI_Request *, comm_size * sizeof(MPI_Request), mpi_errno, "reqarray");
     4032:   87:        MPIU_CHKLMEM_MALLOC(starray, MPI_Status *, comm_size * sizeof(MPI_Status), mpi_errno, "starray");
        -:   88:
     4032:   89:        reqs = 0;
    12461:   90:        for (i = 0; i < comm_size; i++) {
     8429:   91:            if (recvcnts[i]) {
     7723:   92:                if ((comm_ptr->comm_kind == MPID_INTRACOMM) && (i == rank)) {
     2605:   93:                    if (sendbuf != MPI_IN_PLACE) {
     2594:   94:                        mpi_errno = MPIR_Localcopy(sendbuf, sendcnt, sendtype,
        -:   95:                                                   ((char *)recvbuf+displs[rank]*extent), 
        -:   96:                                                   recvcnts[rank], recvtype);
        -:   97:                    }
        -:   98:                }
        -:   99:                else {
     5118:  100:                    mpi_errno = MPIC_Irecv(((char *)recvbuf+displs[i]*extent), 
        -:  101:                                           recvcnts[i], recvtype, i,
        -:  102:                                           MPIR_GATHERV_TAG, comm,
        -:  103:                                           &reqarray[reqs++]);
        -:  104:                }
        -:  105:		/* --BEGIN ERROR HANDLING-- */
     7723:  106:                if (mpi_errno) {
    #####:  107:		    mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
    #####:  108:		    return mpi_errno;
        -:  109:		}
        -:  110:		/* --END ERROR HANDLING-- */
        -:  111:            }
        -:  112:        }
        -:  113:        /* ... then wait for *all* of them to finish: */
     4032:  114:        mpi_errno = NMPI_Waitall(reqs, reqarray, starray);
        -:  115:        /* --BEGIN ERROR HANDLING-- */
     4032:  116:        if (mpi_errno == MPI_ERR_IN_STATUS) {
    #####:  117:            for (i = 0; i < reqs; i++) {
    #####:  118:                if (starray[i].MPI_ERROR != MPI_SUCCESS)
    #####:  119:                    mpi_errno = starray[i].MPI_ERROR;
        -:  120:            }
        -:  121:        }
        -:  122:        /* --END ERROR HANDLING-- */
        -:  123:    }
        -:  124:
     7773:  125:    else if (root != MPI_PROC_NULL) { /* non-root nodes, and in the intercomm. case, non-root nodes on remote side */
     5677:  126:        if (sendcnt) {
        -:  127:            /* we want local size in both the intracomm and intercomm cases
        -:  128:               because the size of the root's group (group A in the standard) is
        -:  129:               irrelevant here. */
     5118:  130:            comm_size = comm_ptr->local_size;
        -:  131:
     5118:  132:            min_procs_str = getenv("MPICH2_GATHERV_MIN_PROCS");
     5118:  133:            if (min_procs_str != NULL)
        -:  134:                min_procs = atoi(min_procs_str);
        -:  135:            else
     5118:  136:                min_procs = comm_size + 1; /* Disable ssend if env not set */
        -:  137:
     5118:  138:            if (min_procs == -1)
    #####:  139:                min_procs = comm_size + 1; /* Disable ssend */
     5118:  140:            else if (min_procs == 0)
    #####:  141:                min_procs = MPIR_GATHERV_MIN_PROCS; /* Use the default value */
        -:  142:
     5118:  143:            if (comm_size >= min_procs) {
    #####:  144:                mpi_errno = MPIC_Ssend(sendbuf, sendcnt, sendtype, root, 
        -:  145:                                       MPIR_GATHERV_TAG, comm);
        -:  146:            }
        -:  147:            else {
     5118:  148:                mpi_errno = MPIC_Send(sendbuf, sendcnt, sendtype, root, 
        -:  149:                                      MPIR_GATHERV_TAG, comm);
        -:  150:            }
        -:  151:            /* --BEGIN ERROR HANDLING-- */
     5118:  152:            if (mpi_errno) {
    #####:  153:                mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
    #####:  154:                return mpi_errno;
        -:  155:            }
        -:  156:            /* --END ERROR HANDLING-- */
        -:  157:        }
        -:  158:    }
        -:  159:    
        -:  160:    /* check if multiple threads are calling this collective function */
        -:  161:    MPIDU_ERR_CHECK_MULTIPLE_THREADS_EXIT( comm_ptr );
        -:  162:
        -:  163:fn_exit:
     8064:  164:    MPIU_CHKLMEM_FREEALL();
    11805:  165:    return mpi_errno;
        -:  166:fn_fail:
        -:  167:    goto fn_exit;
        -:  168:}
        -:  169:
        -:  170:#endif
        -:  171:
        -:  172:#undef FUNCNAME
        -:  173:#define FUNCNAME MPI_Gatherv
        -:  174:
        -:  175:/*@
        -:  176:
        -:  177:MPI_Gatherv - Gathers into specified locations from all processes in a group
        -:  178:
        -:  179:Input Parameters:
        -:  180:+ sendbuf - starting address of send buffer (choice) 
        -:  181:. sendcount - number of elements in send buffer (integer) 
        -:  182:. sendtype - data type of send buffer elements (handle) 
        -:  183:. recvcounts - integer array (of length group size) 
        -:  184:containing the number of elements that are received from each process
        -:  185:(significant only at 'root') 
        -:  186:. displs - integer array (of length group size). Entry 
        -:  187: 'i'  specifies the displacement relative to recvbuf  at
        -:  188:which to place the incoming data from process  'i'  (significant only
        -:  189:at root) 
        -:  190:. recvtype - data type of recv buffer elements 
        -:  191:(significant only at 'root') (handle) 
        -:  192:. root - rank of receiving process (integer) 
        -:  193:- comm - communicator (handle) 
        -:  194:
        -:  195:Output Parameter:
        -:  196:. recvbuf - address of receive buffer (choice, significant only at 'root') 
        -:  197:
        -:  198:.N ThreadSafe
        -:  199:
        -:  200:.N Fortran
        -:  201:
        -:  202:.N Errors
        -:  203:.N MPI_SUCCESS
        -:  204:.N MPI_ERR_COMM
        -:  205:.N MPI_ERR_TYPE
        -:  206:.N MPI_ERR_BUFFER
        -:  207:@*/
        -:  208:int MPI_Gatherv(void *sendbuf, int sendcnt, MPI_Datatype sendtype, 
        -:  209:                void *recvbuf, int *recvcnts, int *displs, 
        -:  210:                MPI_Datatype recvtype, int root, MPI_Comm comm)
     6057:  211:{
        -:  212:    static const char FCNAME[] = "MPI_Gatherv";
     6057:  213:    int mpi_errno = MPI_SUCCESS;
     6057:  214:    MPID_Comm *comm_ptr = NULL;
     6057:  215:    MPIU_THREADPRIV_DECL;
        -:  216:    MPID_MPI_STATE_DECL(MPID_STATE_MPI_GATHERV);
        -:  217:
     6057:  218:    MPIR_ERRTEST_INITIALIZED_ORDIE();
        -:  219:    
     6057:  220:    MPIU_THREAD_CS_ENTER(ALLFUNC,);
        -:  221:    MPID_MPI_COLL_FUNC_ENTER(MPID_STATE_MPI_GATHERV);
        -:  222:
        -:  223:    /* Validate parameters, especially handles needing to be converted */
        -:  224:#   ifdef HAVE_ERROR_CHECKING
        -:  225:    {
        -:  226:        MPID_BEGIN_ERROR_CHECKS;
        -:  227:        {
     6057:  228:	    MPIR_ERRTEST_COMM(comm, mpi_errno);
     6057:  229:            if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:  230:	}
        -:  231:        MPID_END_ERROR_CHECKS;
        -:  232:    }
        -:  233:#   endif /* HAVE_ERROR_CHECKING */
        -:  234:
        -:  235:    /* Convert MPI object handles to object pointers */
     6055:  236:    MPID_Comm_get_ptr( comm, comm_ptr );
        -:  237:
        -:  238:    /* Validate parameters and objects (post conversion) */
        -:  239:#   ifdef HAVE_ERROR_CHECKING
        -:  240:    {
        -:  241:        MPID_BEGIN_ERROR_CHECKS;
        -:  242:        {
     6055:  243:	    MPID_Datatype *sendtype_ptr=NULL, *recvtype_ptr=NULL;
        -:  244:            int i, rank, comm_size;
        -:  245:	    
     6055:  246:            MPID_Comm_valid_ptr( comm_ptr, mpi_errno );
     6055:  247:            if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:  248:
     6053:  249:	    if (comm_ptr->comm_kind == MPID_INTRACOMM) {
     4613:  250:		MPIR_ERRTEST_INTRA_ROOT(comm_ptr, root, mpi_errno);
        -:  251:
     4613:  252:                if (sendbuf != MPI_IN_PLACE) {
     4602:  253:                    MPIR_ERRTEST_COUNT(sendcnt, mpi_errno);
     4602:  254:                    MPIR_ERRTEST_DATATYPE(sendtype, "sendtype", mpi_errno);
     4602:  255:                    if (HANDLE_GET_KIND(sendtype) != HANDLE_KIND_BUILTIN) {
      578:  256:                        MPID_Datatype_get_ptr(sendtype, sendtype_ptr);
      578:  257:                        MPID_Datatype_valid_ptr( sendtype_ptr, mpi_errno );
      578:  258:                        MPID_Datatype_committed_ptr( sendtype_ptr, mpi_errno );
        -:  259:                    }
     4602:  260:                    MPIR_ERRTEST_USERBUFFER(sendbuf,sendcnt,sendtype,mpi_errno);
        -:  261:                }
        -:  262:
     4613:  263:                rank = comm_ptr->rank;
     4613:  264:                if (rank == root) {
     2754:  265:                    comm_size = comm_ptr->local_size;
     7363:  266:                    for (i=0; i<comm_size; i++) {
     4609:  267:                        MPIR_ERRTEST_COUNT(recvcnts[i], mpi_errno);
     4609:  268:                        MPIR_ERRTEST_DATATYPE(recvtype, "recvtype", mpi_errno);
        -:  269:                    }
     2754:  270:                    if (HANDLE_GET_KIND(recvtype) != HANDLE_KIND_BUILTIN) {
      361:  271:                        MPID_Datatype_get_ptr(recvtype, recvtype_ptr);
      361:  272:                        MPID_Datatype_valid_ptr( recvtype_ptr, mpi_errno );
      361:  273:                        MPID_Datatype_committed_ptr( recvtype_ptr, mpi_errno );
        -:  274:                    }
        -:  275:
     2964:  276:                    for (i=0; i<comm_size; i++) {
     2880:  277:                        if (recvcnts[i] > 0) {
     2670:  278:                            MPIR_ERRTEST_RECVBUF_INPLACE(recvbuf, recvcnts[i], mpi_errno);
     2670:  279:                            MPIR_ERRTEST_USERBUFFER(recvbuf,recvcnts[i],recvtype,mpi_errno); 
        -:  280:                            break;
        -:  281:                        }
        -:  282:                    }
        -:  283:                }
        -:  284:                else
     1859:  285:                    MPIR_ERRTEST_SENDBUF_INPLACE(sendbuf, sendcnt, mpi_errno);
        -:  286:            }
        -:  287:
     6053:  288:	    if (comm_ptr->comm_kind == MPID_INTERCOMM) {
     1440:  289:		MPIR_ERRTEST_INTER_ROOT(comm_ptr, root, mpi_errno);
        -:  290:
     1440:  291:                if (root == MPI_ROOT) {
      256:  292:                    comm_size = comm_ptr->remote_size;
     1200:  293:                    for (i=0; i<comm_size; i++) {
      944:  294:                        MPIR_ERRTEST_COUNT(recvcnts[i], mpi_errno);
      944:  295:                        MPIR_ERRTEST_DATATYPE(recvtype, "recvtype", mpi_errno);
        -:  296:                    }
      256:  297:                    if (HANDLE_GET_KIND(recvtype) != HANDLE_KIND_BUILTIN) {
    #####:  298:                        MPID_Datatype_get_ptr(recvtype, recvtype_ptr);
    #####:  299:                        MPID_Datatype_valid_ptr( recvtype_ptr, mpi_errno );
    #####:  300:                        MPID_Datatype_committed_ptr( recvtype_ptr, mpi_errno );
        -:  301:                    }
      256:  302:                    for (i=0; i<comm_size; i++) {
      256:  303:                        if (recvcnts[i] > 0) {
      256:  304:                            MPIR_ERRTEST_RECVBUF_INPLACE(recvbuf, recvcnts[i], mpi_errno);
      256:  305:                            MPIR_ERRTEST_USERBUFFER(recvbuf,recvcnts[i],recvtype,mpi_errno); 
        -:  306:                            break;
        -:  307:                        }
        -:  308:                    }
        -:  309:                }
     1184:  310:                else if (root != MPI_PROC_NULL) {
      944:  311:                    MPIR_ERRTEST_COUNT(sendcnt, mpi_errno);
      944:  312:                    MPIR_ERRTEST_DATATYPE(sendtype, "sendtype", mpi_errno);
      944:  313:                    if (HANDLE_GET_KIND(sendtype) != HANDLE_KIND_BUILTIN) {
    #####:  314:                        MPID_Datatype_get_ptr(sendtype, sendtype_ptr);
    #####:  315:                        MPID_Datatype_valid_ptr( sendtype_ptr, mpi_errno );
    #####:  316:                        MPID_Datatype_committed_ptr( sendtype_ptr, mpi_errno );
        -:  317:                    }
      944:  318:                    MPIR_ERRTEST_SENDBUF_INPLACE(sendbuf, sendcnt, mpi_errno);
      944:  319:                    MPIR_ERRTEST_USERBUFFER(sendbuf,sendcnt,sendtype,mpi_errno);
        -:  320:                }
        -:  321:	    }
        -:  322:
     6053:  323:            if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:  324:        }
        -:  325:        MPID_END_ERROR_CHECKS;
        -:  326:    }
        -:  327:#   endif /* HAVE_ERROR_CHECKING */
        -:  328:
        -:  329:    /* ... body of routine ...  */
        -:  330:
     6045:  331:    if (comm_ptr->coll_fns != NULL && comm_ptr->coll_fns->Gatherv != NULL)
        -:  332:    {
    #####:  333:	mpi_errno = comm_ptr->coll_fns->Gatherv(sendbuf, sendcnt,
        -:  334:                                                sendtype, recvbuf, recvcnts,
        -:  335:                                                displs, recvtype, root,
        -:  336:                                                comm_ptr);  
        -:  337:    }
        -:  338:    else
        -:  339:    {
     6045:  340:	MPIU_THREADPRIV_GET;
        -:  341:        
     6045:  342:        MPIR_Nest_incr();
     6045:  343:        mpi_errno = MPIR_Gatherv(sendbuf, sendcnt, sendtype, 
        -:  344:                                 recvbuf, recvcnts,
        -:  345:                                 displs, recvtype, root, comm_ptr); 
     6045:  346:        MPIR_Nest_decr();
        -:  347:    }
        -:  348:
     6045:  349:    if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:  350:
        -:  351:    /* ... end of body of routine ... */
        -:  352:    
     6057:  353:  fn_exit:
        -:  354:    MPID_MPI_COLL_FUNC_EXIT(MPID_STATE_MPI_GATHERV);
     6057:  355:    MPIU_THREAD_CS_EXIT(ALLFUNC,);
     6057:  356:    return mpi_errno;
        -:  357:
       12:  358:  fn_fail:
        -:  359:    /* --BEGIN ERROR HANDLING-- */
        -:  360:#   ifdef HAVE_ERROR_CHECKING
        -:  361:    {
       12:  362:	mpi_errno = MPIR_Err_create_code(
        -:  363:	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_gatherv",
        -:  364:	    "**mpi_gatherv %p %d %D %p %p %p %D %d %C", sendbuf, sendcnt, sendtype,
        -:  365:	    recvbuf, recvcnts, displs, recvtype, root, comm);
        -:  366:    }
        -:  367:#   endif
       12:  368:    mpi_errno = MPIR_Err_return_comm( comm_ptr, FCNAME, mpi_errno );
       12:  369:    goto fn_exit;
        -:  370:    /* --END ERROR HANDLING-- */
        -:  371:}