Ejemplo n.º 1
0
MPID_Get(origin_addr, origin_count, origin_datatype,
        target_rank, target_disp, target_count, target_datatype, dwin)
{
    if (target_rank == dwin->rank)
    {
	/*
	 * We are attempting to get data from our own memory.
	 *
	 * NOTE: Since we are assuming only basic datatypes are supplied, we
	 * can simple copy the bytes from the local window to the supplied
	 * buffer.
	 */
	target_addr = win.bases[target_rank] + target_offset;
	memcpy(origin_addr, target_addr, origin_byte_count);
    }
    else
    {
	/*
	 * Since we are assuming only basic datatypes are supplied, we do not
	 * need to send the target datatype to the target process. (at least
	 * not yet...)
	 */

	/*
	 * NOTE: the tag 
	 */
	tag = dwin->lops_posted++;
	rc = MPID_Irecv(origin_addr, origin_count, origin_datatype, tag,
		   target_rank, dwin->comm, &req);
	MPIR_Win_req_add(dwin->cur_reqs, req);
	
	MPID_Hid_Win_get_t header;

	header.win = dwin->wins[target_rank];
	header.disp = target_disp;
	header.count = target_count;
	header.datatype = target_datatype;
	header.epoch = win.cur_epoch;
	header.tag = tag;

	iovec[0] = header;
	iovec_cnt = 1;
	MPID_Rhcv(target_rank, dwin->comm, MPID_HID_WIN_GET,
		  iovec, iovec_cnt);

	thread_mutex_lock(dwin->thread_lock);
	{
	    dwin->rhc_cnts[target_rank]++;
	}
	thread_mutex_unlock(dwin->thread_unlock);
    }
}
Ejemplo n.º 2
0
int MPID_Recv(void * buf, int count, MPI_Datatype datatype, int rank, int tag,
	      MPID_Comm * comm, int context_offset, MPI_Status * status, MPID_Request ** request)
{
	int mpi_errno;
/*	printf("#%d ps--- %s() called\n", MPIDI_Process.my_pg_rank, __func__); */

	mpi_errno = MPID_Irecv(buf, count, datatype, rank, tag, comm, context_offset, request);
	if (mpi_errno == MPI_SUCCESS) {
		mpi_errno = MPID_PSP_Wait(*request);
	}

	return mpi_errno;
}
Ejemplo n.º 3
0
static void progress_fn(void * data)
{
    int mpi_errno = MPI_SUCCESS;
    MPIR_Request *request_ptr = NULL;
    MPI_Request request;
    MPI_Status status;

    /* Explicitly add CS_ENTER/EXIT since this thread is created from
     * within an internal function and will call NMPI functions
     * directly. */
    MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);

    /* FIXME: We assume that waiting on some request forces progress
     * on all requests. With fine-grained threads, will this still
     * work as expected? We can imagine an approach where a request on
     * a non-conflicting communicator would not touch the remaining
     * requests to avoid locking issues. Once the fine-grained threads
     * code is fully functional, we need to revisit this and, if
     * appropriate, either change what we do in this thread, or delete
     * this comment. */

    mpi_errno = MPID_Irecv(NULL, 0, MPI_CHAR, 0, WAKE_TAG, progress_comm_ptr,
                           MPIR_CONTEXT_INTRA_PT2PT, &request_ptr);
    MPIR_Assert(!mpi_errno);
    request = request_ptr->handle;
    mpi_errno = MPIR_Wait_impl(&request, &status);
    MPIR_Assert(!mpi_errno);

    /* Send a signal to the main thread saying we are done */
    MPID_Thread_mutex_lock(&progress_mutex, &mpi_errno);
    MPIR_Assert(!mpi_errno);

    progress_thread_done = 1;

    MPID_Thread_mutex_unlock(&progress_mutex, &mpi_errno);
    MPIR_Assert(!mpi_errno);

    MPID_Thread_cond_signal(&progress_cond, &mpi_errno);
    MPIR_Assert(!mpi_errno);

    MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);

    return;
}
Ejemplo n.º 4
0
int MPIC_Sendrecv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
                  int dest, int sendtag, void *recvbuf, int recvcount,
                  MPI_Datatype recvtype, int source, int recvtag,
                  MPI_Comm comm, MPI_Status *status) 
{
    MPID_Request *recv_req_ptr=NULL, *send_req_ptr=NULL;
    int mpi_errno, context_id;
    MPID_Comm *comm_ptr = NULL;
    MPIDI_STATE_DECL(MPID_STATE_MPIC_SENDRECV);

    MPIDI_PT2PT_FUNC_ENTER_BOTH(MPID_STATE_MPIC_SENDRECV);

    MPID_Comm_get_ptr( comm, comm_ptr );
    context_id = (comm_ptr->comm_kind == MPID_INTRACOMM) ?
        MPID_CONTEXT_INTRA_COLL : MPID_CONTEXT_INTER_COLL;

    mpi_errno = MPID_Irecv(recvbuf, recvcount, recvtype, source, recvtag,
                           comm_ptr, context_id, &recv_req_ptr);
    if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
    mpi_errno = MPID_Isend(sendbuf, sendcount, sendtype, dest, sendtag, 
                           comm_ptr, context_id, &send_req_ptr); 
    if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }

    mpi_errno = MPIC_Wait(send_req_ptr); 
    if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
    
    mpi_errno = MPIC_Wait(recv_req_ptr);
    if (mpi_errno) { MPIU_ERR_POPFATAL(mpi_errno); }
    if (status != MPI_STATUS_IGNORE)
        *status = recv_req_ptr->status;
    mpi_errno = recv_req_ptr->status.MPI_ERROR;

    MPID_Request_release(send_req_ptr);
    MPID_Request_release(recv_req_ptr);
 fn_fail:
    /* --BEGIN ERROR HANDLING-- */
    MPIDI_PT2PT_FUNC_EXIT_BOTH(MPID_STATE_MPIC_SENDRECV);
    return mpi_errno;
    /* --END ERROR HANDLING-- */
}
Ejemplo n.º 5
0
/*@
    MPI_Sendrecv - Sends and receives a message

Input Parameters:
+ sendbuf - initial address of send buffer (choice)
. sendcount - number of elements in send buffer (integer)
. sendtype - type of elements in send buffer (handle)
. dest - rank of destination (integer)
. sendtag - send tag (integer)
. recvcount - number of elements in receive buffer (integer)
. recvtype - type of elements in receive buffer (handle)
. source - rank of source (integer)
. recvtag - receive tag (integer)
- comm - communicator (handle)

Output Parameters:
+ recvbuf - initial address of receive buffer (choice)
- status - status object (Status).  This refers to the receive operation.

.N ThreadSafe

.N Fortran

.N FortranStatus

.N Errors
.N MPI_SUCCESS
.N MPI_ERR_COMM
.N MPI_ERR_COUNT
.N MPI_ERR_TYPE
.N MPI_ERR_TAG
.N MPI_ERR_RANK

@*/
int MPI_Sendrecv(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
                 int dest, int sendtag,
                 void *recvbuf, int recvcount, MPI_Datatype recvtype,
                 int source, int recvtag, MPI_Comm comm, MPI_Status * status)
{
    int mpi_errno = MPI_SUCCESS;
    MPIR_Comm *comm_ptr = NULL;
    MPIR_Request *sreq = NULL;
    MPIR_Request *rreq = NULL;
    MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_SENDRECV);

    MPIR_ERRTEST_INITIALIZED_ORDIE();

    MPID_THREAD_CS_ENTER(VCI_GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
    MPIR_FUNC_TERSE_PT2PT_ENTER_BOTH(MPID_STATE_MPI_SENDRECV);

    /* Validate handle parameters needing to be converted */
#ifdef HAVE_ERROR_CHECKING
    {
        MPID_BEGIN_ERROR_CHECKS;
        {
            MPIR_ERRTEST_COMM(comm, mpi_errno);
        }
        MPID_END_ERROR_CHECKS;
    }
#endif /* HAVE_ERROR_CHECKING */

    /* Convert handles to MPI objects. */
    MPIR_Comm_get_ptr(comm, comm_ptr);

#ifdef HAVE_ERROR_CHECKING
    {
        MPID_BEGIN_ERROR_CHECKS;
        {
            /* Validate communicator */
            MPIR_Comm_valid_ptr(comm_ptr, mpi_errno, FALSE);
            if (mpi_errno)
                goto fn_fail;

            /* Validate count */
            MPIR_ERRTEST_COUNT(sendcount, mpi_errno);
            MPIR_ERRTEST_COUNT(recvcount, mpi_errno);

            /* Validate status (status_ignore is not the same as null) */
            MPIR_ERRTEST_ARGNULL(status, "status", mpi_errno);

            /* Validate tags */
            MPIR_ERRTEST_SEND_TAG(sendtag, mpi_errno);
            MPIR_ERRTEST_RECV_TAG(recvtag, mpi_errno);

            /* Validate source and destination */
            if (comm_ptr) {
                MPIR_ERRTEST_SEND_RANK(comm_ptr, dest, mpi_errno);
                MPIR_ERRTEST_RECV_RANK(comm_ptr, source, mpi_errno);
            }

            /* Validate datatype handles */
            MPIR_ERRTEST_DATATYPE(sendtype, "datatype", mpi_errno);
            MPIR_ERRTEST_DATATYPE(recvtype, "datatype", mpi_errno);

            /* Validate datatype objects */
            if (HANDLE_GET_KIND(sendtype) != HANDLE_KIND_BUILTIN) {
                MPIR_Datatype *datatype_ptr = NULL;

                MPIR_Datatype_get_ptr(sendtype, datatype_ptr);
                MPIR_Datatype_valid_ptr(datatype_ptr, mpi_errno);
                if (mpi_errno)
                    goto fn_fail;
                MPIR_Datatype_committed_ptr(datatype_ptr, mpi_errno);
                if (mpi_errno)
                    goto fn_fail;
            }
            if (HANDLE_GET_KIND(recvtype) != HANDLE_KIND_BUILTIN) {
                MPIR_Datatype *datatype_ptr = NULL;

                MPIR_Datatype_get_ptr(recvtype, datatype_ptr);
                MPIR_Datatype_valid_ptr(datatype_ptr, mpi_errno);
                if (mpi_errno)
                    goto fn_fail;
                MPIR_Datatype_committed_ptr(datatype_ptr, mpi_errno);
                if (mpi_errno)
                    goto fn_fail;
            }

            /* Validate buffers */
            MPIR_ERRTEST_USERBUFFER(sendbuf, sendcount, sendtype, mpi_errno);
            MPIR_ERRTEST_USERBUFFER(recvbuf, recvcount, recvtype, mpi_errno);
        }
        MPID_END_ERROR_CHECKS;
    }
#endif /* HAVE_ERROR_CHECKING */

    /* ... body of routine ...  */

    mpi_errno =
        MPID_Irecv(recvbuf, recvcount, recvtype, source, recvtag, comm_ptr,
                   MPIR_CONTEXT_INTRA_PT2PT, &rreq);
    if (mpi_errno != MPI_SUCCESS)
        goto fn_fail;

    /* FIXME - Performance for small messages might be better if MPID_Send() were used here instead of MPID_Isend() */
    mpi_errno =
        MPID_Isend(sendbuf, sendcount, sendtype, dest, sendtag, comm_ptr, MPIR_CONTEXT_INTRA_PT2PT,
                   &sreq);
    if (mpi_errno != MPI_SUCCESS) {
        /* --BEGIN ERROR HANDLING-- */
        if (mpi_errno == MPIX_ERR_NOREQ)
            MPIR_ERR_SET(mpi_errno, MPI_ERR_OTHER, "**nomem");
        /* FIXME: should we cancel the pending (possibly completed) receive request or wait for it to complete? */
        MPIR_Request_free(rreq);
        goto fn_fail;
        /* --END ERROR HANDLING-- */
    }

    if (!MPIR_Request_is_complete(sreq) || !MPIR_Request_is_complete(rreq)) {
        MPID_Progress_state progress_state;

        MPID_Progress_start(&progress_state);
        while (!MPIR_Request_is_complete(sreq) || !MPIR_Request_is_complete(rreq)) {
            mpi_errno = MPID_Progress_wait(&progress_state);
            if (mpi_errno != MPI_SUCCESS) {
                /* --BEGIN ERROR HANDLING-- */
                MPID_Progress_end(&progress_state);
                goto fn_fail;
                /* --END ERROR HANDLING-- */
            }

            if (unlikely(MPIR_Request_is_anysrc_mismatched(rreq))) {
                /* --BEGIN ERROR HANDLING-- */
                mpi_errno = MPIR_Request_handle_proc_failed(rreq);
                if (!MPIR_Request_is_complete(sreq)) {
                    MPID_Cancel_send(sreq);
                    MPIR_STATUS_SET_CANCEL_BIT(sreq->status, FALSE);
                }
                goto fn_fail;
                /* --END ERROR HANDLING-- */
            }
        }
        MPID_Progress_end(&progress_state);
    }

    mpi_errno = rreq->status.MPI_ERROR;
    MPIR_Request_extract_status(rreq, status);
    MPIR_Request_free(rreq);

    if (mpi_errno == MPI_SUCCESS) {
        mpi_errno = sreq->status.MPI_ERROR;
    }
    MPIR_Request_free(sreq);

    if (mpi_errno != MPI_SUCCESS)
        goto fn_fail;

    /* ... end of body of routine ... */

  fn_exit:
    MPIR_FUNC_TERSE_PT2PT_EXIT_BOTH(MPID_STATE_MPI_SENDRECV);
    MPID_THREAD_CS_EXIT(VCI_GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
    return mpi_errno;

  fn_fail:
    /* --BEGIN ERROR HANDLING-- */
#ifdef HAVE_ERROR_CHECKING
    {
        mpi_errno =
            MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, __func__, __LINE__, MPI_ERR_OTHER,
                                 "**mpi_sendrecv",
                                 "**mpi_sendrecv %p %d %D %i %t %p %d %D %i %t %C %p", sendbuf,
                                 sendcount, sendtype, dest, sendtag, recvbuf, recvcount, recvtype,
                                 source, recvtag, comm, status);
    }
#endif
    mpi_errno = MPIR_Err_return_comm(comm_ptr, __func__, mpi_errno);
    goto fn_exit;
    /* --END ERROR HANDLING-- */
}
Ejemplo n.º 6
0
    MPIDI_PT2PT_FUNC_ENTER_BOTH(MPID_STATE_MPIC_SENDRECV_REPLACE);
    
    MPID_Comm_get_ptr( comm, comm_ptr );
    context_id_offset = (comm_ptr->comm_kind == MPID_INTRACOMM) ?
        MPID_CONTEXT_INTRA_COLL : MPID_CONTEXT_INTER_COLL;

    if (count > 0 && dest != MPI_PROC_NULL)
    {
        MPIR_Pack_size_impl(count, datatype, &tmpbuf_size);
        MPIU_CHKLMEM_MALLOC(tmpbuf, void *, tmpbuf_size, mpi_errno, "temporary send buffer");

        mpi_errno = MPIR_Pack_impl(buf, count, datatype, tmpbuf, tmpbuf_size, &tmpbuf_count);
        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
    }

    mpi_errno = MPID_Irecv(buf, count, datatype, source, recvtag,
                           comm_ptr, context_id_offset, &rreq);
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);

    mpi_errno = MPID_Isend(tmpbuf, tmpbuf_count, MPI_PACKED, dest,
                           sendtag, comm_ptr, context_id_offset,
                           &sreq);
    if (mpi_errno != MPI_SUCCESS)
    {
        /* --BEGIN ERROR HANDLING-- */
        /* FIXME: should we cancel the pending (possibly completed) receive request or wait for it to complete? */
        MPID_Request_release(rreq);
        MPIU_ERR_POP(mpi_errno);
        /* --END ERROR HANDLING-- */
    }

    if (!MPID_Request_is_complete(sreq) || !MPID_Request_is_complete(rreq))
Ejemplo n.º 7
0
int MPID_Startall(int count, MPID_Request * requests[])
{
  int rc=MPI_SUCCESS, i;
  for (i = 0; i < count; i++)
    {
      MPID_Request * const preq = requests[i];
      switch(MPID_Request_getType(preq))
        {
        case MPIDI_DCMF_REQUEST_TYPE_RECV:
          {
            rc = MPID_Irecv(preq->dcmf.userbuf,
                            preq->dcmf.userbufcount,
                            preq->dcmf.datatype,
                            MPID_Request_getMatchRank(preq),
                            MPID_Request_getMatchTag(preq),
                            preq->comm,
                            MPID_Request_getMatchCtxt(preq) - preq->comm->recvcontext_id,
                            &preq->partner_request);
            break;
          }
        case MPIDI_DCMF_REQUEST_TYPE_SEND:
          {
            rc = MPID_Isend(preq->dcmf.userbuf,
                            preq->dcmf.userbufcount,
                            preq->dcmf.datatype,
                            MPID_Request_getMatchRank(preq),
                            MPID_Request_getMatchTag(preq),
                            preq->comm,
                            MPID_Request_getMatchCtxt(preq) - preq->comm->context_id,
                            &preq->partner_request);
            break;
          }
        case MPIDI_DCMF_REQUEST_TYPE_RSEND:
          {
            rc = MPID_Irsend(preq->dcmf.userbuf,
                             preq->dcmf.userbufcount,
                             preq->dcmf.datatype,
                             MPID_Request_getMatchRank(preq),
                             MPID_Request_getMatchTag(preq),
                             preq->comm,
                             MPID_Request_getMatchCtxt(preq) - preq->comm->context_id,
                             &preq->partner_request);
            break;
          }
        case MPIDI_DCMF_REQUEST_TYPE_SSEND:
          {
            rc = MPID_Issend(preq->dcmf.userbuf,
                             preq->dcmf.userbufcount,
                             preq->dcmf.datatype,
                             MPID_Request_getMatchRank(preq),
                             MPID_Request_getMatchTag(preq),
                             preq->comm,
                             MPID_Request_getMatchCtxt(preq) - preq->comm->context_id,
                             &preq->partner_request);
            break;
          }
        case MPIDI_DCMF_REQUEST_TYPE_BSEND:
          {
            rc = MPIR_Bsend_isend(preq->dcmf.userbuf,
                                  preq->dcmf.userbufcount,
                                  preq->dcmf.datatype,
                                  MPID_Request_getMatchRank(preq),
                                  MPID_Request_getMatchTag(preq),
                                  preq->comm,
                                  BSEND_INIT,
                                  &preq->partner_request);
            /*
             * MPICH2 maintains an independant reference to the child,
             * but doesn't refcount it.  Since they actually call
             * MPI_Test() on the child request (which will release a
             * ref iff the request is complete), we have to increment
             * the ref_count so that it doesn't get freed from under
             * us.
             */
            if (preq->partner_request != NULL)
              MPIU_Object_add_ref(preq->partner_request);
            break;
          }

        default:
          {
            rc = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, "MPID_Startall", __LINE__, MPI_ERR_INTERN,"**ch3|badreqtype","**ch3|badreqtype %d",MPID_Request_getType(preq));
          }

        } /* switch should end here, bug fixed. */

      if (rc == MPI_SUCCESS)
      {
        preq->status.MPI_ERROR = MPI_SUCCESS;
        if (MPID_Request_getType(preq) == MPIDI_DCMF_REQUEST_TYPE_BSEND)
          {
            /*
             * Complete a persistent Bsend immediately.
             *
             * Because the child of a persistent Bsend is just a
             * normal Isend on a temp buffer, we don't need to wait on
             * the child when the user calls MPI_Wait on the parent.
             * Therefore, disconnect the cc_ptr link to the child and
             * mark the parent complete.
             */
            preq->cc = 0;
            preq->cc_ptr = &preq->cc;
          }
        else
          preq->cc_ptr = &preq->partner_request->cc;
      }
      else
      {
        /* If a failure occurs attempting to start the request,
          then we assume that partner request was not created,
          and stuff the error code in the persistent request.
          The wait and test routines will look at the error code
          in the persistent request if a partner request is not present. */
        preq->partner_request = NULL;
        preq->status.MPI_ERROR = rc;
        preq->cc_ptr = &preq->cc;
        preq->cc = 0;
      }
  } /* for */
  return rc;
}
Ejemplo n.º 8
0
int MPIC_Sendrecv(const void *sendbuf, MPI_Aint sendcount, MPI_Datatype sendtype,
                     int dest, int sendtag, void *recvbuf, MPI_Aint recvcount,
                     MPI_Datatype recvtype, int source, int recvtag,
                     MPID_Comm *comm_ptr, MPI_Status *status, mpir_errflag_t *errflag)
{
    int mpi_errno = MPI_SUCCESS;
    int context_id;
    MPI_Status mystatus;
    MPID_Request *recv_req_ptr = NULL, *send_req_ptr = NULL;
    MPIDI_STATE_DECL(MPID_STATE_MPIC_SENDRECV);

    MPIDI_FUNC_ENTER(MPID_STATE_MPIC_SENDRECV);

    MPIU_DBG_MSG_S(PT2PT, TYPICAL, "IN: errflag = %s", *errflag?"TRUE":"FALSE");

    MPIU_ERR_CHKANDJUMP1((sendcount < 0), mpi_errno, MPI_ERR_COUNT,
                         "**countneg", "**countneg %d", sendcount);
    MPIU_ERR_CHKANDJUMP1((recvcount < 0), mpi_errno, MPI_ERR_COUNT,
                         "**countneg", "**countneg %d", recvcount);

    context_id = (comm_ptr->comm_kind == MPID_INTRACOMM) ?
        MPID_CONTEXT_INTRA_COLL : MPID_CONTEXT_INTER_COLL;

    if (status == MPI_STATUS_IGNORE) status = &mystatus;
    switch(*errflag) {
        case MPIR_ERR_NONE:
            break;
        case MPIR_ERR_PROC_FAILED:
            MPIR_TAG_SET_PROC_FAILURE_BIT(sendtag);
        default:
            MPIR_TAG_SET_ERROR_BIT(sendtag);
    }

    mpi_errno = MPID_Irecv(recvbuf, recvcount, recvtype, source, recvtag,
                           comm_ptr, context_id, &recv_req_ptr);
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
    mpi_errno = MPID_Isend(sendbuf, sendcount, sendtype, dest, sendtag,
                           comm_ptr, context_id, &send_req_ptr);
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);

    mpi_errno = MPIC_Wait(send_req_ptr, errflag);
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
    mpi_errno = MPIC_Wait(recv_req_ptr, errflag);
    if (mpi_errno) MPIU_ERR_POPFATAL(mpi_errno);

    *status = recv_req_ptr->status;

    if (mpi_errno == MPI_SUCCESS) {
        mpi_errno = recv_req_ptr->status.MPI_ERROR;

        if (mpi_errno == MPI_SUCCESS) {
            mpi_errno = send_req_ptr->status.MPI_ERROR;
        }
    }

    MPID_Request_release(send_req_ptr);
    MPID_Request_release(recv_req_ptr);

 fn_exit:
    MPIU_DBG_MSG_D(PT2PT, TYPICAL, "OUT: errflag = %d", *errflag);

    MPIDI_FUNC_EXIT(MPID_STATE_MPIC_SENDRECV);
    return mpi_errno;
 fn_fail:
    if (send_req_ptr)
        MPID_Request_release(send_req_ptr);
    if (recv_req_ptr)
        MPID_Request_release(recv_req_ptr);
    goto fn_exit;
}
Ejemplo n.º 9
0
/*@
    MPI_Sendrecv_replace - Sends and receives using a single buffer

Input Parameters:
+ count - number of elements in send and receive buffer (integer) 
. datatype - type of elements in send and receive buffer (handle) 
. dest - rank of destination (integer) 
. sendtag - send message tag (integer) 
. source - rank of source (integer) 
. recvtag - receive message tag (integer) 
- comm - communicator (handle) 

Output Parameters:
+ buf - initial address of send and receive buffer (choice) 
- status - status object (Status) 

.N ThreadSafe

.N Fortran

.N FortranStatus

.N Errors
.N MPI_SUCCESS
.N MPI_ERR_COMM
.N MPI_ERR_COUNT
.N MPI_ERR_TYPE
.N MPI_ERR_TAG
.N MPI_ERR_RANK
.N MPI_ERR_TRUNCATE
.N MPI_ERR_EXHAUSTED

@*/
int MPI_Sendrecv_replace(void *buf, int count, MPI_Datatype datatype, 
			 int dest, int sendtag, int source, int recvtag,
			 MPI_Comm comm, MPI_Status *status)
{
    static const char FCNAME[] = "MPI_Sendrecv_replace";
    int mpi_errno = MPI_SUCCESS;
    MPIR_Comm *comm_ptr = NULL;
    MPIR_CHKLMEM_DECL(1);
    MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_SENDRECV_REPLACE);
    
    MPIR_ERRTEST_INITIALIZED_ORDIE();
    
    MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
    MPIR_FUNC_TERSE_PT2PT_ENTER_BOTH(MPID_STATE_MPI_SENDRECV_REPLACE);

    /* Convert handles to MPI objects. */
    MPIR_Comm_get_ptr(comm, comm_ptr);
    
#   ifdef HAVE_ERROR_CHECKING
    {
        MPID_BEGIN_ERROR_CHECKS;
        {
	    /* Validate communicator */
            MPIR_Comm_valid_ptr( comm_ptr, mpi_errno, FALSE );
            if (mpi_errno) goto fn_fail;
	    
	    /* Validate count */
	    MPIR_ERRTEST_COUNT(count, mpi_errno);

	    /* Validate status (status_ignore is not the same as null) */
	    MPIR_ERRTEST_ARGNULL(status, "status", mpi_errno);

	    /* Validate tags */
	    MPIR_ERRTEST_SEND_TAG(sendtag, mpi_errno);
	    MPIR_ERRTEST_RECV_TAG(recvtag, mpi_errno);

	    /* Validate source and destination */
	    MPIR_ERRTEST_SEND_RANK(comm_ptr, dest, mpi_errno);
	    MPIR_ERRTEST_RECV_RANK(comm_ptr, source, mpi_errno);

	    /* Validate datatype handle */
	    MPIR_ERRTEST_DATATYPE(datatype, "datatype", mpi_errno);
	    
	    /* Validate datatype object */
	    if (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN)
	    {
		MPIR_Datatype *datatype_ptr = NULL;

		MPIR_Datatype_get_ptr(datatype, datatype_ptr);
		MPIR_Datatype_valid_ptr(datatype_ptr, mpi_errno);
		if (mpi_errno) goto fn_fail;
		MPIR_Datatype_committed_ptr(datatype_ptr, mpi_errno);
		if (mpi_errno) goto fn_fail;
	    }
	    
	    /* Validate buffer */
	    MPIR_ERRTEST_USERBUFFER(buf,count,datatype,mpi_errno);
        }
        MPID_END_ERROR_CHECKS;
    }
#   endif /* HAVE_ERROR_CHECKING */

    /* ... body of routine ... */
    
#   if defined(MPID_Sendrecv_replace)
    {
	mpi_errno = MPID_Sendrecv_replace(buf, count, datatype, dest,
					  sendtag, source, recvtag, comm_ptr, 
					  status)
    }
#   else
    {
	MPIR_Request * sreq;
	MPIR_Request * rreq;
	void * tmpbuf = NULL;
	MPI_Aint tmpbuf_size = 0;
	MPI_Aint tmpbuf_count = 0;

	if (count > 0 && dest != MPI_PROC_NULL)
	{
	    MPIR_Pack_size_impl(count, datatype, &tmpbuf_size);

	    MPIR_CHKLMEM_MALLOC_ORJUMP(tmpbuf, void *, tmpbuf_size, mpi_errno, "temporary send buffer", MPL_MEM_BUFFER);

	    mpi_errno = MPIR_Pack_impl(buf, count, datatype, tmpbuf, tmpbuf_size, &tmpbuf_count);
	    if (mpi_errno != MPI_SUCCESS) goto fn_fail;
	}
	
	mpi_errno = MPID_Irecv(buf, count, datatype, source, recvtag, 
			       comm_ptr, MPIR_CONTEXT_INTRA_PT2PT, &rreq);
	if (mpi_errno != MPI_SUCCESS) goto fn_fail;

	mpi_errno = MPID_Isend(tmpbuf, tmpbuf_count, MPI_PACKED, dest, 
			       sendtag, comm_ptr, MPIR_CONTEXT_INTRA_PT2PT,
			       &sreq);
	if (mpi_errno != MPI_SUCCESS)
	{
	    /* --BEGIN ERROR HANDLING-- */
	    /* FIXME: should we cancel the pending (possibly completed) receive request or wait for it to complete? */
	    MPIR_Request_free(rreq);
	    goto fn_fail;
	    /* --END ERROR HANDLING-- */
	}
	
        if (!MPIR_Request_is_complete(sreq) || !MPIR_Request_is_complete(rreq))
	{
	    MPID_Progress_state progress_state;
	
	    MPID_Progress_start(&progress_state);
            while (!MPIR_Request_is_complete(sreq) || !MPIR_Request_is_complete(rreq))
	    {
		mpi_errno = MPID_Progress_wait(&progress_state);
		if (mpi_errno != MPI_SUCCESS)
		{
		    /* --BEGIN ERROR HANDLING-- */
		    MPID_Progress_end(&progress_state);
		    goto fn_fail;
		    /* --END ERROR HANDLING-- */
		}
	    }
	    MPID_Progress_end(&progress_state);

	}

	if (status != MPI_STATUS_IGNORE)
	{
	    *status = rreq->status;
	}

	if (mpi_errno == MPI_SUCCESS)
	{
	    mpi_errno = rreq->status.MPI_ERROR;

	    if (mpi_errno == MPI_SUCCESS)
	    {
		mpi_errno = sreq->status.MPI_ERROR;
	    }
	}
    
	MPIR_Request_free(sreq);
	MPIR_Request_free(rreq);
    }
