📄 mpid_type_struct.c
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//* * (C) 2001 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */#include <mpiimpl.h>#include <mpid_dataloop.h>#include <stdlib.h>#include <assert.h>#include <limits.h>#undef MPID_STRUCT_FLATTEN_DEBUG#undef MPID_STRUCT_DEBUGint MPID_Type_struct_alignsize(int count, MPI_Datatype *oldtype_array);int MPID_Type_struct_alignsize(int count, MPI_Datatype *oldtype_array){ int i, max_alignsize = 0, tmp_alignsize; for (i=0; i < count; i++) { /* shouldn't be called with an LB or UB, but we'll handle it nicely */ if (oldtype_array[i] == MPI_LB || oldtype_array[i] == MPI_UB) continue; else if (HANDLE_GET_KIND(oldtype_array[i]) == HANDLE_KIND_BUILTIN) { tmp_alignsize = MPID_Datatype_get_basic_size(oldtype_array[i]); } else { MPID_Datatype *dtp; MPID_Datatype_get_ptr(oldtype_array[i], dtp); tmp_alignsize = dtp->alignsize; } if (max_alignsize < tmp_alignsize) max_alignsize = tmp_alignsize; }#ifdef HAVE_MAX_STRUCT_ALIGNMENT if (max_alignsize > HAVE_MAX_STRUCT_ALIGNMENT) max_alignsize = HAVE_MAX_STRUCT_ALIGNMENT;#endif /* if we didn't calculate a maximum struct alignment (above), then the * alignment was either "largest", in which case we just use what we found, * or "unknown", in which case what we found is as good a guess as any. */ return max_alignsize;}/*@ MPID_Type_struct - create a struct datatype Input Parameters:+ count - number of blocks in vector. blocklength_array - number of elements in each block. displacement_array - offsets of blocks from start of type in bytes- oldtype_array - types (using handle) of datatypes on which vector is based Output Parameters:. newtype - handle of new struct datatype Return Value: 0 on success, -1 on failure. This version relies on other MPID_Type routines in order to create the final type. The resulting type will bear little resemblance to what was passed in, and currently get contents/envelope would not work.@*//* * THIS VERSION CONVERTS THE STRUCT INTO AN HINDEXED, SO IT'S ONLY GOOD FOR * HOMOGENOUS SYSTEMS!!! */int MPID_Type_struct(int count, int *blocklength_array, MPI_Aint *displacement_array, MPI_Datatype *oldtype_array, MPI_Datatype *newtype){ int mpi_errno = MPI_SUCCESS; int i, nr_real_types = 0, all_basics = 1, all_same = 1, has_lb_builtin = 0, has_ub_builtin = 0; MPID_Datatype *new_dtp, *old_dtp;#ifdef MPID_STRUCT_DEBUG MPIDI_Datatype_printf(oldtype_array[0], 1, displacement_array[0], blocklength_array[0], 1); for (i=1; i < count; i++) { MPIDI_Datatype_printf(oldtype_array[i], 1, displacement_array[i], blocklength_array[i], 0); }#endif if (count == 1) { /* simplest case: count == 1 */ /* NOTE: this could be done with a contig with an LB I think? */ mpi_errno = MPID_Type_indexed(count, blocklength_array, displacement_array, 1, /* displacement in bytes */ *oldtype_array, newtype);#ifdef MPID_STRUCT_DEBUG MPIDI_Datatype_printf(*newtype, 0, 0, 1, 0);#endif return mpi_errno; } if (*oldtype_array == MPI_LB) has_lb_builtin = 1; else if (*oldtype_array == MPI_UB) has_ub_builtin = 1; else if (HANDLE_GET_KIND(*oldtype_array) != HANDLE_KIND_BUILTIN) { all_basics = 0; nr_real_types = 1; } else { nr_real_types = 1; } /* have a quick look at the types to see if there are any easy simplifications * that we can make. */ for (i=1; i < count; i++) { if (oldtype_array[i] == MPI_LB) has_lb_builtin = 1; else if (oldtype_array[i] == MPI_UB) has_ub_builtin = 1; else if (HANDLE_GET_KIND(oldtype_array[i]) != HANDLE_KIND_BUILTIN) { all_basics = 0; nr_real_types++; } else /* builtin that isn't an LB or UB */ nr_real_types++; if (oldtype_array[i] != *oldtype_array) all_same = 0; } if (all_same) { /* they used the same type every time; this is just an hindexed again */ mpi_errno = MPID_Type_indexed(count, blocklength_array, displacement_array, 1, /* displacement in bytes */ *oldtype_array, newtype); /* alignsize and padding should be ok in this case */#ifdef MPID_STRUCT_DEBUG MPIDI_Datatype_printf(*newtype, 0, 0, 1, 0);#endif return mpi_errno; } else if (all_basics && !has_lb_builtin && !has_ub_builtin) { /* no derived types and no ub/lb, but not all the same -- just convert * everything to bytes. */ int *tmp_blocklength_array, alignsize, epsilon; tmp_blocklength_array = (int *) MPIU_Malloc(count * sizeof(int)); for (i=0; i < count; i++) { int sz = MPID_Datatype_get_basic_size(oldtype_array[i]); tmp_blocklength_array[i] = sz * blocklength_array[i]; } mpi_errno = MPID_Type_indexed(count, tmp_blocklength_array, displacement_array, 1, /* displacement in bytes */ MPI_BYTE, newtype); MPIU_Free(tmp_blocklength_array); /* account for padding */ MPID_Datatype_get_ptr(*newtype, new_dtp); alignsize = MPID_Type_struct_alignsize(count, oldtype_array); new_dtp->alignsize = alignsize; epsilon = new_dtp->extent % alignsize; if (epsilon) { new_dtp->ub += (alignsize - epsilon); new_dtp->extent = new_dtp->ub - new_dtp->lb; } new_dtp->element_size = -1; /* not all the same size */#ifdef MPID_STRUCT_DEBUG MPIDI_Datatype_printf(*newtype, 0, 0, 1, 0);#endif return mpi_errno; } /* end of all basics w/out lb or ub case */ /* TODO: Catch case of a single basic with an LB and/or UB; this can be done * with a contig followed by an adjustment of the LB and UB, which would be * simpler to process than the indexed that we use below. */ else if (all_basics) { /* There are only basics, but there are LBs and/or UBs that we need to * strip out. So we convert to MPI_BYTEs as before, pull out the LBs and * UBs, and then adjust the LB/UB as needed afterwards. */ int tmp_idx = 0, *tmp_blocklength_array, found_lb = 0, found_ub = 0; MPI_Aint lb_disp = 0, ub_disp = 0, *tmp_displacement_array; /* don't bother to figure out exactly how much space we really need; use * count as an upper bound instead. */ tmp_blocklength_array = (int *) MPIU_Malloc(count * sizeof(int)); tmp_displacement_array = (MPI_Aint *) MPIU_Malloc(count * sizeof(MPI_Aint)); /* pass through all the types: * - find the smallest LB * - find the largest UB * - create the tmp blocklength and displacemment arrays * - get tmp count */ for (i=0; i < count; i++) { if (oldtype_array[i] == MPI_LB) { if (!found_lb) { found_lb = 1; lb_disp = displacement_array[i]; } else if (displacement_array[i] < lb_disp) lb_disp = displacement_array[i]; } else if (oldtype_array[i] == MPI_UB) { if (!found_ub) { found_ub = 1; ub_disp = displacement_array[i]; } else if (displacement_array[i] > ub_disp) ub_disp = displacement_array[i]; } else { int sz = MPID_Datatype_get_basic_size(oldtype_array[i]); tmp_blocklength_array[tmp_idx] = sz * blocklength_array[i]; tmp_displacement_array[tmp_idx] = displacement_array[i]; tmp_idx++; } } mpi_errno = MPID_Type_indexed(tmp_idx, tmp_blocklength_array, tmp_displacement_array, 1, /* displacement in bytes */ MPI_BYTE, newtype); MPIU_Free(tmp_blocklength_array); MPIU_Free(tmp_displacement_array); if (mpi_errno != MPI_SUCCESS) return mpi_errno; /* deal with the LB and/or UB */ MPID_Datatype_get_ptr(*newtype, new_dtp); if (found_lb) { new_dtp->has_sticky_lb = 1; new_dtp->lb = lb_disp; } if (found_ub) { new_dtp->has_sticky_ub = 1; new_dtp->ub = ub_disp; } new_dtp->extent = new_dtp->ub - new_dtp->lb;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -