📄 ch3u_eager.c
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//* * (C) 2001 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */#include "mpidimpl.h"/* * Send an eager message. To optimize for the important, short contiguous * message case, there are separate routines for the contig and non-contig * datatype cases. */#undef FUNCNAME#define FUNCNAME MPIDI_CH3_SendNoncontig#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)/* MPIDI_CH3_SendNoncontig - Sends a message by loading an IOV and calling iSendv. The caller must initialize sreq->dev.segment as well as segment_first and segment_size. */int MPIDI_CH3_SendNoncontig( MPIDI_VC_t *vc, MPID_Request *sreq, void *header, MPIDI_msg_sz_t hdr_sz ){ int mpi_errno = MPI_SUCCESS; int iov_n; MPID_IOV iov[MPID_IOV_LIMIT]; iov[0].MPID_IOV_BUF = header; iov[0].MPID_IOV_LEN = hdr_sz; iov_n = MPID_IOV_LIMIT - 1; /* One the initial load of a send iov req, set the OnFinal action (null for point-to-point) */ sreq->dev.OnFinal = 0; mpi_errno = MPIDI_CH3U_Request_load_send_iov(sreq, &iov[1], &iov_n); if (mpi_errno == MPI_SUCCESS) { iov_n += 1; mpi_errno = MPIU_CALL(MPIDI_CH3,iSendv(vc, sreq, iov, iov_n)); /* --BEGIN ERROR HANDLING-- */ if (mpi_errno != MPI_SUCCESS) { MPIU_Object_set_ref(sreq, 0); MPIDI_CH3_Request_destroy(sreq); mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_FATAL, FCNAME, __LINE__, MPI_ERR_OTHER, "**ch3|eagermsg", 0); goto fn_fail; } /* --END ERROR HANDLING-- */ /* Note that in the non-blocking case, we need to add a ref to the datatypes */ } else { /* --BEGIN ERROR HANDLING-- */ MPIU_Object_set_ref(sreq, 0); MPIDI_CH3_Request_destroy(sreq); mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**ch3|loadsendiov", 0); goto fn_fail; /* --END ERROR HANDLING-- */ } fn_exit: return mpi_errno; fn_fail: goto fn_exit;}/* This function will allocate a segment. That segment must be freed when it is no longer needed */#undef FUNCNAME#define FUNCNAME MPIDI_EagerNoncontigSend#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)/* MPIDI_CH3_EagerNoncontigSend - Eagerly send noncontiguous data */int MPIDI_CH3_EagerNoncontigSend( MPID_Request **sreq_p, MPIDI_CH3_Pkt_type_t reqtype, const void * buf, int count, MPI_Datatype datatype, MPIDI_msg_sz_t data_sz, int rank, int tag, MPID_Comm * comm, int context_offset ){ int mpi_errno = MPI_SUCCESS; MPIDI_VC_t * vc; MPID_Request *sreq = *sreq_p; MPIDI_CH3_Pkt_t upkt; MPIDI_CH3_Pkt_eager_send_t * const eager_pkt = &upkt.eager_send; MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST, "sending non-contiguous eager message, data_sz=" MPIDI_MSG_SZ_FMT, data_sz)); MPIDI_Pkt_init(eager_pkt, reqtype); eager_pkt->match.rank = comm->rank; eager_pkt->match.tag = tag; eager_pkt->match.context_id = comm->context_id + context_offset; eager_pkt->sender_req_id = MPI_REQUEST_NULL; eager_pkt->data_sz = data_sz; MPIDI_Comm_get_vc(comm, rank, &vc); MPIDI_VC_FAI_send_seqnum(vc, seqnum); MPIDI_Pkt_set_seqnum(eager_pkt, seqnum); MPIDI_Request_set_seqnum(sreq, seqnum); MPIU_DBG_MSGPKT(vc,tag,eager_pkt->match.context_id,rank,data_sz, "Eager"); sreq->dev.segment_ptr = MPID_Segment_alloc( ); /* if (!sreq->dev.segment_ptr) { MPIU_ERR_POP(); } */ MPID_Segment_init(buf, count, datatype, sreq->dev.segment_ptr, 0); sreq->dev.segment_first = 0; sreq->dev.segment_size = data_sz; mpi_errno = vc->sendNoncontig_fn(vc, sreq, eager_pkt, sizeof(MPIDI_CH3_Pkt_eager_send_t)); if (mpi_errno) MPIU_ERR_POP(mpi_errno); fn_exit: return mpi_errno; fn_fail: *sreq_p = NULL; goto fn_exit;}/* Send a contiguous eager message. We'll want to optimize (and possibly inline) this. Make sure that buf is at the beginning of the data to send; adjust by adding dt_true_lb if necessary */#undef FUNCNAME#define FUNCNAME MPIDI_EagerContigSend#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)int MPIDI_CH3_EagerContigSend( MPID_Request **sreq_p, MPIDI_CH3_Pkt_type_t reqtype, const void * buf, MPIDI_msg_sz_t data_sz, int rank, int tag, MPID_Comm * comm, int context_offset ){ int mpi_errno = MPI_SUCCESS; MPIDI_VC_t * vc; MPIDI_CH3_Pkt_t upkt; MPIDI_CH3_Pkt_eager_send_t * const eager_pkt = &upkt.eager_send; MPID_Request *sreq = *sreq_p; MPID_IOV iov[2]; MPIDI_Pkt_init(eager_pkt, reqtype); eager_pkt->match.rank = comm->rank; eager_pkt->match.tag = tag; eager_pkt->match.context_id = comm->context_id + context_offset; eager_pkt->sender_req_id = MPI_REQUEST_NULL; eager_pkt->data_sz = data_sz; iov[0].MPID_IOV_BUF = (MPID_IOV_BUF_CAST)eager_pkt; iov[0].MPID_IOV_LEN = sizeof(*eager_pkt); MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST, "sending contiguous eager message, data_sz=" MPIDI_MSG_SZ_FMT, data_sz)); iov[1].MPID_IOV_BUF = (MPID_IOV_BUF_CAST) buf; iov[1].MPID_IOV_LEN = data_sz; MPIDI_Comm_get_vc(comm, rank, &vc); MPIDI_VC_FAI_send_seqnum(vc, seqnum); MPIDI_Pkt_set_seqnum(eager_pkt, seqnum); MPIU_DBG_MSGPKT(vc,tag,eager_pkt->match.context_id,rank,data_sz,"EagerContig"); mpi_errno = MPIU_CALL(MPIDI_CH3,iStartMsgv(vc, iov, 2, sreq_p)); if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_SETFATALANDJUMP(mpi_errno,MPI_ERR_OTHER,"**ch3|eagermsg"); } sreq = *sreq_p; if (sreq != NULL) { MPIDI_Request_set_seqnum(sreq, seqnum); MPIDI_Request_set_type(sreq, MPIDI_REQUEST_TYPE_SEND); } fn_fail: return mpi_errno;}#ifdef USE_EAGER_SHORT/* Send a short contiguous eager message. We'll want to optimize (and possibly inline) this Make sure that buf is at the beginning of the data to send; adjust by adding dt_true_lb if necessary We may need a nonblocking (cancellable) version of this, which will have a smaller payload.*/#undef FUNCNAME#define FUNCNAME MPIDI_EagerContigShortSend#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)int MPIDI_CH3_EagerContigShortSend( MPID_Request **sreq_p, MPIDI_CH3_Pkt_type_t reqtype, const void * buf, MPIDI_msg_sz_t data_sz, int rank, int tag, MPID_Comm * comm, int context_offset ){ int mpi_errno = MPI_SUCCESS; MPIDI_VC_t * vc; MPIDI_CH3_Pkt_t upkt; MPIDI_CH3_Pkt_eagershort_send_t * const eagershort_pkt = &upkt.eagershort_send; MPID_Request *sreq = *sreq_p; /* printf( "Sending short eager\n"); fflush(stdout); */ MPIDI_Pkt_init(eagershort_pkt, reqtype); eagershort_pkt->match.rank = comm->rank; eagershort_pkt->match.tag = tag; eagershort_pkt->match.context_id = comm->context_id + context_offset; eagershort_pkt->data_sz = data_sz; MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST, "sending contiguous short eager message, data_sz=" MPIDI_MSG_SZ_FMT, data_sz)); MPIDI_Comm_get_vc(comm, rank, &vc); MPIDI_VC_FAI_send_seqnum(vc, seqnum); MPIDI_Pkt_set_seqnum(eagershort_pkt, seqnum); /* Copy the payload. We could optimize this if data_sz & 0x3 == 0 (copy (data_sz >> 2) ints, inline that since data size is currently limited to 4 ints */ { unsigned char * restrict p = (unsigned char *)eagershort_pkt->data; unsigned char const * restrict bufp = (unsigned char *)buf; int i; for (i=0; i<data_sz; i++) { *p++ = *bufp++; } } MPIU_DBG_MSGPKT(vc,tag,eagershort_pkt->match.context_id,rank,data_sz, "EagerShort"); mpi_errno = MPIU_CALL(MPIDI_CH3,iStartMsg(vc, eagershort_pkt, sizeof(*eagershort_pkt), sreq_p )); if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_SETFATALANDJUMP(mpi_errno,MPI_ERR_OTHER,"**ch3|eagermsg"); } sreq = *sreq_p; if (sreq != NULL) { /*printf( "Surprise, did not complete send of eagershort (starting connection?)\n" ); fflush(stdout); */ MPIDI_Request_set_seqnum(sreq, seqnum); MPIDI_Request_set_type(sreq, MPIDI_REQUEST_TYPE_SEND); } fn_fail: return mpi_errno;}/* This is the matching handler for the EagerShort message defined above */#undef FUNCNAME#define FUNCNAME MPIDI_CH3_PktHandler_EagerShortSend#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)int MPIDI_CH3_PktHandler_EagerShortSend( MPIDI_VC_t *vc, MPIDI_CH3_Pkt_t *pkt, MPIDI_msg_sz_t *buflen, MPID_Request **rreqp ){ MPIDI_CH3_Pkt_eagershort_send_t * eagershort_pkt = &pkt->eagershort_send; MPID_Request * rreq; int found; int mpi_errno = MPI_SUCCESS; /* printf( "Receiving short eager!\n" ); fflush(stdout); */ MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST, "received eagershort send pkt, rank=%d, tag=%d, context=%d", eagershort_pkt->match.rank, eagershort_pkt->match.tag, eagershort_pkt->match.context_id)); MPIU_DBG_MSGPKT(vc,eagershort_pkt->match.tag, eagershort_pkt->match.context_id, eagershort_pkt->match.rank,eagershort_pkt->data_sz, "ReceivedEagerShort"); rreq = MPIDI_CH3U_Recvq_FDP_or_AEU(&eagershort_pkt->match, &found); if (rreq == NULL) { MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**nomemreq"); } (rreq)->status.MPI_SOURCE = (eagershort_pkt)->match.rank; (rreq)->status.MPI_TAG = (eagershort_pkt)->match.tag; (rreq)->status.count = (eagershort_pkt)->data_sz; (rreq)->dev.recv_data_sz = (eagershort_pkt)->data_sz; MPIDI_Request_set_seqnum((rreq), (eagershort_pkt)->seqnum); /* FIXME: Why do we set the message type? */ MPIDI_Request_set_msg_type((rreq), MPIDI_REQUEST_EAGER_MSG); /* The request is still complete (in the sense of having all data) */ MPIDI_CH3U_Request_complete(rreq); /* This packed completes the reception of the indicated data. The packet handler returns null for a request that requires no further communication */ *rreqp = NULL; *buflen = sizeof(MPIDI_CH3_Pkt_t); /* Extract the data from the packet */ /* Note that if the data size if zero, we're already done */ if (rreq->dev.recv_data_sz > 0) { if (found) { int dt_contig; MPI_Aint dt_true_lb; MPIDI_msg_sz_t userbuf_sz; MPID_Datatype *dt_ptr; MPIDI_msg_sz_t data_sz; /* Make sure that we handle the general (non-contiguous) datatypes correctly while optimizing for the special case */ MPIDI_Datatype_get_info(rreq->dev.user_count, rreq->dev.datatype, dt_contig, userbuf_sz, dt_ptr, dt_true_lb); if (rreq->dev.recv_data_sz <= userbuf_sz) { data_sz = rreq->dev.recv_data_sz; } else { MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST, "receive buffer too small; message truncated, msg_sz=" MPIDI_MSG_SZ_FMT ", userbuf_sz=" MPIDI_MSG_SZ_FMT, rreq->dev.recv_data_sz, userbuf_sz)); rreq->status.MPI_ERROR = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_TRUNCATE, "**truncate", "**truncate %d %d %d %d", rreq->status.MPI_SOURCE, rreq->status.MPI_TAG, rreq->dev.recv_data_sz, userbuf_sz ); rreq->status.count = userbuf_sz; data_sz = userbuf_sz; } if (dt_contig && data_sz == rreq->dev.recv_data_sz) { /* user buffer is contiguous and large enough to store the entire message. We can just copy the code */ /* Copy the payload. We could optimize this if data_sz & 0x3 == 0 (copy (data_sz >> 2) ints, inline that since data size is currently limited to 4 ints */ { unsigned char const * restrict p = (unsigned char *)eagershort_pkt->data; unsigned char * restrict bufp = (unsigned char *)(char*)(rreq->dev.user_buf) + dt_true_lb; int i; for (i=0; i<data_sz; i++) { *bufp++ = *p++; } } /* FIXME: We want to set the OnDataAvail to the appropriate function, which depends on whether this is an RMA request or a pt-to-pt request. */ rreq->dev.OnDataAvail = 0; /* The recv_pending_count must be one here (!) because of the way the pending count is queried. We may want to fix this, but it will require a sweep of the code */ } else { MPIDI_msg_sz_t data_sz, last; /* user buffer is not contiguous. Use the segment code to unpack it, handling various errors and exceptional cases */ /* FIXME: The MPICH2 tests do not exercise this branch */ /* printf( "Surprise!\n" ); fflush(stdout);*/ rreq->dev.segment_ptr = MPID_Segment_alloc( ); /* if (!rreq->dev.segment_ptr) { MPIU_ERR_POP(); } */ MPID_Segment_init(rreq->dev.user_buf, rreq->dev.user_count, rreq->dev.datatype, rreq->dev.segment_ptr, 0); data_sz = rreq->dev.recv_data_sz; last = data_sz; MPID_Segment_unpack( rreq->dev.segment_ptr, 0, &last, eagershort_pkt->data ); if (last != data_sz) { /* --BEGIN ERROR HANDLING-- */ /* There are two cases: a datatype mismatch (could
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -