void MPIDU_Type_calc_footprint(MPI_Datatype type, DLOOP_Type_footprint *tfp) { int mpi_errno; int nr_ints, nr_aints, nr_types, combiner; int *ints; MPI_Aint *aints; MPI_Datatype *types; /* used to store parameters for constituent types */ DLOOP_Offset size = 0, lb = 0, ub = 0, true_lb = 0, true_ub = 0; DLOOP_Offset extent = 0, alignsz; int has_sticky_lb, has_sticky_ub; /* used for vector/hvector/hvector_integer calculations */ DLOOP_Offset stride; /* used for indexed/hindexed calculations */ DLOOP_Offset disp; /* used for calculations on types with more than one block of data */ DLOOP_Offset i, min_lb, max_ub, ntypes, tmp_lb, tmp_ub; /* used for processing subarray and darray types */ int ndims; MPI_Datatype tmptype; MPIR_Type_get_envelope(type, &nr_ints, &nr_aints, &nr_types, &combiner); if (combiner == MPI_COMBINER_NAMED) { int mpisize; MPI_Aint mpiextent; MPIR_Datatype_get_size_macro(type, mpisize); MPIR_Datatype_get_extent_macro(type, mpiextent); tfp->size = (DLOOP_Offset) mpisize; tfp->lb = 0; tfp->ub = (DLOOP_Offset) mpiextent; tfp->true_lb = 0; tfp->true_ub = (DLOOP_Offset) mpiextent; tfp->extent = (DLOOP_Offset) mpiextent; tfp->alignsz = DLOOP_Named_type_alignsize(type, (MPI_Aint) 0); tfp->has_sticky_lb = (type == MPI_LB) ? 1 : 0; tfp->has_sticky_ub = (type == MPI_UB) ? 1 : 0; goto clean_exit; } /* get access to contents; need it immediately to check for zero count */ MPIDU_Type_access_contents(type, &ints, &aints, &types); /* knock out all the zero count cases */ if ((combiner == MPI_COMBINER_CONTIGUOUS || combiner == MPI_COMBINER_VECTOR || combiner == MPI_COMBINER_HVECTOR_INTEGER || combiner == MPI_COMBINER_HVECTOR || combiner == MPI_COMBINER_INDEXED_BLOCK || combiner == MPI_COMBINER_HINDEXED_BLOCK || combiner == MPI_COMBINER_INDEXED || combiner == MPI_COMBINER_HINDEXED_INTEGER || combiner == MPI_COMBINER_STRUCT_INTEGER || combiner == MPI_COMBINER_STRUCT) && ints[0] == 0) { tfp->size = tfp->lb = tfp->ub = tfp->extent = tfp->alignsz = 0; tfp->true_lb = tfp->true_ub = 0; tfp->has_sticky_lb = tfp->has_sticky_ub = 0; goto clean_exit; } if (combiner != MPI_COMBINER_STRUCT && combiner != MPI_COMBINER_STRUCT_INTEGER) { DLOOP_Type_footprint cfp; MPIDU_Type_calc_footprint(types[0], &cfp); size = cfp.size; lb = cfp.lb; ub = cfp.ub; true_lb = cfp.true_lb; true_ub = cfp.true_ub; extent = cfp.extent; alignsz = cfp.alignsz; has_sticky_lb = cfp.has_sticky_lb; has_sticky_ub = cfp.has_sticky_ub; /* initialize some common values so we don't have to assign * them in every case below. */ tfp->alignsz = alignsz; tfp->has_sticky_lb = has_sticky_lb; tfp->has_sticky_ub = has_sticky_ub; } switch(combiner) { case MPI_COMBINER_DUP: tfp->size = size; tfp->lb = lb; tfp->ub = ub; tfp->true_lb = true_lb; tfp->true_ub = true_ub; tfp->extent = extent; break; case MPI_COMBINER_RESIZED: tfp->size = size; tfp->lb = aints[0]; /* lb */ tfp->ub = aints[0] + aints[1]; tfp->true_lb = true_lb; tfp->true_ub = true_ub; tfp->extent = aints[1]; /* extent */ tfp->has_sticky_lb = 1; tfp->has_sticky_ub = 1; break; case MPI_COMBINER_CONTIGUOUS: DLOOP_DATATYPE_CONTIG_LB_UB(ints[0] /* count */, lb, ub, extent, tfp->lb, tfp->ub); tfp->true_lb = tfp->lb + (true_lb - lb); tfp->true_ub = tfp->ub + (true_ub - ub); tfp->size = (DLOOP_Offset) ints[0] * size; tfp->extent = tfp->ub - tfp->lb; break; case MPI_COMBINER_VECTOR: case MPI_COMBINER_HVECTOR: case MPI_COMBINER_HVECTOR_INTEGER: if (combiner == MPI_COMBINER_VECTOR) stride = (DLOOP_Offset) ints[2] * extent; else if (combiner == MPI_COMBINER_HVECTOR) stride = aints[0]; else /* HVECTOR_INTEGER */ stride = (DLOOP_Offset) ints[2]; DLOOP_DATATYPE_VECTOR_LB_UB(ints[0] /* count */, stride /* stride in bytes */, ints[1] /* blklen */, lb, ub, extent, tfp->lb, tfp->ub); tfp->true_lb = tfp->lb + (true_lb - lb); tfp->true_ub = tfp->ub + (true_ub - ub); tfp->size = (DLOOP_Offset) ints[0] * (DLOOP_Offset) ints[1] * size; tfp->extent = tfp->ub - tfp->lb; break; case MPI_COMBINER_INDEXED_BLOCK: /* prime min_lb and max_ub */ DLOOP_DATATYPE_BLOCK_LB_UB(ints[1] /* blklen */, (DLOOP_Offset) ints[2] * extent /* disp */, lb, ub, extent, min_lb, max_ub); for (i=1; i < ints[0]; i++) { DLOOP_DATATYPE_BLOCK_LB_UB(ints[1] /* blklen */, (DLOOP_Offset) ints[i+2] * extent /* disp */, lb, ub, extent, tmp_lb, tmp_ub); if (tmp_lb < min_lb) min_lb = tmp_lb; if (tmp_ub > max_ub) max_ub = tmp_ub; } tfp->size = (DLOOP_Offset) ints[0] * (DLOOP_Offset) ints[1] * size; tfp->lb = min_lb; tfp->ub = max_ub; tfp->true_lb = min_lb + (true_lb - lb); tfp->true_ub = max_ub + (true_ub - ub); tfp->extent = tfp->ub - tfp->lb; break; case MPI_COMBINER_HINDEXED_BLOCK: /* prime min_lb and max_ub */ DLOOP_DATATYPE_BLOCK_LB_UB(ints[1] /* blklen */, (DLOOP_Offset) ints[2] /* disp */, lb, ub, extent, min_lb, max_ub); for (i=1; i < ints[0]; i++) { DLOOP_DATATYPE_BLOCK_LB_UB(ints[1] /* blklen */, (DLOOP_Offset) ints[i+2] /* disp */, lb, ub, extent, tmp_lb, tmp_ub); if (tmp_lb < min_lb) min_lb = tmp_lb; if (tmp_ub > max_ub) max_ub = tmp_ub; } tfp->size = (DLOOP_Offset) ints[0] * (DLOOP_Offset) ints[1] * size; tfp->lb = min_lb; tfp->ub = max_ub; tfp->true_lb = min_lb + (true_lb - lb); tfp->true_ub = max_ub + (true_ub - ub); tfp->extent = tfp->ub - tfp->lb; break; case MPI_COMBINER_INDEXED: case MPI_COMBINER_HINDEXED_INTEGER: case MPI_COMBINER_HINDEXED: /* find first non-zero blocklength element */ for (i=0; i < ints[0] && ints[i+1] == 0; i++); if (i == ints[0]) { /* all zero blocklengths */ tfp->size = tfp->lb = tfp->ub = tfp->extent = tfp->alignsz = 0; tfp->has_sticky_lb = tfp->has_sticky_ub = 0; } else { /* prime min_lb, max_ub, count */ ntypes = ints[i+1]; if (combiner == MPI_COMBINER_INDEXED) disp = (DLOOP_Offset) ints[ints[0]+i+1] * extent; else if (combiner == MPI_COMBINER_HINDEXED_INTEGER) disp = (DLOOP_Offset) ints[ints[0]+i+1]; else /* MPI_COMBINER_HINDEXED */ disp = aints[i]; DLOOP_DATATYPE_BLOCK_LB_UB(ints[i+1] /* blklen */, disp, lb, ub, extent, min_lb, max_ub); for (i++; i < ints[0]; i++) { /* skip zero blocklength elements */ if (ints[i+1] == 0) continue; ntypes += ints[i+1]; if (combiner == MPI_COMBINER_INDEXED) disp = (DLOOP_Offset) ints[ints[0]+i+1] * extent; else if (combiner == MPI_COMBINER_HINDEXED_INTEGER) disp = (DLOOP_Offset) ints[ints[0]+i+1]; else /* MPI_COMBINER_HINDEXED */ disp = aints[i]; DLOOP_DATATYPE_BLOCK_LB_UB(ints[i+1], disp, lb, ub, extent, tmp_lb, tmp_ub); if (tmp_lb < min_lb) min_lb = tmp_lb; if (tmp_ub > max_ub) max_ub = tmp_ub; } tfp->size = ntypes * size; tfp->lb = min_lb; tfp->ub = max_ub; tfp->true_lb = min_lb + (true_lb - lb); tfp->true_ub = max_ub + (true_ub - ub); tfp->extent = tfp->ub - tfp->lb; } break; case MPI_COMBINER_STRUCT_INTEGER: DLOOP_Assert(combiner != MPI_COMBINER_STRUCT_INTEGER); break; case MPI_COMBINER_STRUCT: /* sufficiently complicated to pull out into separate fn */ DLOOP_Type_calc_footprint_struct(type, combiner, ints, aints, types, tfp); break; case MPI_COMBINER_SUBARRAY: ndims = ints[0]; MPIDU_Type_convert_subarray(ndims, &ints[1] /* sizes */, &ints[1+ndims] /* subsz */, &ints[1+2*ndims] /* strts */, ints[1+3*ndims] /* order */, types[0], &tmptype); MPIDU_Type_calc_footprint(tmptype, tfp); MPIR_Type_free_impl(&tmptype); break; case MPI_COMBINER_DARRAY: ndims = ints[2]; MPIDU_Type_convert_darray(ints[0] /* size */, ints[1] /* rank */, ndims, &ints[3] /* gsizes */, &ints[3+ndims] /*distribs */, &ints[3+2*ndims] /* dargs */, &ints[3+3*ndims] /* psizes */, ints[3+4*ndims] /* order */, types[0], &tmptype); MPIDU_Type_calc_footprint(tmptype, tfp); MPIR_Type_free_impl(&tmptype); break; case MPI_COMBINER_F90_REAL: case MPI_COMBINER_F90_COMPLEX: case MPI_COMBINER_F90_INTEGER: default: DLOOP_Assert(0); break; } clean_exit: MPIDU_Type_release_contents(type, &ints, &aints, &types); return; }
/* DLOOP_Type_calc_footprint_struct - calculate size, lb, ub, extent, and alignsize for a struct type */ static void DLOOP_Type_calc_footprint_struct(MPI_Datatype type, int struct_combiner, int *ints, MPI_Aint *aints, MPI_Datatype *types, DLOOP_Type_footprint *tfp) { int i, found_sticky_lb = 0, found_sticky_ub = 0, first_iter = 1; DLOOP_Offset tmp_lb, tmp_ub, tmp_extent, tmp_true_lb, tmp_true_ub; DLOOP_Offset max_alignsz = 0, tmp_size = 0, min_lb = 0, max_ub = 0; DLOOP_Offset min_true_lb = 0, max_true_ub = 0; int nr_ints, nr_aints, nr_types, combiner; /* used to store parameters for constituent types */ DLOOP_Type_footprint cfp; DLOOP_Offset size, lb, ub, true_lb, true_ub, extent, alignsz; int sticky_lb, sticky_ub; /* find first non-zero blocklength element */ for (i=0; i < ints[0] && ints[i+1] == 0; i++); if (i == ints[0]) /* all zero-length blocks */ { tfp->size = tfp->lb = tfp->ub = tfp->extent = tfp->alignsz = 0; tfp->has_sticky_lb = tfp->has_sticky_ub = 0; return; } for (; i < ints[0]; i++) { /* skip zero blocklength elements */ if (ints[i+1] == 0) continue; MPIR_Type_get_envelope(types[i], &nr_ints, &nr_aints, &nr_types, &combiner); /* opt: could just inline assignments for combiner == NAMED case */ MPIDU_Type_calc_footprint(types[i], &cfp); size = cfp.size; lb = cfp.lb; ub = cfp.ub; true_lb = cfp.true_lb; true_ub = cfp.true_ub; extent = cfp.extent; alignsz = cfp.alignsz; sticky_lb = cfp.has_sticky_lb; sticky_ub = cfp.has_sticky_ub; DLOOP_DATATYPE_BLOCK_LB_UB(ints[i+1] /* blklen */, aints[i] /* disp */, lb, ub, extent, tmp_lb, tmp_ub); tmp_true_lb = tmp_lb + (true_lb - lb); tmp_true_ub = tmp_ub + (true_ub - ub); tmp_size += size * (DLOOP_Offset) ints[i+1]; 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; } } 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; }
/*@ MPI_Type_get_envelope - get type envelope Input Parameters: . datatype - datatype to access (handle) Output Parameters: + num_integers - number of input integers used in the call constructing combiner (non-negative integer) . num_addresses - number of input addresses used in the call constructing combiner (non-negative integer) . num_datatypes - number of input datatypes used in the call constructing combiner (non-negative integer) - combiner - combiner (state) Notes: .N Fortran .N Errors .N MPI_SUCCESS @*/ int MPI_Type_get_envelope(MPI_Datatype datatype, int *num_integers, int *num_addresses, int *num_datatypes, int *combiner) { int mpi_errno = MPI_SUCCESS; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_TYPE_GET_ENVELOPE); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_TYPE_GET_ENVELOPE); /* Validate parameters, especially handles needing to be converted */ #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_DATATYPE(datatype, "datatype", mpi_errno); } MPID_END_ERROR_CHECKS; } #endif /* Validate parameters and objects (post conversion) */ #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_Datatype *datatype_ptr = NULL; /* Convert MPI object handles to object pointers */ MPIR_Datatype_get_ptr(datatype, datatype_ptr); /* Validate datatype_ptr */ MPIR_Datatype_valid_ptr(datatype_ptr, mpi_errno); /* If comm_ptr is not value, it will be reset to null */ if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPID_END_ERROR_CHECKS; } #endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ MPIR_Type_get_envelope(datatype, num_integers, num_addresses, num_datatypes, combiner); /* ... end of body of routine ... */ #ifdef HAVE_ERROR_CHECKING fn_exit: #endif MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_TYPE_GET_ENVELOPE); return mpi_errno; #ifdef HAVE_ERROR_CHECKING fn_fail: /* --BEGIN ERROR HANDLING-- */ { mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, __func__, __LINE__, MPI_ERR_OTHER, "**mpi_type_get_envelope", "**mpi_type_get_envelope %D %p %p %p %p", datatype, num_integers, num_addresses, num_datatypes, combiner); } mpi_errno = MPIR_Err_return_comm(NULL, __func__, mpi_errno); goto fn_exit; /* --END ERROR HANDLING-- */ #endif }