Ejemplo n.º 10
0
/*@
    MPI_Irecv - Begins a nonblocking receive

Input Parameters:
+ buf - initial address of receive buffer (choice) 
. count - number of elements in receive buffer (integer) 
. datatype - datatype of each receive buffer element (handle) 
. source - rank of source (integer) 
. tag - message tag (integer) 
- comm - communicator (handle) 

Output Parameters:
. request - communication request (handle) 

.N ThreadSafe

.N Fortran

.N Errors
.N MPI_SUCCESS
.N MPI_ERR_COMM
.N MPI_ERR_COUNT
.N MPI_ERR_TYPE
.N MPI_ERR_TAG
.N MPI_ERR_RANK
.N MPI_ERR_EXHAUSTED
@*/
int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source,
	      int tag, MPI_Comm comm, MPI_Request *request)
{
    static const char FCNAME[] = "MPI_Irecv";
    int mpi_errno = MPI_SUCCESS;
    MPID_Comm *comm_ptr = NULL;
    MPID_Request *request_ptr = NULL;
    MPID_MPI_STATE_DECL(MPID_STATE_MPI_IRECV);

    MPIR_ERRTEST_INITIALIZED_ORDIE();
    
    MPIU_THREAD_CS_ENTER(ALLFUNC,);
    MPID_MPI_PT2PT_FUNC_ENTER_BACK(MPID_STATE_MPI_IRECV);

    /* Validate handle parameters needing to be converted */
#   ifdef HAVE_ERROR_CHECKING
    {
        MPID_BEGIN_ERROR_CHECKS;
        {
	    MPIR_ERRTEST_COMM(comm, mpi_errno);
	}
        MPID_END_ERROR_CHECKS;
    }
#   endif /* HAVE_ERROR_CHECKING */
    
    /* Convert MPI object handles to object pointers */
    MPID_Comm_get_ptr( comm, comm_ptr );

    /* Validate parameters if error checking is enabled */
#   ifdef HAVE_ERROR_CHECKING
    {
        MPID_BEGIN_ERROR_CHECKS;
        {
            MPID_Comm_valid_ptr( comm_ptr, mpi_errno, FALSE );
            if (mpi_errno) goto fn_fail;
	    
	    MPIR_ERRTEST_COUNT(count, mpi_errno);
	    MPIR_ERRTEST_RECV_RANK(comm_ptr, source, mpi_errno);
	    MPIR_ERRTEST_RECV_TAG(tag, mpi_errno);
	    MPIR_ERRTEST_ARGNULL(request,"request",mpi_errno);

	    /* Validate datatype handle */
	    MPIR_ERRTEST_DATATYPE(datatype, "datatype", mpi_errno);
	    
	    /* Validate datatype object */
	    if (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN)
	    {
		MPID_Datatype *datatype_ptr = NULL;

		MPID_Datatype_get_ptr(datatype, datatype_ptr);
		MPID_Datatype_valid_ptr(datatype_ptr, mpi_errno);
		if (mpi_errno) goto fn_fail;
		MPID_Datatype_committed_ptr(datatype_ptr, mpi_errno);
		if (mpi_errno) goto fn_fail;
	    }
	    
	    /* Validate buffer */
	    MPIR_ERRTEST_USERBUFFER(buf,count,datatype,mpi_errno);
        }
        MPID_END_ERROR_CHECKS;
    }
#   endif /* HAVE_ERROR_CHECKING */

    /* ... body of routine ...  */
    
    mpi_errno = MPID_Irecv(buf, count, datatype, source, tag, comm_ptr, 
			   MPID_CONTEXT_INTRA_PT2PT, &request_ptr);
    if (mpi_errno != MPI_SUCCESS) goto fn_fail;

    /* return the handle of the request to the user */
    /* MPIU_OBJ_HANDLE_PUBLISH is unnecessary for irecv, lower-level access is
     * responsible for its own consistency, while upper-level field access is
     * controlled by the completion counter */
    *request = request_ptr->handle;

    /* ... end of body of routine ... */
    
  fn_exit:
    MPID_MPI_PT2PT_FUNC_EXIT_BACK(MPID_STATE_MPI_IRECV);
    MPIU_THREAD_CS_EXIT(ALLFUNC,);
    return mpi_errno;

  fn_fail:
    /* --BEGIN ERROR HANDLING-- */
#   ifdef HAVE_ERROR_CHECKING
    {
	mpi_errno = MPIR_Err_create_code(
	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_irecv",
	    "**mpi_irecv %p %d %D %i %t %C %p", buf, count, datatype, source, tag, comm, request);
    }
#   endif
    mpi_errno = MPIR_Err_return_comm( comm_ptr, FCNAME, mpi_errno );
    goto fn_exit;
    /* --END ERROR HANDLING-- */
}
Ejemplo n.º 11
0
int MPID_Startall(int count, MPID_Request * requests[])
{
    int i;
    int rc;
    int mpi_errno = MPI_SUCCESS;
    MPIDI_STATE_DECL(MPID_STATE_MPID_STARTALL);

    MPIDI_FUNC_ENTER(MPID_STATE_MPID_STARTALL);

    for (i = 0; i < count; i++)
    {
	MPID_Request * const preq = requests[i];

	/* FIXME: The odd 7th arg (match.context_id - comm->context_id) 
	   is probably to get the context offset.  Do we really need the
	   context offset? Is there any case where the offset isn't zero? */
	switch (MPIDI_Request_get_type(preq))
	{
	    case MPIDI_REQUEST_TYPE_RECV:
	    {
		rc = MPID_Irecv(preq->dev.user_buf, preq->dev.user_count, preq->dev.datatype, preq->dev.match.parts.rank,
		    preq->dev.match.parts.tag, preq->comm, preq->dev.match.parts.context_id - preq->comm->recvcontext_id,
		    &preq->partner_request);
		break;
	    }
	    
	    case MPIDI_REQUEST_TYPE_SEND:
	    {
		rc = MPID_Isend(preq->dev.user_buf, preq->dev.user_count, preq->dev.datatype, preq->dev.match.parts.rank,
		    preq->dev.match.parts.tag, preq->comm, preq->dev.match.parts.context_id - preq->comm->context_id,
		    &preq->partner_request);
		break;
	    }
		
	    case MPIDI_REQUEST_TYPE_RSEND:
	    {
		rc = MPID_Irsend(preq->dev.user_buf, preq->dev.user_count, preq->dev.datatype, preq->dev.match.parts.rank,
		    preq->dev.match.parts.tag, preq->comm, preq->dev.match.parts.context_id - preq->comm->context_id,
		    &preq->partner_request);
		break;
	    }
		
	    case MPIDI_REQUEST_TYPE_SSEND:
	    {
		rc = MPID_Issend(preq->dev.user_buf, preq->dev.user_count, preq->dev.datatype, preq->dev.match.parts.rank,
		    preq->dev.match.parts.tag, preq->comm, preq->dev.match.parts.context_id - preq->comm->context_id,
		    &preq->partner_request);
		break;
	    }

	    case MPIDI_REQUEST_TYPE_BSEND:
	    {
		MPI_Request sreq_handle;

                rc = MPIR_Ibsend_impl(preq->dev.user_buf, preq->dev.user_count,
                                      preq->dev.datatype, preq->dev.match.parts.rank,
                                      preq->dev.match.parts.tag, preq->comm,
                                      &sreq_handle);
                if (rc == MPI_SUCCESS)
                {
                    MPID_Request_get_ptr(sreq_handle, preq->partner_request);
                }
		break;
	    }

	    default:
	    {
		/* --BEGIN ERROR HANDLING-- */
		rc = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, FCNAME, __LINE__, MPI_ERR_INTERN, "**ch3|badreqtype",
					  "**ch3|badreqtype %d", MPIDI_Request_get_type(preq));
		/* --END ERROR HANDLING-- */
	    }
	}
	
	if (rc == MPI_SUCCESS)
	{
	    preq->status.MPI_ERROR = MPI_SUCCESS;
	    preq->cc_ptr = &preq->partner_request->cc;
	}
	/* --BEGIN ERROR HANDLING-- */
	else
	{
	    /* If a failure occurs attempting to start the request, then we 
	       assume that partner request was not created, and stuff
	       the error code in the persistent request.  The wait and test
	       routines will look at the error code in the persistent
	       request if a partner request is not present. */
	    preq->partner_request = NULL;
	    preq->status.MPI_ERROR = rc;
	    preq->cc_ptr = &preq->cc;
            MPID_cc_set(&preq->cc, 0);
	}
	/* --END ERROR HANDLING-- */
    }

    MPIDI_FUNC_EXIT(MPID_STATE_MPID_STARTALL);
    return mpi_errno;
}