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

📄 mpid_rma_common.c

📁 fortran并行计算包
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  (C)Copyright IBM Corp.  2007, 2008  *//** * \file src/onesided/mpid_rma_common.c * \brief MPI-DCMF Code and data common to RMA modules */#include "mpid_onesided.h"#if 0char *msgtypes[] = {[MPID_MSGTYPE_NONE] = "MPID_MSGTYPE_NONE",[MPID_MSGTYPE_LOCK] = "MPID_MSGTYPE_LOCK",[MPID_MSGTYPE_UNLOCK] = "MPID_MSGTYPE_UNLOCK",[MPID_MSGTYPE_POST] = "MPID_MSGTYPE_POST",[MPID_MSGTYPE_START] = "MPID_MSGTYPE_START",[MPID_MSGTYPE_COMPLETE] = "MPID_MSGTYPE_COMPLETE",[MPID_MSGTYPE_WAIT] = "MPID_MSGTYPE_WAIT",[MPID_MSGTYPE_FENCE] = "MPID_MSGTYPE_FENCE",[MPID_MSGTYPE_UNFENCE] = "MPID_MSGTYPE_UNFENCE",[MPID_MSGTYPE_PUT] = "MPID_MSGTYPE_PUT",[MPID_MSGTYPE_GET] = "MPID_MSGTYPE_GET",[MPID_MSGTYPE_ACC] = "MPID_MSGTYPE_ACC",[MPID_MSGTYPE_DT_MAP] = "MPID_MSGTYPE_DT_MAP",[MPID_MSGTYPE_DT_IOV] = "MPID_MSGTYPE_DT_IOV",[MPID_MSGTYPE_LOCKACK] = "MPID_MSGTYPE_LOCKACK",[MPID_MSGTYPE_UNLOCKACK] = "MPID_MSGTYPE_UNLOCKACK",};#endif/** \brief DCMF Protocol object for DCMF_Send() calls */DCMF_Protocol_t bg1s_sn_proto;/** \brief DCMF Protocol object for DCMF_Get() calls */DCMF_Protocol_t bg1s_gt_proto;/** \brief DCMF Protocol object for DCMF_Control() calls */DCMF_Protocol_t bg1s_ct_proto;/** * \page msginfo_usage Message info (DCQuad) usage conventions * * First (or only) quad: *	- \e w0 = Message type (MPID_MSGTYPE_*) *	- \e w1 = (target) window handle *		(except Datatype map/iov messages use num elements) *	- \e w2 = (originating) rank *	- \e w3 = Depends on message type: *<TABLE BORDER=0 CELLPADDING=0> *<TR><TH ALIGN="RIGHT">Epoch End:</TH> *	<TD>RMA send count</TD></TR> *<TR><TH ALIGN="RIGHT">Put/Accumulate:</TH> *	<TD>target memory address</TD></TR> *<TR><TH ALIGN="RIGHT">Lock:</TH> *	<TD>lock type</TD></TR> *<TR><TH ALIGN="RIGHT">Datatype/loop:</TH> *	<TD>datatype (handle on origin)</TD></TR> *</TABLE> * * Additional quads are message-specific * * MPID_MSGTYPE_ACC: *	- \e w0 = target datatype (handle on origin) *	- \e w1 = operand handle (must be builtin) *	- \e w2 = length (number of datatype instances) *	- \e w3 = 0 * * \note Epoch End includes MPID_MSGTYPE_UNLOCK and MPID_MSGTYPE_COMPLETE * (MPID_Win_fence() uses NMPI_Allreduce()). *//** \brief global for our lpid */unsigned mpid_my_lpid = -1;/** * \brief Build datatype map and iovec * * \param[in] dt	Datatype to build map/iov for * \param[out] dti	Pointer to datatype info struct */void make_dt_map_vec(MPI_Datatype dt, mpid_dt_info *dti) {        int nb, last;        MPID_Segment seg;        MPID_Type_map *mv;        DLOOP_VECTOR *iv;        int i;        MPI_Datatype eltype;        unsigned size;        MPID_Datatype *dtp;        /* NOTE: we know "dt" is not builtin, else why do this? */        /* Use existing routines to get IOV */        MPID_Datatype_get_ptr(dt, dtp);        nb = dtp->n_contig_blocks + 1;        MPIDU_MALLOC(mv, MPID_Type_map, nb * sizeof(*mv), last, "MPID_Type_map");        MPID_assert(mv != NULL);        iv = (DLOOP_VECTOR *)mv;        MPID_Segment_init(NULL, 1, dt, &seg, 0);        last = dtp->size;        MPID_Segment_pack_vector(&seg, 0, &last, iv, &nb);        if (HANDLE_GET_KIND(dtp->eltype) == HANDLE_KIND_BUILTIN) {                eltype = dtp->eltype;                size = MPID_Datatype_get_basic_size(eltype);        } else {                eltype = 0;                size = 0; /* don't care */        }        /* This works because we go backwards, and DLOOP_VECTOR << MPID_Type_map */        for (i = nb; i > 0; ) {                --i;                mv[i].off = (unsigned)iv[i].DLOOP_VECTOR_BUF;                mv[i].len = iv[i].DLOOP_VECTOR_LEN;                mv[i].num = (eltype ? mv[i].len / size : 0);                mv[i].dt = eltype;        }        dti->map_len = nb;        dti->map = mv;        dti->dtp = dtp;}/** * \brief Datatype created to represent the rma_sends element * of the coll_info array of the window structure */MPI_Datatype Coll_info_rma_dt;/** * \brief User defined function created to process the rma_sends * elements of the coll_info array of the window structure */MPI_Op Coll_info_rma_op;/** * \brief Dummy, global, MPID_Progress_state since its not used. */MPID_Progress_state dummy_state;/* * * * * * Generic resource pool management * * * * * *//** * \page rsrc_design Basic resource element design * * Generic resources are managed through a \e mpid_qhead structure * which defines the basic geometry of the allocation blocks and * references the first allocated block. * * Generic resources are allocated in blocks. Each block begins * with a header of \e mpid_resource and is followed by a number * of elements whose size and count are defined for each resource * type. Also, the header size is defined, which may be larger * than the natural size of \e mpid_resource in order to optimize * memory layout (i.e. cache usage). * * Resource blocks are never freed (exception: lock wait queue * resources are freed when the window is freed). * * Specific resources are defined by their elements. Every resource * element must have as its first field the \e next pointer, as * defined by \e mpid_element. Following this is * defined by the needs of the specific resource. * * A newly allocated block is initialized with all elements \e next * chained together and the block's \e next_free pointer set to the * first (free) element. Except for the first allocated block * (the one directly referenced by \e mpid_qhead), the \e next_free * is not used again.  This also applies to the \e next_used and * \e last_used pointers. * * A newly allocated secondary block is linked into the \e mpid_qhead * \e next_block chain and \e next_free chain. * * When an element is taken from the free list, it is always taken * from the top of the list, i.e. directly from \e next_free. * When an element is returned to the free list, it is placed * (pushed) on the top. So an element to be allocated is always the * one most-recently freed, i.e. a LIFO queue. * * When an element is added to the used list, it is always added * to the end of the list, i.e. using the \e last_used pointer. * If an arbitrary element is taken from the used list, it is * taken from the top of the list, i.e. using \e next_used.  This * effectively forms a FIFO queue. * * Other routines exist that permit the used list to be searched, * and the found element may be removed from the used list * "out of turn". A specific resource implementation decides * how it will use this list. *//** * \brief Allocate a new block of elements. * * Unconditionally allocates a block of resources as described by * 'qhead' and link the block into 'qhead'. The new elements * are added to the 'qhead' free list. The new elements are * uninitialized except for the mpid_element field(s). * * \param[in] qhead	Queue Head * \return nothing * * \ref rsrc_design */void MPIDU_alloc_resource(struct mpid_qhead *qhead) {        struct mpid_resource *nq;        struct mpid_element *ne, *nl;        struct mpid_resource *lq;        int x, z;        z = qhead->hdl + (qhead->num * qhead->len);        MPIDU_MALLOC(nq, struct mpid_resource, z, x, "MPIDU_alloc_resource");        MPID_assert(nq != NULL);        nq->next_used = NULL;        nq->last_used = NULL;        nq->next_block = NULL;        /* point to last element in block */        ne = (struct mpid_element *)((char *)nq + z - qhead->len);        nl = NULL;        /* stitch together elements, starting at end */        for (x = 0; x < qhead->num; ++x) {                ne->next = nl;                nl = ne;                ne = (struct mpid_element *)((char *)ne - qhead->len);        }        nq->next_free = nl;        /* Determine how to append new block to block list */        if (qhead->blocks == NULL) {                qhead->blocks = nq;        } else {                /* locate end of block list */		lq = qhead->lastblock;                lq->next_block = nq;                lq = qhead->blocks; /* reset/rewind */                /* determine how to append new elements to free list */                if (lq->next_free == NULL) {                        lq->next_free = nq->next_free;                } else {                        /* locate end of free list */                        for (ne = lq->next_free; ne->next;                                                ne = ne->next);                        ne->next = nq->next_free;                }        }	qhead->lastblock = nq;}/** * \brief Unconditionally free all resource blocks * referenced by 'qhead'. * * NOTE: elements such as datatype cache require addition freeing * and so won't work with this. We could add a "free func ptr" to * qhead and call it here - so each element type can free any other * buffers it may have allocated. * * Right now, this is only called by Win_free() on the lock and unlock * wait queues, which do no additional allocation. * * \param[in] qhead	Queue Head * \return nothing * * \ref rsrc_design */void MPIDU_free_resource(struct mpid_qhead *qhead) {        struct mpid_resource *qp, *np;        for (qp = qhead->blocks; qp != NULL; qp = np) {                np = qp->next_block;                MPIDU_FREE(qp, e, "MPIDU_free_resource");        }        qhead->blocks = NULL;}/** * \brief Get a new (unused) resource element. * * Take a resource element off the free list and put it on the * end of used list (bottom of queue). Element is uninitialized * except for mpid_element structure fields. * * \param[in] qhead	Queue Head * \return pointer to element. * * \ref rsrc_design */void *MPIDU_get_element(struct mpid_qhead *qhead) {        struct mpid_resource *lq = qhead->blocks;        struct mpid_element *wp;        if (lq == NULL || lq->next_free == NULL) {                MPIDU_alloc_resource(qhead);                lq = qhead->blocks;                MPID_assert_debug(lq != NULL && lq->next_free != NULL);        }        wp = lq->next_free;        lq->next_free = wp->next;        if (lq->last_used != NULL) {                lq->last_used->next = wp;        }        wp->next = NULL;        lq->last_used = wp;        if (lq->next_used == NULL) {                lq->next_used = wp;        }        return wp;}/** * \brief Initialize a new (unused) element. * * Get a new element from free list and initialize its contents * from 'el'. Element is placed at bottom of queue. * 'el' is assumed to be of qhead->len size. * * \param[in] qhead	Queue Head * \param[in] el	Pointer to new element data * \return pointer to element. * * \ref rsrc_design */void *MPIDU_add_element(struct mpid_qhead *qhead, void *el) {        struct mpid_element *wp;        wp = MPIDU_get_element(qhead);        MPID_assert_debug(wp != NULL);        memcpy(	(char *)wp + sizeof(struct mpid_element),                (char *)el + sizeof(struct mpid_element),                qhead->len - sizeof(struct mpid_element));        return wp;}/** * \brief Peek at top element in queue (used list). * * Copy contents of first element in used list (top of queue) * into 'el'. Does not alter qhead (used or free lists). * 'el' is assumed to be of qhead->len size. * * \param[in] qhead	Queue Head * \param[out] el	Pointer to destination for element data * \return 1 if no elements on queue or *	0 on success with 'el' filled-in. * * \ref rsrc_design */int MPIDU_peek_element(struct mpid_qhead *qhead, void *el) {        struct mpid_resource *lq = qhead->blocks;        if (lq == NULL || lq->next_used == NULL) {                return 1;        }        if (el != NULL) {                memcpy(el, lq->next_used, qhead->len);        }        return 0;}/** * \brief Free an element. * * Remove element 'el' (parent element 'pe') from used list * and place on free list. Typically, this is only called * after calling MPIDU_find_element() to obtain 'el' and 'pe'.

⌨️ 快捷键说明

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