⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpid_recv.c

📁 mpi并行计算的c++代码 可用vc或gcc编译通过 可以用来搭建并行计算试验环境
💻 C
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//* *  (C) 2001 by Argonne National Laboratory. *      See COPYRIGHT in top-level directory. */#include "mpidimpl.h"#undef FUNCNAME#define FUNCNAME MPID_Recv#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)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 = MPI_SUCCESS;    MPID_Request * rreq;    int found;    MPIDI_STATE_DECL(MPID_STATE_MPID_RECV);    MPIDI_FUNC_ENTER(MPID_STATE_MPID_RECV);    MPIDI_DBG_PRINTF((10, FCNAME, "entering"));    MPIDI_DBG_PRINTF((15, FCNAME, "rank=%d, tag=%d, context=%d", rank, tag,		      comm->context_id + context_offset));        if (rank == MPI_PROC_NULL)    {	MPIR_Status_set_procnull(status);	rreq = NULL;	goto fn_exit;    }    rreq = MPIDI_CH3U_Recvq_FDU_or_AEP(rank, tag, comm->context_id + context_offset, &found);    if (rreq == NULL) {	MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_NO_MEM, "**nomem");    }    /* FIXME: in the common case, we want to simply complete the message       and make as few updates as possible.       Note in addition that this routine is used only by MPI_Recv (a       blocking routine; the intent of the interface (which returns        a request) was to simplify the handling of the case where the       message was not found in the unexpected queue. */    /* FIXME: why do we add the ref count to comm?  The routine that       calls this is required to complete before returning, so       no valid user program can free the communicator while we       are within this routine, and no change to the ref count should        be needed.  Ditto for remembering the datatype and user buffer       statistics (no request should need to be returned by       this routine if the message is already available) */    rreq->comm = comm;    MPIR_Comm_add_ref(comm);    rreq->dev.user_buf = buf;    rreq->dev.user_count = count;    rreq->dev.datatype = datatype;    if (found)    {	MPIDI_VC_t * vc;	/* FIXME: We do not need the vc unless we are performing	   a rendezvous (or synchronous eager(!!!)) send.  This code should 	   instead be optimized for the low-latency case of an eager 	   message, already received first, and then handle the more	   expensive case of rendezvous messages separately. */	MPIDI_Comm_get_vc(comm, rreq->dev.match.rank, &vc);	/* Message was found in the unexepected queue */	MPIDI_DBG_PRINTF((15, FCNAME, "request found in unexpected queue"));	if (MPIDI_Request_get_msg_type(rreq) == MPIDI_REQUEST_EAGER_MSG)	{	    int recv_pending;	    	    /* This is an eager message. */	    MPIDI_DBG_PRINTF((15, FCNAME, "eager message in the request"));	    /* FIXME: There should be no synchronous eager messages.  It	       is not worth the extra complexity to support these separate	       from the rendezvous case (we did this early in MPICH-1 and	       took it out, we should *not* commit the same mistake in MPICH-2)	    */	    /* FIXME: This appears to be identical code to that in MPID_Isend;	       that is a maintenance problem (duplicate code should rarely be	       used; if it is necessary to duplicate code, then it is vital 	       that all locations of the duplicate code contain a complete	       list of locations where the same code appears, so that any	       changes may be uniformly applied */	    /* If this is a eager synchronous message, then we need to send an acknowledgement back to the sender. */	    if (MPIDI_Request_get_sync_send_flag(rreq))	    {		MPIDI_CH3_Pkt_t upkt;		MPIDI_CH3_Pkt_eager_sync_ack_t * const esa_pkt = &upkt.eager_sync_ack;		MPID_Request * esa_req;		    		MPIDI_DBG_PRINTF((30, FCNAME, "sending eager sync ack"));		MPIDI_Pkt_init(esa_pkt, MPIDI_CH3_PKT_EAGER_SYNC_ACK);		esa_pkt->sender_req_id = rreq->dev.sender_req_id;		mpi_errno = MPIDI_CH3_iStartMsg(vc, esa_pkt, sizeof(*esa_pkt), &esa_req);		if (mpi_errno != MPI_SUCCESS) {		    MPIU_ERR_POP(mpi_errno);		}		if (esa_req != NULL)		{		    MPID_Request_release(esa_req);		}	    }	                MPIDI_Request_recv_pending(rreq, &recv_pending);	    if (!recv_pending)	    {		/* All of the data has arrived, we need to unpack the data and then free the buffer and the request. */		if (rreq->dev.recv_data_sz > 0)		{		    MPIDI_CH3U_Request_unpack_uebuf(rreq);		    MPIU_Free(rreq->dev.tmpbuf);		}				mpi_errno = rreq->status.MPI_ERROR;		if (status != MPI_STATUS_IGNORE)		{		    *status = rreq->status;		}				MPID_Request_release(rreq);		rreq = NULL;				goto fn_exit;	    }	    else	    {		/* The data is still being transfered across the net.  We'll leave it to the progress engine to handle once the		   entire message has arrived. */		if (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN)		{		    MPID_Datatype_get_ptr(datatype, rreq->dev.datatype_ptr);		    MPID_Datatype_add_ref(rreq->dev.datatype_ptr);		}	    }	}	else if (MPIDI_Request_get_msg_type(rreq) == MPIDI_REQUEST_RNDV_MSG)	{	    /* A rendezvous request-to-send (RTS) message has arrived.  We need to send a CTS message to the remote process. */	    /* FIXME: We should decide who is responsible for the rendezvous	       and require them to perform the operation.  It makes 	       the most sense for the channel to do this, since it may want to	       optimize the particular handling of the operation.  Common	       code can be made available to the channels separately */#ifdef MPIDI_CH3_CHANNEL_RNDV		/* The channel will be performing the rendezvous */		mpi_errno = MPIDI_CH3U_Post_data_receive(found, &rreq);		/* --BEGIN ERROR HANDLING-- */		if (mpi_errno != MPI_SUCCESS) {		    MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER,					 "**ch3|postrecv",					 "**ch3|postrecv %s",					 "MPIDI_CH3_PKT_RNDV_REQ_TO_SEND");		}		/* --END ERROR HANDLING-- */		mpi_errno = MPIDI_CH3_iStartRndvTransfer (vc, rreq);		/* --BEGIN ERROR HANDLING-- */		if (mpi_errno != MPI_SUCCESS) {		    MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,					"**ch3|ctspkt");		}		/* --END ERROR HANDLING-- */#else	    MPID_Request * cts_req;	    MPIDI_CH3_Pkt_t upkt;	    MPIDI_CH3_Pkt_rndv_clr_to_send_t * cts_pkt = &upkt.rndv_clr_to_send;			    MPIDI_DBG_PRINTF((15, FCNAME, "rndv RTS in the request, sending rndv CTS"));	    	    MPIDI_Pkt_init(cts_pkt, MPIDI_CH3_PKT_RNDV_CLR_TO_SEND);	    cts_pkt->sender_req_id = rreq->dev.sender_req_id;	    cts_pkt->receiver_req_id = rreq->handle;	    mpi_errno = MPIDI_CH3_iStartMsg(vc, cts_pkt, sizeof(*cts_pkt), &cts_req);	    if (mpi_errno != MPI_SUCCESS) {		MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**ch3|ctspkt");	    }	    if (cts_req != NULL)	    {		/* FIXME: Ideally we could specify that a req not be returned.  This would avoid our having to decrement the		   reference count on a req we don't want/need. */		MPID_Request_release(cts_req);	    }#endif	    if (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN)	    {		MPID_Datatype_get_ptr(datatype, rreq->dev.datatype_ptr);		MPID_Datatype_add_ref(rreq->dev.datatype_ptr);	    }	}	else if (MPIDI_Request_get_msg_type(rreq) == MPIDI_REQUEST_SELF_MSG)	{	    MPID_Request * const sreq = rreq->partner_request;	    if (sreq != NULL)	    {		MPIDI_msg_sz_t data_sz;				MPIDI_CH3U_Buffer_copy(sreq->dev.user_buf, sreq->dev.user_count, sreq->dev.datatype, &sreq->status.MPI_ERROR,				       buf, count, datatype, &data_sz, &rreq->status.MPI_ERROR);		rreq->status.count = (int)data_sz;		MPID_Request_set_completed(sreq);		MPID_Request_release(sreq);	    }	    else	    {		/* The sreq is missing which means an error occurred.  rreq->status.MPI_ERROR should have been set when the		   error was detected. */	    }	    if (status != MPI_STATUS_IGNORE)	    {		*status = rreq->status;	    }	    /* no other thread can possibly be waiting on rreq, so it is safe to reset ref_count and cc */	    rreq->cc = 0;	    MPIU_Object_set_ref(rreq, 1);	}	else	{	    /* --BEGIN ERROR HANDLING-- */	    MPID_Request_release(rreq);	    rreq = NULL;	    MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_INTERN, "**ch3|badmsgtype",		      "**ch3|badmsgtype %d", MPIDI_Request_get_msg_type(rreq));	    /* --END ERROR HANDLING-- */	}    }    else    {	/* Message has yet to arrived.  The request has been placed on the list of posted receive requests and populated with           information supplied in the arguments. */	MPIDI_DBG_PRINTF((15, FCNAME, "request allocated in posted queue"));		if (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN)	{	    MPID_Datatype_get_ptr(datatype, rreq->dev.datatype_ptr);	    MPID_Datatype_add_ref(rreq->dev.datatype_ptr);	}	rreq->dev.recv_pending_count = 1;        MPID_Request_initialized_set(rreq);    }  fn_exit:    *request = rreq;    if (rreq)    {	MPIDI_DBG_PRINTF((15, FCNAME, "request allocated, handle=0x%08x", rreq->handle));    }    else    {	MPIDI_DBG_PRINTF((15, FCNAME, "operation complete, no requests allocated"));    } fn_fail:    MPIDI_DBG_PRINTF((10, FCNAME, "exiting"));    MPIDI_FUNC_EXIT(MPID_STATE_MPID_RECV);    return mpi_errno;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -