📄 typesize_support.c
字号:
if (combiner == MPI_COMBINER_NAMED) { /* NOTE: This is a special case. If a user creates a struct * with a named type at a non-zero displacement, the * alignment may be different than expected due to * special compiler rules for this case. Thus we must * over-ride the value that we obtained from * Type_calc_footprint() above. */ alignsz = DLOOP_Named_type_alignsize(types[i], aints[i]); } if (max_alignsz < alignsz) max_alignsz = alignsz; /* We save this LB if: * (1) this is our first iteration where we saw a nonzero blklen, * (2) we haven't found a sticky LB and this LB is lower than * any we have previously seen, * (3) we haven't found a sticky LB and this one is sticky, or * (4) this sticky LB is lower than any we have previously seen. */ if ((first_iter) || (!found_sticky_lb && min_lb > tmp_lb) || (!found_sticky_lb && sticky_lb) || (sticky_lb && min_lb > tmp_lb)) { min_lb = tmp_lb; if (sticky_lb) found_sticky_lb = 1; } if ((first_iter) || (!found_sticky_ub && max_ub < tmp_ub) || (!found_sticky_ub && sticky_ub) || (sticky_ub && max_ub < tmp_ub)) { max_ub = tmp_ub; if (sticky_ub) found_sticky_ub = 1; } if ((first_iter) || (tmp_true_lb > min_true_lb)) { min_true_lb = tmp_true_lb; } if ((first_iter) || (tmp_true_ub < max_true_ub)) { max_true_ub = tmp_true_ub; } first_iter = 0; } /* calculate extent, not including potential padding */ tmp_extent = max_ub - min_lb; /* account for padding if no sticky LB/UB is found */ if ((!found_sticky_lb) && (!found_sticky_ub)) { DLOOP_Offset epsilon; epsilon = (max_alignsz > 0) ? tmp_extent % max_alignsz : 0; if (epsilon) { max_ub += (max_alignsz - epsilon); tmp_extent = max_ub - min_lb; } }#if 0 printf("size = %d, extent = %d\n", (int) tmp_size, (int) tmp_extent);#endif tfp->size = tmp_size; tfp->lb = min_lb; tfp->ub = max_ub; tfp->true_lb = min_true_lb; tfp->true_ub = max_true_ub; tfp->extent = tmp_extent; tfp->alignsz = max_alignsz; tfp->has_sticky_lb = found_sticky_lb; tfp->has_sticky_ub = found_sticky_ub; return;}/* DLOOP_Named_type_alignsize - calculate alignment in bytes for a struct based on constituent elements. Returns alignment in bytes.*/static int DLOOP_Named_type_alignsize(MPI_Datatype type, MPI_Aint disp){ int alignsize = 0; static int havent_tested_align_rules = 1; static int max_intalign = 0, max_fpalign = 0; static int have_double_pos_align = 0, have_llint_pos_align = 0; static int max_doublealign = 0, max_longdoublealign = 0; if (havent_tested_align_rules) { max_intalign = DLOOP_Structalign_integer_max(); max_fpalign = DLOOP_Structalign_float_max(); max_doublealign = DLOOP_Structalign_double_max(); max_longdoublealign = DLOOP_Structalign_long_double_max(); have_double_pos_align = DLOOP_Structalign_double_position(); have_llint_pos_align = DLOOP_Structalign_llint_position(); havent_tested_align_rules = 0; } /* skip LBs, UBs, and elements with zero block length */ if (type == MPI_LB || type == MPI_UB) return 0; PMPI_Type_size(type, &alignsize); switch(type) { case MPI_FLOAT: if (alignsize > max_fpalign) alignsize = max_fpalign; break; case MPI_DOUBLE: if (alignsize > max_doublealign) alignsize = max_doublealign; if (have_double_pos_align && disp != (MPI_Aint) 0) alignsize = 4; /* would be better to test */ break; case MPI_LONG_DOUBLE: if (alignsize > max_longdoublealign) alignsize = max_longdoublealign; break; default: if (alignsize > max_intalign) alignsize = max_intalign; if (have_llint_pos_align && type == MPI_LONG_LONG_INT && disp != (MPI_Aint) 0) { alignsize = 4; /* would be better to test */ } break; } return alignsize;}/* INTERNAL STRUCT ALIGNMENT TESTS BELOW *//* from MPICH2 PAC_C_MAX_INTEGER_ALIGN test: * * Tests for max C struct integer alignment. Note that this is for *all* * integer types. * * Return value is 1, 2, 4, or 8. */static int DLOOP_Structalign_integer_max(){ int is_packed = 1; int is_two = 1; int is_four = 1; int is_eight = 1; int size, extent; struct { char a; int b; } char_int; struct { char a; short b; } char_short; struct { char a; long b; } char_long; struct { char a; int b; char c; } char_int_char; struct { char a; short b; char c; } char_short_char;#ifdef HAVE_LONG_LONG_INT struct { long long int a; char b; } lli_c; struct { char a; long long int b; } c_lli; int extent2;#endif /* assume max integer alignment isn't 8 if we don't have * an eight-byte value. */#ifdef HAVE_LONG_LONG_INT if (sizeof(int) < 8 && sizeof(long) < 8 && sizeof(long long int) < 8) is_eight = 0;#else if (sizeof(int) < 8 && sizeof(long) < 8) is_eight = 0;#endif size = sizeof(char) + sizeof(int); extent = sizeof(char_int); if (size != extent) is_packed = 0; if ( (extent % 2) != 0) is_two = 0; if ( (extent % 4) != 0) is_four = 0; if (sizeof(int) == 8 && (extent % 8) != 0) is_eight = 0; size = sizeof(char) + sizeof(short); extent = sizeof(char_short); if (size != extent) is_packed = 0; if ( (extent % 2) != 0) is_two = 0; if (sizeof(short) == 4 && (extent % 4) != 0) is_four = 0; if (sizeof(short) == 8 && (extent % 8) != 0) is_eight = 0; size = sizeof(char) + sizeof(long); extent = sizeof(char_long); if (size != extent) is_packed = 0; if ( (extent % 2) != 0) is_two = 0; if ( (extent % 4) != 0) is_four = 0; if (sizeof(long) == 8 && (extent % 8) != 0) is_eight = 0;#ifdef HAVE_LONG_LONG_INT size = sizeof(char) + sizeof(long long int); extent = sizeof(lli_c); extent2 = sizeof(c_lli); if (size != extent) is_packed = 0; if ( (extent % 2) != 0 && (extent2 % 2) != 0) is_two = 0; if ( (extent % 4) != 0 && (extent2 % 4) != 0) is_four = 0; if (sizeof(long long int) >= 8 && (extent % 8) != 0 && (extent2 % 8) != 0) is_eight = 0;#endif size = sizeof(char) + sizeof(int) + sizeof(char); extent = sizeof(char_int_char); if (size != extent) is_packed = 0; if ( (extent % 2) != 0) is_two = 0; if ( (extent % 4) != 0) is_four = 0; if (sizeof(int) == 8 && (extent % 8) != 0) is_eight = 0; size = sizeof(char) + sizeof(short) + sizeof(char); extent = sizeof(char_short_char); if (size != extent) is_packed = 0; if ( (extent % 2) != 0) is_two = 0; if (sizeof(short) == 4 && (extent % 4) != 0) is_four = 0; if (sizeof(short) == 8 && (extent % 8) != 0) is_eight = 0; if (is_eight) { is_four = 0; is_two = 0; } if (is_four) is_two = 0; DLOOP_Assert(is_packed + is_two + is_four + is_eight == 1); if (is_packed) return 1; if (is_two) return 2; if (is_four) return 4; return 8;}/* from MPICH2 PAC_C_MAX_FP_ALIGN test: * * Checks for max C struct floating point alignment. Note that * in this test we are *only* testing float types, whereas in * the original test we were testing double and long double also. * * Return value is 1, 2, 4, 8, or 16. */static int DLOOP_Structalign_float_max(){ int is_packed = 1; int is_two = 1; int is_four = 1; int is_eight = 1; int is_sixteen = 1; struct { char a; float b; } char_float; struct { float b; char a; } float_char; int size, extent1, extent2; size = sizeof(char) + sizeof(float); extent1 = sizeof(char_float); extent2 = sizeof(float_char); if (size != extent1) is_packed = 0; if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; if (sizeof(float) == 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) is_eight = 0; if (is_sixteen) { is_eight = 0; is_four = 0; is_two = 0; } if (is_eight) { is_four = 0; is_two = 0; } if (is_four) is_two = 0; DLOOP_Assert(is_packed + is_two + is_four + is_eight + is_sixteen == 1); if (is_packed) return 1; if (is_two) return 2; if (is_four) return 4; if (is_eight) return 8; return 16;}/* from MPICH2 PAC_C_MAX_DOUBLE_FP_ALIGN test: * * Determines maximum struct alignment with floats and doubles. * * Return value is 1, 2, 4, or 8. */static int DLOOP_Structalign_double_max(){ int is_packed = 1; int is_two = 1; int is_four = 1; int is_eight = 1; struct { char a; double b; } char_double; struct { double b; char a; } double_char; int size, extent1, extent2; size = sizeof(char) + sizeof(double); extent1 = sizeof(char_double); extent2 = sizeof(double_char); if (size != extent1) is_packed = 0; if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; if (sizeof(double) == 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) is_eight = 0; if (is_eight) { is_four = 0; is_two = 0; } if (is_four) is_two = 0; DLOOP_Assert(is_packed + is_two + is_four + is_eight == 1); if (is_packed) return 1; if (is_two) return 2; if (is_four) return 4; return 8;}/* from MPICH2 PAC_C_MAX_LONGDOUBLE_FP_ALIGN test: * * Determines maximum alignment of structs with long doubles. * * Return value is 1, 2, 4, 8, or 16. */static int DLOOP_Structalign_long_double_max(){ int is_packed = 1; int is_two = 1; int is_four = 1; int is_eight = 1; int is_sixteen = 1; struct { char a; long double b; } char_long_double; struct { long double b; char a; } long_double_char; struct { long double a; int b; char c; } long_double_int_char; int size, extent1, extent2; size = sizeof(char) + sizeof(long double); extent1 = sizeof(char_long_double); extent2 = sizeof(long_double_char); if (size != extent1) is_packed = 0; if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; if (sizeof(long double) >= 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) is_eight = 0; if (sizeof(long double) > 8 && (extent1 % 16) != 0 && (extent2 % 16) != 0) is_sixteen = 0; extent1 = sizeof(long_double_int_char); if ( (extent1 % 2) != 0) is_two = 0; if ( (extent1 % 4) != 0) is_four = 0; if (sizeof(long double) >= 8 && (extent1 % 8) != 0) is_eight = 0; if (sizeof(long double) > 8 && (extent1 % 16) != 0) is_sixteen = 0; if (is_sixteen) { is_eight = 0; is_four = 0; is_two = 0; } if (is_eight) { is_four = 0; is_two = 0; } if (is_four) is_two = 0; DLOOP_Assert(is_packed + is_two + is_four + is_eight + is_sixteen == 1); if (is_packed) return 1; if (is_two) return 2; if (is_four) return 4; if (is_eight) return 8; return 16;}/* from MPICH2 PAC_C_DOUBLE_POS_ALIGN test: * * Test for odd struct alignment rule that only applies max. padding when * double value is at front of type. * * Search for "Power alignment mode" for more details. * * Return value is 1 or 0. */static int DLOOP_Structalign_double_position(){ int padding_varies_by_pos = 0; struct { char a; double b; } char_double; struct { double b; char a; } double_char; int extent1, extent2; extent1 = sizeof(char_double); extent2 = sizeof(double_char); if (extent1 != extent2) padding_varies_by_pos = 1; if (padding_varies_by_pos) return 1; else return 0;}/* from MPICH2 PAC_C_LLINT_POS_ALIGN test: * Test for odd struct alignment rule that only applies max. * padding when long long int value is at front of type. * * Search for "Power alignment mode" for more details. * * Return value is 1 or 0. */static int DLOOP_Structalign_llint_position(){ int padding_varies_by_pos = 0;#ifdef HAVE_LONG_LONG_INT struct { char a; long long int b; } char_llint; struct { long long int b; char a; } llint_char; int extent1, extent2; extent1 = sizeof(char_llint); extent2 = sizeof(llint_char); if (extent1 != extent2) padding_varies_by_pos = 1;#endif if (padding_varies_by_pos) return 1; else return 0;}#if 0/* from MPICH2 PAC_C_DOUBLE_ALIGNMENT_EXCEPTION test: * * Other tests assume that there is potentially a maximum alignment * and that if there is no maximum alignment, or a type is smaller than * that value, then we align on the size of the value, with the exception * of the "position-based alignment" rules we test for separately. * * It turns out that these assumptions have fallen short in at least one * case, on MacBook Pros, where doubles are aligned on 4-byte boundaries * even when long doubles are aligned on 16-byte boundaries. So this test * is here specifically to handle this case. * * Return value is 4 or 0.*/static int double_align_exception(){ struct { char a; double b; } char_double; struct { double b; char a; } double_char; int extent1, extent2, align_4 = 0; extent1 = sizeof(char_double); extent2 = sizeof(double_char); /* we're interested in the largest value, will let separate test * deal with position-based issues. */ if (extent1 < extent2) extent1 = extent2; if ((sizeof(double) == 8) && (extent1 % 8) != 0) { if (extent1 % 4 == 0) {#ifdef HAVE_MAX_FP_ALIGNMENT if (HAVE_MAX_FP_ALIGNMENT >= 8) align_4 = 1;#else align_4 = 1;#endif } } if (align_4) return 4; else return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -