📄 dataloop.c
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//* * (C) 2001 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */#include <string.h>#include <stdio.h>#include <stdlib.h>#include "./dataloop.h"#undef DEBUG_DLOOP_SIZE#undef DLOOP_DEBUG_MEMORY/* Dataloops * * The functions here are used for the creation, copying, update, and display * of DLOOP_Dataloop structures and trees of these structures. * * Currently we store trees of dataloops in contiguous regions of memory. They * are stored in such a way that subtrees are also stored contiguously. This * makes it somewhat easier to copy these subtrees around. Keep this in mind * when looking at the functions below. * * The structures used in this file are defined in mpid_datatype.h. There is * no separate mpid_dataloop.h at this time. * * OPTIMIZATIONS: * * There are spots in the code with OPT tags that indicate where we could * optimize particular calculations or avoid certain checks. * * NOTES: * * Don't have locks in place at this time! *//* Some functions in this file are responsible for allocation of space for * dataloops. These structures include the dataloop structure itself * followed by a sequence of variable-sized arrays, depending on the loop * kind. For example, a dataloop of kind DLOOP_KIND_INDEXED has a * dataloop structure followed by an array of block sizes and then an array * of offsets. * * For efficiency and ease of cleanup (preserving a single free at * deallocation), we want to allocate this memory as a single large chunk. * However, we must perform some alignment of the components of this chunk * in order to obtain correct and efficient operation across all platforms. *//*@ Dataloop_free - deallocate the resources used to store a dataloop Input Parameters:. dataloop - pointer to dataloop structure@*/void PREPEND_PREFIX(Dataloop_free)(DLOOP_Dataloop **dataloop){ if (*dataloop == NULL) return;#ifdef DLOOP_DEBUG_MEMORY DLOOP_dbg_printf("DLOOP_Dataloop_free: freeing loop @ %x.\n", (int) *dataloop);#endif memset(*dataloop, 0, sizeof(DLOOP_Dataloop_common)); DLOOP_Free(*dataloop); *dataloop = NULL; return;}/*@ Dataloop_copy - Copy an arbitrary dataloop structure, updating pointers as necessary Input Parameters:+ dest - pointer to destination region. src - pointer to original dataloop structure- size - size of dataloop structure This routine parses the dataloop structure as it goes in order to determine what exactly it needs to update. Notes: It assumes that the source dataloop was allocated in our usual way; this means that the entire dataloop is in a contiguous region and that the root of the tree is first in the array. This has some implications:+ we can use a contiguous copy mechanism to copy the majority of the structure- all pointers in the region are relative to the start of the data region the first dataloop in the array is the root of the tree@*/void PREPEND_PREFIX(Dataloop_copy)(void *dest, void *src, int size){ DLOOP_Offset ptrdiff;#ifdef DLOOP_DEBUG_MEMORY DLOOP_dbg_printf("DLOOP_Dataloop_copy: copying from %x to %x (%d bytes).\n", (int) src, (int) dest, size);#endif /* copy region first */ memcpy(dest, src, size); /* Calculate difference in starting locations. DLOOP_Dataloop_update() * then traverses the new structure and updates internal pointers by * adding this difference to them. This way we can just copy the * structure, including pointers, in one big block. */ ptrdiff = (char *) dest - (char *) src; /* traverse structure updating pointers */ PREPEND_PREFIX(Dataloop_update)(dest, ptrdiff); return;}/*@ Dataloop_update - update pointers after a copy operation Input Parameters:+ dataloop - pointer to loop to update- ptrdiff - value indicating offset between old and new pointer values This function is used to recursively update all the pointers in a dataloop tree.@*/void PREPEND_PREFIX(Dataloop_update)(DLOOP_Dataloop *dataloop, DLOOP_Offset ptrdiff){ /* OPT: only declare these variables down in the Struct case */ int i; DLOOP_Dataloop **looparray; switch(dataloop->kind & DLOOP_KIND_MASK) { case DLOOP_KIND_CONTIG: case DLOOP_KIND_VECTOR: /* * All these really ugly assignments are really of the form: * * ((char *) dataloop->loop_params.c_t.loop) += ptrdiff; * * However, some compilers spit out warnings about casting on the * LHS, so we get this much nastier form instead (using common * struct for contig and vector): */ dataloop->loop_params.cm_t.dataloop = (DLOOP_Dataloop *) ((char *) dataloop->loop_params.cm_t.dataloop + ptrdiff); if (!(dataloop->kind & DLOOP_FINAL_MASK)) PREPEND_PREFIX(Dataloop_update)(dataloop->loop_params.cm_t.dataloop, ptrdiff); break; case DLOOP_KIND_BLOCKINDEXED: dataloop->loop_params.bi_t.offset_array = (DLOOP_Offset *) ((char *) dataloop->loop_params.bi_t.offset_array + ptrdiff); dataloop->loop_params.bi_t.dataloop = (DLOOP_Dataloop *) ((char *) dataloop->loop_params.bi_t.dataloop + ptrdiff); if (!(dataloop->kind & DLOOP_FINAL_MASK)) PREPEND_PREFIX(Dataloop_update)(dataloop->loop_params.bi_t.dataloop, ptrdiff); break; case DLOOP_KIND_INDEXED: dataloop->loop_params.i_t.blocksize_array = (DLOOP_Count *) ((char *) dataloop->loop_params.i_t.blocksize_array + ptrdiff); dataloop->loop_params.i_t.offset_array = (DLOOP_Offset *) ((char *) dataloop->loop_params.i_t.offset_array + ptrdiff); dataloop->loop_params.i_t.dataloop = (DLOOP_Dataloop *) ((char *) dataloop->loop_params.i_t.dataloop + ptrdiff); if (!(dataloop->kind & DLOOP_FINAL_MASK)) PREPEND_PREFIX(Dataloop_update)(dataloop->loop_params.i_t.dataloop, ptrdiff); break; case DLOOP_KIND_STRUCT: dataloop->loop_params.s_t.blocksize_array = (DLOOP_Count *) ((char *) dataloop->loop_params.s_t.blocksize_array + ptrdiff); dataloop->loop_params.s_t.offset_array = (DLOOP_Offset *) ((char *) dataloop->loop_params.s_t.offset_array + ptrdiff); dataloop->loop_params.s_t.dataloop_array = (DLOOP_Dataloop **) ((char *) dataloop->loop_params.s_t.dataloop_array + ptrdiff); /* fix the N dataloop pointers too */ looparray = dataloop->loop_params.s_t.dataloop_array; for (i=0; i < dataloop->loop_params.s_t.count; i++) { looparray[i] = (DLOOP_Dataloop *) ((char *) looparray[i] + ptrdiff); } if (dataloop->kind & DLOOP_FINAL_MASK) break; for (i=0; i < dataloop->loop_params.s_t.count; i++) { PREPEND_PREFIX(Dataloop_update)(looparray[i], ptrdiff); } break; default: /* --BEGIN ERROR HANDLING-- */ DLOOP_Assert(0); break; /* --END ERROR HANDLING-- */ } return;}/*@ Dataloop_alloc - allocate the resources used to store a dataloop with no old loops associated with it. Input Parameters:+ kind - kind of dataloop to allocate. count - number of elements in dataloop (kind dependent). new_loop_p - address at which to store new dataloop pointer- new_loop_sz_p - pointer to integer in which to store new loop size Notes: The count parameter passed into this function will often be different from the count passed in at the MPI layer due to optimizations.@*/void PREPEND_PREFIX(Dataloop_alloc)(int kind, DLOOP_Count count, DLOOP_Dataloop **new_loop_p, int *new_loop_sz_p){ PREPEND_PREFIX(Dataloop_alloc_and_copy)(kind, count, NULL, 0, new_loop_p, new_loop_sz_p); return;}/*@ Dataloop_alloc_and_copy - allocate the resources used to store a dataloop and copy in old dataloop as appropriate Input Parameters:+ kind - kind of dataloop to allocate. count - number of elements in dataloop (kind dependent). old_loop - pointer to old dataloop (or NULL for none). old_loop_sz - size of old dataloop (should be zero if old_loop is NULL). new_loop_p - address at which to store new dataloop pointer- new_loop_sz_p - pointer to integer in which to store new loop size Notes: The count parameter passed into this function will often be different from the count passed in at the MPI layer.@*/void PREPEND_PREFIX(Dataloop_alloc_and_copy)(int kind, DLOOP_Count count, DLOOP_Dataloop *old_loop, int old_loop_sz, DLOOP_Dataloop **new_loop_p, int *new_loop_sz_p){ int new_loop_sz = 0; int align_sz = 8; /* default aligns everything to 8-byte boundaries */ int epsilon; int loop_sz = sizeof(DLOOP_Dataloop); int off_sz = 0, blk_sz = 0, ptr_sz = 0, extent_sz = 0; char *pos; DLOOP_Dataloop *new_loop;#ifdef HAVE_MAX_STRUCT_ALIGNMENT if (align_sz > HAVE_MAX_STRUCT_ALIGNMENT) { align_sz = HAVE_MAX_STRUCT_ALIGNMENT; }#endif if (old_loop != NULL) { DLOOP_Assert((old_loop_sz % align_sz) == 0); } /* calculate the space that we actually need for everything */ switch (kind) { case DLOOP_KIND_STRUCT: /* need space for dataloop pointers and extents */ ptr_sz = count * sizeof(DLOOP_Dataloop *); extent_sz = count * sizeof(DLOOP_Offset); case DLOOP_KIND_INDEXED: /* need space for block sizes */ blk_sz = count * sizeof(DLOOP_Count); case DLOOP_KIND_BLOCKINDEXED: /* need space for block offsets */ off_sz = count * sizeof(DLOOP_Offset); case DLOOP_KIND_CONTIG: case DLOOP_KIND_VECTOR: break; default: DLOOP_Assert(0); } /* pad everything that we're going to allocate */ epsilon = loop_sz % align_sz; if (epsilon) loop_sz += align_sz - epsilon; epsilon = off_sz % align_sz; if (epsilon) off_sz += align_sz - epsilon; epsilon = blk_sz % align_sz; if (epsilon) blk_sz += align_sz - epsilon; epsilon = ptr_sz % align_sz; if (epsilon) ptr_sz += align_sz - epsilon; epsilon = extent_sz % align_sz; if (epsilon) extent_sz += align_sz - epsilon; new_loop_sz += loop_sz + off_sz + blk_sz + ptr_sz + extent_sz + old_loop_sz; /* allocate space */ new_loop = (DLOOP_Dataloop *) DLOOP_Malloc(new_loop_sz); if (new_loop == NULL) { *new_loop_p = NULL; return; }#ifdef DLOOP_DEBUG_MEMORY DLOOP_dbg_printf("DLOOP_Dataloop_alloc_and_copy: new loop @ %x (tot sz = %d, loop = %d, off = %d, blk = %d, ptr = %d, extent = %d, old = %d)\n", (int) new_loop, new_loop_sz, loop_sz, off_sz, blk_sz, ptr_sz, extent_sz, old_loop_sz);#endif /* set all the pointers in the new dataloop structure */ switch (kind) { case DLOOP_KIND_STRUCT: /* order is: * - pointers * - blocks * - offsets * - extents */ new_loop->loop_params.s_t.dataloop_array = (DLOOP_Dataloop **) (((char *) new_loop) + loop_sz); new_loop->loop_params.s_t.blocksize_array = (DLOOP_Count *) (((char *) new_loop) + loop_sz + ptr_sz); new_loop->loop_params.s_t.offset_array = (DLOOP_Offset *) (((char *) new_loop) + loop_sz + ptr_sz + blk_sz); new_loop->loop_params.s_t.el_extent_array = (DLOOP_Offset *) (((char *) new_loop) + loop_sz + ptr_sz + blk_sz + off_sz); break; case DLOOP_KIND_INDEXED: /* order is: * - blocks * - offsets */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -