📄 segment_ops.c
字号:
return 0;}/* DLOOP_Segment_index_count_block * * Note: this is only called when the starting position is at the * beginning of a whole block in an indexed type. */static int DLOOP_Segment_index_count_block(DLOOP_Offset *blocks_p, DLOOP_Count count, DLOOP_Count *blockarray, DLOOP_Offset *offsetarray, DLOOP_Type el_type, DLOOP_Offset rel_off, void *bufp, /* unused */ void *v_paramp){ DLOOP_Count new_blk_count; DLOOP_Offset el_size, last_loc; struct PREPEND_PREFIX(contig_blocks_params) *paramp = v_paramp; DLOOP_Assert(count > 0 && *blocks_p > 0); DLOOP_Handle_get_size_macro(el_type, el_size); new_blk_count = count; if (paramp->count > 0 && ((rel_off + offsetarray[0]) == paramp->last_loc)) { /* first block sits at end of last block */ new_blk_count--; } /* Note: when we build an indexed type we combine adjacent regions, * so we're not going to go through and check every piece * separately here. if someone else were building indexed * dataloops by hand, then the loop here might be necessary. * DLOOP_Count i and DLOOP_Offset size would need to be * declared above. */#if 0 last_loc = rel_off * offsetarray[0] + blockarray[0] * el_size; for (i=1; i < count; i++) { if (last_loc == rel_off + offsetarray[i]) new_blk_count--; last_loc = rel_off + offsetarray[i] + blockarray[i] * el_size; }#else last_loc = rel_off + offsetarray[count-1] + blockarray[count-1] * el_size;#endif paramp->last_loc = last_loc; paramp->count += new_blk_count; return 0;}/* DLOOP_Segment_count_contig_blocks() * * Count number of contiguous regions in segment between first and last. */void PREPEND_PREFIX(Segment_count_contig_blocks)(DLOOP_Segment *segp, DLOOP_Offset first, DLOOP_Offset *lastp, DLOOP_Count *countp){ struct PREPEND_PREFIX(contig_blocks_params) params; params.count = 0; params.last_loc = 0; /* FIXME: The blkidx and index functions are not used since they * optimize the count by coalescing contiguous segments, while * functions using the count do not optimize in the same way * (e.g., flatten code) */ PREPEND_PREFIX(Segment_manipulate)(segp, first, lastp, DLOOP_Segment_contig_count_block, DLOOP_Segment_vector_count_block, DLOOP_Segment_blkidx_count_block, DLOOP_Segment_index_count_block, NULL, /* size fn */ (void *) ¶ms); *countp = params.count; return;}/********** FUNCTIONS FOR FLATTENING INTO MPI OFFSETS AND BLKLENS **********//* Segment_mpi_flatten * * Flattens into a set of blocklengths and displacements, as in an * MPI hindexed type. Note that we use appropriately-sized variables * in the associated params structure for this reason. * * NOTE: blocks will be in units of bytes when returned. * * WARNING: there's potential for overflow here as we convert from * various types into an index of bytes. */struct PREPEND_PREFIX(mpi_flatten_params) { int index, length; MPI_Aint last_end; int *blklens; MPI_Aint *disps;};/* DLOOP_Segment_contig_mpi_flatten * */static int DLOOP_Segment_contig_mpi_flatten(DLOOP_Offset *blocks_p, DLOOP_Type el_type, DLOOP_Offset rel_off, void *bufp, void *v_paramp){ int last_idx, size; DLOOP_Offset el_size; char *last_end = NULL; struct PREPEND_PREFIX(mpi_flatten_params) *paramp = v_paramp; DLOOP_Handle_get_size_macro(el_type, el_size); size = *blocks_p * (int) el_size; last_idx = paramp->index - 1; if (last_idx >= 0) { last_end = ((char *) paramp->disps[last_idx]) + paramp->blklens[last_idx]; } if ((last_idx == paramp->length-1) && (last_end != ((char *) bufp + rel_off))) { /* we have used up all our entries, and this region doesn't fit on * the end of the last one. setting blocks to 0 tells manipulation * function that we are done (and that we didn't process any blocks). */ *blocks_p = 0; return 1; } else if (last_idx >= 0 && (last_end == ((char *) bufp + rel_off))) { /* add this size to the last vector rather than using up another one */ paramp->blklens[last_idx] += size; } else { paramp->disps[last_idx+1] = (MPI_Aint) ((char *) bufp + rel_off); paramp->blklens[last_idx+1] = size; paramp->index++; } return 0;}/* DLOOP_Segment_vector_mpi_flatten * * Input Parameters: * blocks_p - [inout] pointer to a count of blocks (total, for all noncontiguous pieces) * count - # of noncontiguous regions * blksz - size of each noncontiguous region * stride - distance in bytes from start of one region to start of next * el_type - elemental type (e.g. MPI_INT) * ... * * Note: this is only called when the starting position is at the beginning * of a whole block in a vector type. * * TODO: MAKE THIS CODE SMARTER, USING THE SAME GENERAL APPROACH AS IN THE * COUNT BLOCK CODE ABOVE. */static int DLOOP_Segment_vector_mpi_flatten(DLOOP_Offset *blocks_p, DLOOP_Count count, DLOOP_Count blksz, DLOOP_Offset stride, DLOOP_Type el_type, DLOOP_Offset rel_off, /* offset into buffer */ void *bufp, /* start of buffer */ void *v_paramp){ int i, size, blocks_left; DLOOP_Offset el_size; struct PREPEND_PREFIX(mpi_flatten_params) *paramp = v_paramp; DLOOP_Handle_get_size_macro(el_type, el_size); blocks_left = *blocks_p; for (i=0; i < count && blocks_left > 0; i++) { int last_idx; char *last_end = NULL; if (blocks_left > blksz) { size = blksz * (int) el_size; blocks_left -= blksz; } else { /* last pass */ size = blocks_left * (int) el_size; blocks_left = 0; } last_idx = paramp->index - 1; if (last_idx >= 0) { last_end = ((char *) paramp->disps[last_idx]) + paramp->blklens[last_idx]; } if ((last_idx == paramp->length-1) && (last_end != ((char *) bufp + rel_off))) { /* we have used up all our entries, and this one doesn't fit on * the end of the last one. */ *blocks_p -= (blocks_left + (size / (int) el_size));#ifdef MPID_SP_VERBOSE MPIU_dbg_printf("\t[vector to vec exiting (1): next ind = %d, %d blocks processed.\n", paramp->u.pack_vector.index, (int) *blocks_p);#endif return 1; } else if (last_idx >= 0 && (last_end == ((char *) bufp + rel_off))) { /* add this size to the last vector rather than using up new one */ paramp->blklens[last_idx] += size; } else { paramp->disps[last_idx+1] = (MPI_Aint) ((char *) bufp + rel_off); paramp->blklens[last_idx+1] = size; paramp->index++; } rel_off += stride; }#ifdef MPID_SP_VERBOSE MPIU_dbg_printf("\t[vector to vec exiting (2): next ind = %d, %d blocks processed.\n", paramp->u.pack_vector.index, (int) *blocks_p);#endif /* if we get here then we processed ALL the blocks; don't need to update * blocks_p */ DLOOP_Assert(blocks_left == 0); return 0;}static int DLOOP_Segment_blkidx_mpi_flatten(DLOOP_Offset *blocks_p, DLOOP_Count count, DLOOP_Count blksz, DLOOP_Offset *offsetarray, DLOOP_Type el_type, DLOOP_Offset rel_off, void *bufp, /* unused */ void *v_paramp){ int i, size, blocks_left; DLOOP_Offset el_size; struct PREPEND_PREFIX(mpi_flatten_params) *paramp = v_paramp; DLOOP_Handle_get_size_macro(el_type, el_size); blocks_left = *blocks_p; for (i=0; i < count && blocks_left > 0; i++) { int last_idx; char *last_end = NULL; if (blocks_left > blksz) { size = blksz * (int) el_size; blocks_left -= blksz; } else { /* last pass */ size = blocks_left * (int) el_size; blocks_left = 0; } last_idx = paramp->index - 1; if (last_idx >= 0) { last_end = ((char *) paramp->disps[last_idx]) + paramp->blklens[last_idx]; } if ((last_idx == paramp->length-1) && (last_end != ((char *) bufp + rel_off))) { /* we have used up all our entries, and this one doesn't fit on * the end of the last one. */ *blocks_p -= (blocks_left + (size / (int) el_size));#ifdef MPID_SP_VERBOSE MPIU_dbg_printf("\t[vector to vec exiting (1): next ind = %d, %d blocks processed.\n", paramp->u.pack_vector.index, (int) *blocks_p);#endif return 1; } else if (last_idx >= 0 && (last_end == ((char *) bufp + rel_off))) { /* add this size to the last vector rather than using up new one */ paramp->blklens[last_idx] += size; } else { paramp->disps[last_idx+1] = (MPI_Aint) ((char *) bufp + rel_off + offsetarray[last_idx+1]); paramp->blklens[last_idx+1] = size; paramp->index++; } rel_off += offsetarray[i]; }#ifdef MPID_SP_VERBOSE MPIU_dbg_printf("\t[vector to vec exiting (2): next ind = %d, %d blocks processed.\n", paramp->u.pack_vector.index, (int) *blocks_p);#endif /* if we get here then we processed ALL the blocks; don't need to update * blocks_p */ DLOOP_Assert(blocks_left == 0); return 0;}static int DLOOP_Segment_index_mpi_flatten(DLOOP_Offset *blocks_p, DLOOP_Count count, DLOOP_Count *blockarray, DLOOP_Offset *offsetarray, DLOOP_Type el_type, DLOOP_Offset rel_off, void *bufp, /* unused */ void *v_paramp){ int i, size, blocks_left; DLOOP_Offset el_size; struct PREPEND_PREFIX(mpi_flatten_params) *paramp = v_paramp; DLOOP_Handle_get_size_macro(el_type, el_size); blocks_left = *blocks_p; for (i=0; i < count && blocks_left > 0; i++) { int last_idx; char *last_end = NULL; if (blocks_left > blockarray[i]) { size = blockarray[i] * (int) el_size; blocks_left -= blockarray[i]; } else { /* last pass */ size = blocks_left * (int) el_size; blocks_left = 0; } last_idx = paramp->index - 1; if (last_idx >= 0) { last_end = ((char *) paramp->disps[last_idx]) + paramp->blklens[last_idx]; } if ((last_idx == paramp->length-1) && (last_end != ((char *) bufp + rel_off))) { /* we have used up all our entries, and this one doesn't fit on * the end of the last one. */ *blocks_p -= (blocks_left + (size / (int) el_size));#ifdef MPID_SP_VERBOSE MPIU_dbg_printf("\t[vector to vec exiting (1): next ind = %d, %d blocks processed.\n", paramp->u.pack_vector.index, (int) *blocks_p);#endif return 1; } else if (last_idx >= 0 && (last_end == ((char *) bufp + rel_off))) { /* add this size to the last vector rather than using up new one */ paramp->blklens[last_idx] += size; } else { paramp->disps[last_idx+1] = (MPI_Aint) ((char *) bufp + rel_off + offsetarray[last_idx+1]); paramp->blklens[last_idx+1] = size; paramp->index++; } rel_off += offsetarray[i]; }#ifdef MPID_SP_VERBOSE MPIU_dbg_printf("\t[vector to vec exiting (2): next ind = %d, %d blocks processed.\n", paramp->u.pack_vector.index, (int) *blocks_p);#endif /* if we get here then we processed ALL the blocks; don't need to update * blocks_p */ DLOOP_Assert(blocks_left == 0); return 0;}/* MPID_Segment_mpi_flatten - flatten a type into a representation * appropriate for passing to hindexed create. * * Parameters: * segp - pointer to segment structure * first - first byte in segment to pack * lastp - in/out parameter describing last byte to pack (and afterwards * the last byte _actually_ packed) * NOTE: actually returns index of byte _after_ last one packed * blklens, disps - the usual blocklength and displacement arrays for MPI * lengthp - in/out parameter describing length of array (and afterwards * the amount of the array that has actual data) */void PREPEND_PREFIX(Segment_mpi_flatten)(DLOOP_Segment *segp, DLOOP_Offset first, DLOOP_Offset *lastp, int *blklens, MPI_Aint *disps, int *lengthp){ struct PREPEND_PREFIX(mpi_flatten_params) params; DLOOP_Assert(*lengthp > 0); params.index = 0; params.length = *lengthp; params.blklens = blklens; params.disps = disps; PREPEND_PREFIX(Segment_manipulate)(segp, first, lastp, DLOOP_Segment_contig_mpi_flatten, DLOOP_Segment_vector_mpi_flatten, NULL, /* DLOOP_Segment_blkidx_mpi_flatten, */ NULL, /* DLOOP_Segment_index_mpi_flatten, */ NULL, ¶ms); /* last value already handled by MPID_Segment_manipulate */ *lengthp = params.index; return;}/* * Local variables: * c-indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -