-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/coll/scatterv.c
        -:    0:Graph:scatterv.gcno
        -:    0:Data:scatterv.gcda
        -:    0:Runs:4381
        -:    0:Programs:1376
        -:    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_Scatterv */
        -:   11:#if defined(HAVE_PRAGMA_WEAK)
        -:   12:#pragma weak MPI_Scatterv = PMPI_Scatterv
        -:   13:#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
        -:   14:#pragma _HP_SECONDARY_DEF PMPI_Scatterv  MPI_Scatterv
        -:   15:#elif defined(HAVE_PRAGMA_CRI_DUP)
        -:   16:#pragma _CRI duplicate MPI_Scatterv as PMPI_Scatterv
        -:   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_Scatterv
        -:   24:#define MPI_Scatterv PMPI_Scatterv
        -:   25:
        -:   26:/* This is the default implementation of scatterv. The algorithm is:
        -:   27:   
        -:   28:   Algorithm: MPI_Scatterv
        -:   29:
        -:   30:   Since the array of sendcounts is valid only on the root, we cannot
        -:   31:   do a tree algorithm without first communicating the sendcounts to
        -:   32:   other processes. Therefore, we simply use a linear algorithm for the
        -:   33:   scatter, 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_Scatterv
        -:   41:*/
        -:   42:
        -:   43:/* not declared static because it is called in intercomm. reduce_scatter */
        -:   44:#undef FUNCNAME
        -:   45:#define FUNCNAME MPIR_Scatterv
        -:   46:int MPIR_Scatterv ( 
        -:   47:	void *sendbuf, 
        -:   48:	int *sendcnts, 
        -:   49:	int *displs, 
        -:   50:	MPI_Datatype sendtype, 
        -:   51:	void *recvbuf, 
        -:   52:	int recvcnt,  
        -:   53:	MPI_Datatype recvtype, 
        -:   54:	int root, 
        -:   55:	MPID_Comm *comm_ptr )
     5528:   56:{
        -:   57:    static const char FCNAME[] = "MPIR_Scatterv";
     5528:   58:    int rank, comm_size, mpi_errno = MPI_SUCCESS;
        -:   59:    MPI_Comm comm;
        -:   60:    MPI_Aint extent;
        -:   61:    int      i, reqs;
        -:   62:    MPI_Request *reqarray;
        -:   63:    MPI_Status *starray;
     5528:   64:    MPIU_CHKLMEM_DECL(2);
        -:   65:
     5528:   66:    comm = comm_ptr->handle;
     5528:   67:    rank = comm_ptr->rank;
        -:   68:    
        -:   69:    /* check if multiple threads are calling this collective function */
        -:   70:    MPIDU_ERR_CHECK_MULTIPLE_THREADS_ENTER( comm_ptr );
        -:   71:
        -:   72:    /* If I'm the root, then scatter */
     5528:   73:    if (((comm_ptr->comm_kind == MPID_INTRACOMM) && (root == rank)) ||
        -:   74:        ((comm_ptr->comm_kind == MPID_INTERCOMM) && (root == MPI_ROOT))) {
     2792:   75:        if (comm_ptr->comm_kind == MPID_INTRACOMM)
     2536:   76:            comm_size = comm_ptr->local_size;
        -:   77:        else
      256:   78:            comm_size = comm_ptr->remote_size;
        -:   79:
     2792:   80:        MPID_Datatype_get_extent_macro(sendtype, extent);
        -:   81:        /* We need a check to ensure extent will fit in a
        -:   82:         * pointer. That needs extent * (max count) but we can't get
        -:   83:         * that without looping over the input data. This is at least
        -:   84:         * a minimal sanity check. Maybe add a global var since we do
        -:   85:         * loop over sendcount[] in MPI_Scatterv before calling
        -:   86:         * this? */
        -:   87:        MPID_Ensure_Aint_fits_in_pointer(MPI_VOID_PTR_CAST_TO_MPI_AINT sendbuf + extent);
        -:   88:
     2792:   89:        MPIU_CHKLMEM_MALLOC(reqarray, MPI_Request *, comm_size * sizeof(MPI_Request), mpi_errno, "reqarray");
     2792:   90:        MPIU_CHKLMEM_MALLOC(starray, MPI_Status *, comm_size * sizeof(MPI_Status), mpi_errno, "starray");
        -:   91:
     2792:   92:        reqs = 0;
     7824:   93:        for (i = 0; i < comm_size; i++) {
     5032:   94:            if (sendcnts[i]) {
     4822:   95:                if ((comm_ptr->comm_kind == MPID_INTRACOMM) && (i == rank)) {
     2389:   96:                    if (recvbuf != MPI_IN_PLACE) {
     2388:   97:                        mpi_errno = MPIR_Localcopy(((char *)sendbuf+displs[rank]*extent), 
        -:   98:                                                   sendcnts[rank], sendtype, 
        -:   99:                                                   recvbuf, recvcnt, recvtype);
        -:  100:                    }
        -:  101:                }
        -:  102:                else {
     2433:  103:                    mpi_errno = MPIC_Isend(((char *)sendbuf+displs[i]*extent), 
        -:  104:                                           sendcnts[i], sendtype, i,
        -:  105:                                           MPIR_SCATTERV_TAG, comm, &reqarray[reqs++]);
        -:  106:                }
        -:  107:		/* --BEGIN ERROR HANDLING-- */
     4822:  108:                if (mpi_errno) {
    #####:  109:		    mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
    #####:  110:		    return mpi_errno;
        -:  111:		}
        -:  112:		/* --END ERROR HANDLING-- */
        -:  113:            }
        -:  114:        }
        -:  115:        /* ... then wait for *all* of them to finish: */
     2792:  116:        mpi_errno = NMPI_Waitall(reqs, reqarray, starray);
        -:  117:        /* --BEGIN ERROR HANDLING-- */
     2792:  118:        if (mpi_errno == MPI_ERR_IN_STATUS) {
    #####:  119:            for (i = 0; i < reqs; i++) {
    #####:  120:                if (starray[i].MPI_ERROR != MPI_SUCCESS)
    #####:  121:                    mpi_errno = starray[i].MPI_ERROR;
        -:  122:            }
        -:  123:        }
        -:  124:        /* --END ERROR HANDLING-- */
        -:  125:    }
        -:  126:
     2736:  127:    else if (root != MPI_PROC_NULL) { /* non-root nodes, and in the intercomm. case, non-root nodes on remote side */
     2496:  128:        if (recvcnt) {
     2433:  129:            mpi_errno = MPIC_Recv(recvbuf,recvcnt,recvtype,root,
        -:  130:                                  MPIR_SCATTERV_TAG,comm,MPI_STATUS_IGNORE);
        -:  131:            /* --BEGIN ERROR HANDLING-- */
     2433:  132:            if (mpi_errno) {
    #####:  133:                mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
    #####:  134:                return mpi_errno;
        -:  135:            }
        -:  136:            /* --END ERROR HANDLING-- */
        -:  137:        }
        -:  138:    }
        -:  139:    
        -:  140:    /* check if multiple threads are calling this collective function */
        -:  141:    MPIDU_ERR_CHECK_MULTIPLE_THREADS_EXIT( comm_ptr );
        -:  142:    
        -:  143:fn_exit:
     5584:  144:    MPIU_CHKLMEM_FREEALL();
     5528:  145:    return mpi_errno;
        -:  146:fn_fail:
        -:  147:    goto fn_exit;
        -:  148:}
        -:  149:
        -:  150:#endif
        -:  151:
        -:  152:#undef FUNCNAME
        -:  153:#define FUNCNAME MPI_Scatterv
        -:  154:
        -:  155:/*@
        -:  156:
        -:  157:MPI_Scatterv - Scatters a buffer in parts to all processes in a communicator
        -:  158:
        -:  159:Input Parameters:
        -:  160:+ sendbuf - address of send buffer (choice, significant only at 'root') 
        -:  161:. sendcounts - integer array (of length group size) 
        -:  162:specifying the number of elements to send to each processor  
        -:  163:. displs - integer array (of length group size). Entry 
        -:  164: 'i'  specifies the displacement (relative to sendbuf  from
        -:  165:which to take the outgoing data to process  'i' 
        -:  166:. sendtype - data type of send buffer elements (handle) 
        -:  167:. recvcount - number of elements in receive buffer (integer) 
        -:  168:. recvtype - data type of receive buffer elements (handle) 
        -:  169:. root - rank of sending process (integer) 
        -:  170:- comm - communicator (handle) 
        -:  171:
        -:  172:Output Parameter:
        -:  173:. recvbuf - address of receive buffer (choice) 
        -:  174:
        -:  175:.N ThreadSafe
        -:  176:
        -:  177:.N Fortran
        -:  178:
        -:  179:.N Errors
        -:  180:.N MPI_SUCCESS
        -:  181:.N MPI_ERR_COMM
        -:  182:.N MPI_ERR_COUNT
        -:  183:.N MPI_ERR_TYPE
        -:  184:.N MPI_ERR_BUFFER
        -:  185:@*/
        -:  186:int MPI_Scatterv( void *sendbuf, int *sendcnts, int *displs, 
        -:  187:		  MPI_Datatype sendtype, void *recvbuf, int recvcnt,
        -:  188:		  MPI_Datatype recvtype,
        -:  189:		  int root, MPI_Comm comm)
     5540:  190:{
        -:  191:    static const char FCNAME[] = "MPI_Scatterv";
     5540:  192:    int mpi_errno = MPI_SUCCESS;
     5540:  193:    MPID_Comm *comm_ptr = NULL;
     5540:  194:    MPIU_THREADPRIV_DECL;
        -:  195:    MPID_MPI_STATE_DECL(MPID_STATE_MPI_SCATTERV);
        -:  196:
     5540:  197:    MPIR_ERRTEST_INITIALIZED_ORDIE();
        -:  198:    
     5540:  199:    MPIU_THREAD_CS_ENTER(ALLFUNC,);
        -:  200:    MPID_MPI_COLL_FUNC_ENTER(MPID_STATE_MPI_SCATTERV);
        -:  201:
        -:  202:    /* Validate parameters, especially handles needing to be converted */
        -:  203:#   ifdef HAVE_ERROR_CHECKING
        -:  204:    {
        -:  205:        MPID_BEGIN_ERROR_CHECKS;
        -:  206:        {
     5540:  207:	    MPIR_ERRTEST_COMM(comm, mpi_errno);
     5540:  208:            if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:  209:	}
        -:  210:        MPID_END_ERROR_CHECKS;
        -:  211:    }
        -:  212:#   endif /* HAVE_ERROR_CHECKING */
        -:  213:
        -:  214:    /* Convert MPI object handles to object pointers */
     5538:  215:    MPID_Comm_get_ptr( comm, comm_ptr );
        -:  216:
        -:  217:    /* Validate parameters and objects (post conversion) */
        -:  218:#   ifdef HAVE_ERROR_CHECKING
        -:  219:    {
        -:  220:        MPID_BEGIN_ERROR_CHECKS;
        -:  221:        {
     5538:  222:	    MPID_Datatype *sendtype_ptr=NULL, *recvtype_ptr=NULL;
        -:  223:            int i, comm_size, rank;
        -:  224:	    
     5538:  225:            MPID_Comm_valid_ptr( comm_ptr, mpi_errno );
     5538:  226:            if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:  227:
     5536:  228:            if (comm_ptr->comm_kind == MPID_INTRACOMM) {
     4096:  229:		MPIR_ERRTEST_INTRA_ROOT(comm_ptr, root, mpi_errno);
     4096:  230:                rank = comm_ptr->rank;
     4096:  231:                comm_size = comm_ptr->local_size;
        -:  232:
     4096:  233:                if (rank == root) {
     6630:  234:                    for (i=0; i<comm_size; i++) {
     4092:  235:                        MPIR_ERRTEST_COUNT(sendcnts[i], mpi_errno);
     4092:  236:                        MPIR_ERRTEST_DATATYPE(sendtype, "sendtype", mpi_errno);
        -:  237:                    }
     2538:  238:                    if (HANDLE_GET_KIND(sendtype) != HANDLE_KIND_BUILTIN) {
      364:  239:                        MPID_Datatype_get_ptr(sendtype, sendtype_ptr);
      364:  240:                        MPID_Datatype_valid_ptr( sendtype_ptr, mpi_errno );
      364:  241:                        MPID_Datatype_committed_ptr( sendtype_ptr, mpi_errno );
        -:  242:                    }
     2750:  243:                    for (i=0; i<comm_size; i++) {
     2665:  244:                        if (sendcnts[i] > 0) {
     2453:  245:                            MPIR_ERRTEST_USERBUFFER(sendbuf,sendcnts[i],sendtype,mpi_errno);
        -:  246:                            break;
        -:  247:                        }
        -:  248:                    }  
     2750:  249:                    for (i=0; i<comm_size; i++) {
     2665:  250:                        if (sendcnts[i] > 0) {
     2453:  251:                            MPIR_ERRTEST_SENDBUF_INPLACE(sendbuf, sendcnts[i], mpi_errno);
        -:  252:                            break;
        -:  253:                        }
        -:  254:                    }
        -:  255:                }
        -:  256:                else 
     1558:  257:                    MPIR_ERRTEST_RECVBUF_INPLACE(recvbuf, recvcnt, mpi_errno);
        -:  258:
     4096:  259:                if (recvbuf != MPI_IN_PLACE) {
     4095:  260:                    MPIR_ERRTEST_COUNT(recvcnt, mpi_errno);
     4095:  261:                    MPIR_ERRTEST_DATATYPE(recvtype, "recvtype", mpi_errno);
     4095:  262:                    if (HANDLE_GET_KIND(recvtype) != HANDLE_KIND_BUILTIN) {
      578:  263:                        MPID_Datatype_get_ptr(recvtype, recvtype_ptr);
      578:  264:                        MPID_Datatype_valid_ptr( recvtype_ptr, mpi_errno );
      578:  265:                        MPID_Datatype_committed_ptr( recvtype_ptr, mpi_errno );
        -:  266:                    }
     4095:  267:                    MPIR_ERRTEST_USERBUFFER(recvbuf,recvcnt,recvtype,mpi_errno);
        -:  268:                }
        -:  269:            }
        -:  270:
     5536:  271:            if (comm_ptr->comm_kind == MPID_INTERCOMM) {
     1440:  272:		MPIR_ERRTEST_INTER_ROOT(comm_ptr, root, mpi_errno);
     1440:  273:                if (root == MPI_ROOT) {
      256:  274:                    comm_size = comm_ptr->remote_size;
     1200:  275:                    for (i=0; i<comm_size; i++) {
      944:  276:                        MPIR_ERRTEST_COUNT(sendcnts[i], mpi_errno);
      944:  277:                        MPIR_ERRTEST_DATATYPE(sendtype, "sendtype", mpi_errno);
        -:  278:                    }
      256:  279:                    if (HANDLE_GET_KIND(sendtype) != HANDLE_KIND_BUILTIN) {
    #####:  280:                        MPID_Datatype_get_ptr(sendtype, sendtype_ptr);
    #####:  281:                        MPID_Datatype_valid_ptr( sendtype_ptr, mpi_errno );
    #####:  282:                        MPID_Datatype_committed_ptr( sendtype_ptr, mpi_errno );
        -:  283:                    }
      256:  284:                    for (i=0; i<comm_size; i++) {
      256:  285:                        if (sendcnts[i] > 0) {
      256:  286:                            MPIR_ERRTEST_SENDBUF_INPLACE(sendbuf, sendcnts[i], mpi_errno);
      256:  287:                            MPIR_ERRTEST_USERBUFFER(sendbuf,sendcnts[i],sendtype,mpi_errno);
        -:  288:                            break;
        -:  289:                        }
        -:  290:                    }
        -:  291:                }       
     1184:  292:                else if (root != MPI_PROC_NULL) {
      944:  293:                    MPIR_ERRTEST_COUNT(recvcnt, mpi_errno);
      944:  294:                    MPIR_ERRTEST_DATATYPE(recvtype, "recvtype", mpi_errno);
      944:  295:                    if (HANDLE_GET_KIND(recvtype) != HANDLE_KIND_BUILTIN) {
    #####:  296:                        MPID_Datatype_get_ptr(recvtype, recvtype_ptr);
    #####:  297:                        MPID_Datatype_valid_ptr( recvtype_ptr, mpi_errno );
    #####:  298:                        MPID_Datatype_committed_ptr( recvtype_ptr, mpi_errno );
        -:  299:                    }
      944:  300:                    MPIR_ERRTEST_RECVBUF_INPLACE(recvbuf, recvcnt, mpi_errno);
      944:  301:                    MPIR_ERRTEST_USERBUFFER(recvbuf,recvcnt,recvtype,mpi_errno);                    
        -:  302:                }
        -:  303:            }
        -:  304:
     5536:  305:            if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:  306:        }
        -:  307:        MPID_END_ERROR_CHECKS;
        -:  308:    }
        -:  309:#   endif /* HAVE_ERROR_CHECKING */
        -:  310:
        -:  311:    /* ... body of routine ...  */
        -:  312:
     5528:  313:    if (comm_ptr->coll_fns != NULL && comm_ptr->coll_fns->Scatter != NULL)
        -:  314:    {
    #####:  315:	mpi_errno = comm_ptr->coll_fns->Scatterv(sendbuf, sendcnts, displs,
        -:  316:                                                sendtype, recvbuf, recvcnt,
        -:  317:                                                recvtype, root, comm_ptr);
        -:  318:    }
        -:  319:    else
        -:  320:    {
     5528:  321:	MPIU_THREADPRIV_GET;
        -:  322:
     5528:  323:        MPIR_Nest_incr();
     5528:  324:        mpi_errno = MPIR_Scatterv(sendbuf, sendcnts, displs, sendtype, 
        -:  325:                                  recvbuf, recvcnt, recvtype, 
        -:  326:                                  root, comm_ptr); 
     5528:  327:        MPIR_Nest_decr();
        -:  328:    }
        -:  329:    
     5528:  330:    if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:  331:
        -:  332:    /* ... end of body of routine ... */
        -:  333:    
     5540:  334:  fn_exit:
        -:  335:    MPID_MPI_COLL_FUNC_EXIT(MPID_STATE_MPI_SCATTERV);
     5540:  336:    MPIU_THREAD_CS_EXIT(ALLFUNC,);
     5540:  337:    return mpi_errno;
        -:  338:
       12:  339:  fn_fail:
        -:  340:    /* --BEGIN ERROR HANDLING-- */
        -:  341:#   ifdef HAVE_ERROR_CHECKING
        -:  342:    {
       12:  343:	mpi_errno = MPIR_Err_create_code(
        -:  344:	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_scatterv",
        -:  345:	    "**mpi_scatterv %p %p %p %D %p %d %D %d %C", sendbuf, sendcnts, displs, sendtype,
        -:  346:	    recvbuf, recvcnt, recvtype, root, comm);
        -:  347:    }
        -:  348:#   endif
       12:  349:    mpi_errno = MPIR_Err_return_comm( comm_ptr, FCNAME, mpi_errno );
       12:  350:    goto fn_exit;
        -:  351:    /* --END ERROR HANDLING-- */
        -:  352:}