📄 mpid_get.c
字号:
/* (C)Copyright IBM Corp. 2007, 2008 *//** * \file src/onesided/mpid_get.c * \brief MPI-DCMF MPI_Get functionality */#include "mpid_onesided.h"/** * \page get_design MPID_Get Design * * A MPID_Get sequence is as follows: * * <B>Origin node calls MPI_Get</B> * * - A sanity-check is done to * ensure that the window is in a valid state to initiate * a get RMA operation. * These checks include testing that * the epoch currently in affect is not \e NONE or \e POST. * - If target rank is origin rank, call MPIR_Localcopy. * - If origin datatype is not contiguous, allocate a buffer * for contiguous data. * - If target datatype is contiguous, get data from target node * into local buffer. * - If target datatype is non-contiguous: * - Create IO Vector from target datatype. * - Perform multiple get's from target into local buffer. * - If origin datatype is not contiguous, unpack data from buffer * into local window. (free buffer) *//// \cond NOT_REAL_CODE#undef FUNCNAME#define FUNCNAME MPID_Get#undef FCNAME#define FCNAME MPIU_QUOTE(FUNCNAME)/// \endcond/** * \brief MPI-DCMF glue for MPI_GET function * * Get \e target_count number of \e target_datatype from \e target_rank * from window location \e target_disp offset (window displacement units) * into \e origin_count number of \e origin_datatype at \e origin_addr * * \param[in] origin_addr Source buffer * \param[in] origin_count Number of datatype elements * \param[in] origin_datatype Source datatype * \param[in] target_rank Destination rank (target) * \param[in] target_disp Displacement factor in target buffer * \param[in] target_count Number of target datatype elements * \param[in] target_datatype Destination datatype * \param[in] win_ptr Window * \return MPI_SUCCESS, MPI_ERR_RMA_SYNC, or error returned from * MPIR_Localcopy, MPID_Segment_init, or DCMF_Get. * * \ref msginfo_usage\n * \ref get_design */int MPID_Get(void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPID_Win *win_ptr){ int mpi_errno = MPI_SUCCESS; int dt_contig, rank; MPID_Datatype *dtp; MPI_Aint dt_true_lb; MPIDI_msg_sz_t data_sz; MPIU_THREADPRIV_DECL; MPID_MPI_STATE_DECL(MPID_STATE_MPID_GET); MPID_MPI_FUNC_ENTER(MPID_STATE_MPID_GET); MPIU_THREADPRIV_GET; MPIR_Nest_incr(); if (win_ptr->_dev.epoch_type == MPID_EPOTYPE_NONE || win_ptr->_dev.epoch_type == MPID_EPOTYPE_POST || !MPIDU_VALID_RMA_TARGET(win_ptr, target_rank)) { /* --BEGIN ERROR HANDLING-- */ MPIU_ERR_SETANDSTMT(mpi_errno, MPI_ERR_RMA_SYNC, goto fn_fail, "**rmasync"); /* --END ERROR HANDLING-- */ } MPIDI_Datatype_get_info(origin_count, origin_datatype, dt_contig, data_sz, dtp, dt_true_lb); if ((data_sz == 0) || (target_rank == MPI_PROC_NULL)) { goto fn_exit; } rank = win_ptr->_dev.comm_ptr->rank; /* If the get is a local operation, do it here */ if (target_rank == rank) { mpi_errno = MPIR_Localcopy( (char *)win_ptr->base + win_ptr->disp_unit * target_disp, target_count, target_datatype, origin_addr, origin_count, origin_datatype); if (mpi_errno) { MPIU_ERR_POP(mpi_errno); } } else { /* queue it up */ /* * Since GET can never be left pending, we keep * GETs separate from other RMA ops which might not * complete until later. We also do not increment * [target]rma_sends here. */ DCMF_Callback_t cb_send; DCMF_Request_t *reqp; int t_dt_contig; MPID_Datatype *t_dtp; MPI_Aint t_dt_true_lb; MPIDI_msg_sz_t t_data_sz; mpid_dt_info dti; int i, j, get_len; int *refp = NULL; char *b, *s, *t, *buf; int lpid; DCQuad xtra = {0}; lpid = MPIDU_world_rank(win_ptr, target_rank); MPIDI_Datatype_get_info(target_count, target_datatype, t_dt_contig, t_data_sz, t_dtp, t_dt_true_lb); /* NOTE! t_data_sz already is adjusted for target_count */ get_len = (data_sz < t_data_sz ? data_sz : t_data_sz); xtra.w0 = (unsigned)&win_ptr->_dev.my_get_pends; if (dt_contig) { buf = origin_addr; cb_send.function = done_rqc_cb; } else { struct mpid_get_cb_data *get; MPIDU_MALLOC(buf, char, get_len + sizeof(struct mpid_get_cb_data), mpi_errno, "MPID_Get"); if (buf == NULL) { MPID_Abort(NULL, MPI_ERR_NO_SPACE, -1, "Unable to allocate non-" "contiguous buffer"); } MPID_Datatype_add_ref(dtp); get = (struct mpid_get_cb_data *)buf; buf += sizeof(struct mpid_get_cb_data); get->ref = 0; refp = &get->ref; get->dtp = dtp; get->addr = origin_addr; get->count = origin_count; get->len = get_len; get->buf = buf; xtra.w1 = (unsigned)get; xtra.w2 = (unsigned)get; cb_send.function = done_getfree_rqc_cb; } if (t_dt_contig) { t = win_ptr->_dev.coll_info[target_rank].base_addr + win_ptr->_dev.coll_info[target_rank].disp_unit * target_disp; reqp = MPIDU_get_req(&xtra, NULL); cb_send.clientdata = reqp; ++win_ptr->_dev.my_get_pends; if (refp) ++(*refp); mpi_errno = DCMF_Get(&bg1s_gt_proto, reqp, cb_send, win_ptr->_dev.my_cstcy, lpid, t_data_sz, buf, t); if (mpi_errno) { MPIU_ERR_POP(mpi_errno); } } else { /* force map to get built but don't assume * it was sent (use our lpid) */ (void)MPIDU_check_dt(mpid_my_lpid, target_datatype, &dti); MPID_assert(dti.map != NULL); b = win_ptr->_dev.coll_info[target_rank].base_addr + win_ptr->_dev.coll_info[target_rank].disp_unit * target_disp; s = buf; if (refp) *refp = target_count * dti.map_len; for (j = 0; j < target_count; ++j) { for (i = 0; i < dti.map_len; i++) { MPIDU_Progress_spin(win_ptr->_dev.my_get_pends > MPIDI_Process.rma_pending); t = b + dti.map[i].off; reqp = MPIDU_get_req(&xtra, NULL); cb_send.clientdata = reqp; ++win_ptr->_dev.my_get_pends; mpi_errno = DCMF_Get(&bg1s_gt_proto, reqp, cb_send, win_ptr->_dev.my_cstcy, lpid, dti.map[i].len, s, t); if (mpi_errno) { MPIU_ERR_POP(mpi_errno); } s += dti.map[i].len; } b += dti.dtp->extent; } } /** * \todo we don't know when the "request to get" messages have been sent, * but we should wait for that. */ }fn_exit: MPIR_Nest_decr(); MPID_MPI_FUNC_EXIT(MPID_STATE_MPID_GET); return mpi_errno; /* --BEGIN ERROR HANDLING-- */fn_fail: goto fn_exit; /* --END ERROR HANDLING-- */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -