📄 segment_ops.c
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//* * (C) 2001 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include "./dataloop.h"#ifdef HAVE_ANY_INT64_T_ALIGNEMENT#define MPIR_ALIGN8_TEST(p1,p2)#else#define MPIR_ALIGN8_TEST(p1,p2) && ((((MPI_Aint)p1 | (MPI_Aint)p2) & 0x7) == 0)#endif#ifdef HAVE_ANY_INT32_T_ALIGNEMENT#define MPIR_ALIGN4_TEST(p1,p2)#else#define MPIR_ALIGN4_TEST(p1,p2) && ((((MPI_Aint)p1 | (MPI_Aint)p2) & 0x3) == 0)#endif#define MPIDI_COPY_FROM_VEC(src,dest,stride,type,nelms,count) \{ \ type * l_src = (type *)src, * l_dest = (type *)dest; \ int i, j; \ const int l_stride = stride; \ if (nelms == 1) { \ for (i=count;i!=0;i--) { \ *l_dest++ = *l_src; \ l_src = (type *) ((char *) l_src + l_stride); \ } \ } \ else { \ for (i=count; i!=0; i--) { \ for (j=0; j<nelms; j++) { \ *l_dest++ = l_src[j]; \ } \ l_src = (type *) ((char *) l_src + l_stride); \ } \ } \ dest = (char *) l_dest; \ src = (char *) l_src; \}#define MPIDI_COPY_TO_VEC(src,dest,stride,type,nelms,count) \{ \ type * l_src = (type *)src, * l_dest = (type *)dest; \ int i, j; \ const int l_stride = stride; \ if (nelms == 1) { \ for (i=count;i!=0;i--) { \ *l_dest = *l_src++; \ l_dest = (type *) ((char *) l_dest + l_stride); \ } \ } \ else { \ for (i=count; i!=0; i--) { \ for (j=0; j<nelms; j++) { \ l_dest[j] = *l_src++; \ } \ l_dest = (type *) ((char *) l_dest + l_stride); \ } \ } \ dest = (char *) l_dest; \ src = (char *) l_src; \}/* m2m_params defined in dataloop_parts.h */int PREPEND_PREFIX(Segment_contig_m2m)(DLOOP_Offset *blocks_p, DLOOP_Type el_type, DLOOP_Offset rel_off, DLOOP_Buffer unused, void *v_paramp){ DLOOP_Offset el_size; /* DLOOP_Count? */ DLOOP_Offset size; struct PREPEND_PREFIX(m2m_params) *paramp = v_paramp; DLOOP_Handle_get_size_macro(el_type, el_size); size = *blocks_p * el_size;#ifdef MPID_SU_VERBOSE dbg_printf("\t[contig unpack: do=%d, dp=%x, bp=%x, sz=%d, blksz=%d]\n", rel_off, (unsigned) bufp, (unsigned) paramp->u.unpack.unpack_buffer, el_size, (int) *blocks_p);#endif if (paramp->direction == DLOOP_M2M_TO_USERBUF) { memcpy((char *) (paramp->userbuf + rel_off), paramp->streambuf, size); } else { memcpy(paramp->streambuf, (char *) (paramp->userbuf + rel_off), size); } paramp->streambuf += size; return 0;}/* Segment_vector_m2m * * Note: this combines both packing and unpacking functionality. * * Note: this is only called when the starting position is at the beginning * of a whole block in a vector type. */int PREPEND_PREFIX(Segment_vector_m2m)(DLOOP_Offset *blocks_p, DLOOP_Count unused, DLOOP_Count blksz, DLOOP_Offset stride, DLOOP_Type el_type, DLOOP_Offset rel_off, /* into buffer */ DLOOP_Buffer unused2, void *v_paramp){ DLOOP_Count i, blocks_left, whole_count; DLOOP_Offset el_size; struct PREPEND_PREFIX(m2m_params) *paramp = v_paramp; char *cbufp; cbufp = paramp->userbuf + rel_off; DLOOP_Handle_get_size_macro(el_type, el_size); whole_count = (blksz > 0) ? (*blocks_p / blksz) : 0; blocks_left = (blksz > 0) ? (*blocks_p % blksz) : 0; if (paramp->direction == DLOOP_M2M_TO_USERBUF) { if (el_size == 8 MPIR_ALIGN8_TEST(paramp->streambuf,cbufp)) { MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, stride, int64_t, blksz, whole_count); MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, 0, int64_t, blocks_left, 1); } else if (el_size == 4 MPIR_ALIGN4_TEST(paramp->streambuf,cbufp)) { MPIDI_COPY_TO_VEC((paramp->streambuf), cbufp, stride, int32_t, blksz, whole_count); MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, 0, int32_t, blocks_left, 1); } else if (el_size == 2) { MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, stride, int16_t, blksz, whole_count); MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, 0, int16_t, blocks_left, 1); } else { for (i=0; i < whole_count; i++) { memcpy(cbufp, paramp->streambuf, blksz * el_size); paramp->streambuf += blksz * el_size; cbufp += stride; } if (blocks_left) { memcpy(cbufp, paramp->streambuf, blocks_left * el_size); paramp->streambuf += blocks_left * el_size; } } } else /* M2M_FROM_USERBUF */ { if (el_size == 8 MPIR_ALIGN8_TEST(cbufp,paramp->streambuf)) { MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, stride, int64_t, blksz, whole_count); MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, 0, int64_t, blocks_left, 1); } else if (el_size == 4 MPIR_ALIGN4_TEST(cbufp,paramp->streambuf)) { MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, stride, int32_t, blksz, whole_count); MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, 0, int32_t, blocks_left, 1); } else if (el_size == 2) { MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, stride, int16_t, blksz, whole_count); MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, 0, int16_t, blocks_left, 1); } else { for (i=0; i < whole_count; i++) { memcpy(paramp->streambuf, cbufp, blksz * el_size); paramp->streambuf += blksz * el_size; cbufp += stride; } if (blocks_left) { memcpy(paramp->streambuf, cbufp, blocks_left * el_size); paramp->streambuf += blocks_left * el_size; } } } return 0;}/* MPID_Segment_blkidx_m2m */int PREPEND_PREFIX(Segment_blkidx_m2m)(DLOOP_Offset *blocks_p, DLOOP_Count count, DLOOP_Count blocklen, DLOOP_Offset *offsetarray, DLOOP_Type el_type, DLOOP_Offset rel_off, DLOOP_Buffer unused, void *v_paramp){ DLOOP_Count curblock = 0; DLOOP_Offset el_size; DLOOP_Offset blocks_left = *blocks_p; char *cbufp; struct PREPEND_PREFIX(m2m_params) *paramp = v_paramp; DLOOP_Handle_get_size_macro(el_type, el_size); while (blocks_left) { char *src, *dest; DLOOP_Assert(curblock < count); cbufp = paramp->userbuf + rel_off + offsetarray[curblock]; if (blocklen > blocks_left) blocklen = blocks_left; if (paramp->direction == DLOOP_M2M_TO_USERBUF) { src = paramp->streambuf; dest = cbufp; } else { src = cbufp; dest = paramp->streambuf; } /* note: macro modifies dest buffer ptr, so we must reset */ if (el_size == 8 MPIR_ALIGN8_TEST(src, dest)) { MPIDI_COPY_FROM_VEC(src, dest, 0, int64_t, blocklen, 1); } else if (el_size == 4 MPIR_ALIGN4_TEST(src,dest)) { MPIDI_COPY_FROM_VEC(src, dest, 0, int32_t, blocklen, 1); } else if (el_size == 2) { MPIDI_COPY_FROM_VEC(src, dest, 0, int16_t, blocklen, 1); } else { memcpy(dest, src, blocklen * el_size); } paramp->streambuf += blocklen * el_size; blocks_left -= blocklen; curblock++; } return 0;}/* MPID_Segment_index_m2m */int PREPEND_PREFIX(Segment_index_m2m)(DLOOP_Offset *blocks_p, DLOOP_Count count, DLOOP_Count *blockarray, DLOOP_Offset *offsetarray, DLOOP_Type el_type, DLOOP_Offset rel_off, DLOOP_Buffer unused, void *v_paramp){ int curblock = 0; DLOOP_Offset el_size; DLOOP_Offset cur_block_sz, blocks_left = *blocks_p; char *cbufp; struct PREPEND_PREFIX(m2m_params) *paramp = v_paramp; DLOOP_Handle_get_size_macro(el_type, el_size); while (blocks_left) { char *src, *dest; DLOOP_Assert(curblock < count); cur_block_sz = blockarray[curblock]; cbufp = paramp->userbuf + rel_off + offsetarray[curblock]; if (cur_block_sz > blocks_left) cur_block_sz = blocks_left; if (paramp->direction == DLOOP_M2M_TO_USERBUF) { src = paramp->streambuf; dest = cbufp; } else { src = cbufp; dest = paramp->streambuf; } /* note: macro modifies dest buffer ptr, so we must reset */ if (el_size == 8 MPIR_ALIGN8_TEST(src, dest)) { MPIDI_COPY_FROM_VEC(src, dest, 0, int64_t, cur_block_sz, 1); } else if (el_size == 4 MPIR_ALIGN4_TEST(src,dest)) { MPIDI_COPY_FROM_VEC(src, dest, 0, int32_t, cur_block_sz, 1); } else if (el_size == 2) { MPIDI_COPY_FROM_VEC(src, dest, 0, int16_t, cur_block_sz, 1); } else { memcpy(dest, src, cur_block_sz * el_size); } paramp->streambuf += cur_block_sz * el_size; blocks_left -= cur_block_sz; curblock++; } return 0;}void PREPEND_PREFIX(Segment_pack)(DLOOP_Segment *segp, DLOOP_Offset first, DLOOP_Offset *lastp, void *streambuf){ struct PREPEND_PREFIX(m2m_params) params; /* experimenting with discarding buf value in the segment, keeping in * per-use structure instead. would require moving the parameters around a * bit. same applies to Segment_unpack below. */ params.userbuf = segp->ptr; params.streambuf = streambuf; params.direction = DLOOP_M2M_FROM_USERBUF; PREPEND_PREFIX(Segment_manipulate)(segp, first, lastp, PREPEND_PREFIX(Segment_contig_m2m), PREPEND_PREFIX(Segment_vector_m2m), PREPEND_PREFIX(Segment_blkidx_m2m), PREPEND_PREFIX(Segment_index_m2m), NULL, /* size fn */ ¶ms); return;}void PREPEND_PREFIX(Segment_unpack)(DLOOP_Segment *segp, DLOOP_Offset first, DLOOP_Offset *lastp, void *streambuf){ struct PREPEND_PREFIX(m2m_params) params; params.userbuf = segp->ptr; params.streambuf = streambuf; params.direction = DLOOP_M2M_TO_USERBUF; PREPEND_PREFIX(Segment_manipulate)(segp, first, lastp, PREPEND_PREFIX(Segment_contig_m2m), PREPEND_PREFIX(Segment_vector_m2m), PREPEND_PREFIX(Segment_blkidx_m2m), PREPEND_PREFIX(Segment_index_m2m), NULL, /* size fn */ ¶ms); return;}struct PREPEND_PREFIX(contig_blocks_params) { DLOOP_Count count; DLOOP_Offset last_loc;};/* MPID_Segment_contig_count_block * * Note: because bufp is just an offset, we can ignore it in our * calculations of # of contig regions. */static int DLOOP_Segment_contig_count_block(DLOOP_Offset *blocks_p, DLOOP_Type el_type, DLOOP_Offset rel_off, DLOOP_Buffer unused, void *v_paramp){ DLOOP_Offset size, el_size; struct PREPEND_PREFIX(contig_blocks_params) *paramp = v_paramp; DLOOP_Assert(*blocks_p > 0); DLOOP_Handle_get_size_macro(el_type, el_size); size = *blocks_p * el_size;#ifdef MPID_SP_VERBOSE MPIU_dbg_printf("contig count block: count = %d, buf+off = %d, lastloc = %d\n", (int) paramp->count,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -