diff options
-rw-r--r-- | src/H5Smpio.c | 235 |
1 files changed, 150 insertions, 85 deletions
diff --git a/src/H5Smpio.c b/src/H5Smpio.c index 1f538db..fd18f7c 100644 --- a/src/H5Smpio.c +++ b/src/H5Smpio.c @@ -121,7 +121,7 @@ H5S_mpio_all_type( const H5S_t *space, const size_t elmt_size, * * Programmer: rky 980813 * - * Modifications: + * Modifications: ppw 990401 * *------------------------------------------------------------------------- */ @@ -140,12 +140,12 @@ H5S_mpio_hyper_type( const H5S_t *space, const size_t elmt_size, hsize_t count; } d[32]; - int i, err, new_rank, num_to_collapse; + int i, j, err, new_rank, num_to_collapse, stride_bytes; + int offset[32], max_xtent[32], block_length[2], displacement[2]; H5S_hyper_dim_t *diminfo; /* [rank] */ intn rank; - MPI_Datatype inner_type, outer_type; - MPI_Aint s[2]; /* array of displacements for struct type */ - MPI_Aint extent_len, start_Aint; /* for calculating d[1] */ + MPI_Datatype inner_type, outer_type, old_type[32]; + MPI_Aint extent_len; FUNC_ENTER (H5S_mpio_hyper_type, FAIL); @@ -165,13 +165,33 @@ H5S_mpio_hyper_type( const H5S_t *space, const size_t elmt_size, d[i].count = diminfo[i].count; d[i].xtent = space->extent.u.simple.size[i]; #ifdef H5Smpi_DEBUG - fprintf(stdout, "hyper_type: start=%Hd stride=%Hu count=%Hu " + HDfprintf(stdout, "hyper_type: start=%Hd stride=%Hu count=%Hu " "block=%Hu xtent=%Hu", d[i].start, d[i].strid, d[i].count, d[i].block, d[i].xtent ); if (i==0) fprintf(stdout, " rank=%d\n", rank ); else fprintf(stdout, "\n" ); #endif } + +/********************************************************************** + Compute array "offset[rank]" which gives the offsets for a multi- + dimensional array with dimensions "d[i].xtent" (i=0,1,...,rank-1). +**********************************************************************/ + offset[rank-1] = 1; + max_xtent[rank-1] = d[rank-1].xtent; +#ifdef H5Smpi_DEBUG + i=rank-1; + fprintf(stdout, " offset[%2d]=%d; max_xtent[%2d]=%d\n", + i, offset[i], i, max_xtent[i]); +#endif + for (i=rank-2; i>=0; --i) { + offset[i] = offset[i+1]*d[i+1].xtent; + max_xtent[i] = max_xtent[i+1]*d[i].xtent; +#ifdef H5Smpi_DEBUG + fprintf(stdout, " offset[%2d]=%d; max_xtent[%2d]=%d\n", + i, offset[i], i, max_xtent[i]); +#endif + } /* Create a type covering the selected hyperslab. * Multidimensional dataspaces are stored in row-major order. @@ -207,9 +227,8 @@ H5S_mpio_hyper_type( const H5S_t *space, const size_t elmt_size, } } /* end for */ num_to_collapse = i; - - num_to_collapse = 0; /* rky 980827 DEBUG Temporary change to prevent - collapsing dims until further testing of collapse */ + if (num_to_collapse == rank) num_to_collapse--; + printf ("num_to_collapse=%d\n", num_to_collapse); assert(0<=num_to_collapse && num_to_collapse<rank); new_rank = rank - num_to_collapse; @@ -218,10 +237,11 @@ H5S_mpio_hyper_type( const H5S_t *space, const size_t elmt_size, #endif /* To collapse dims, just transform dimension info (from inner to outer) */ + /* must multiply r.h.s. by "count" --- ppw 03/11/99 */ for (i=rank-1; i>=new_rank; --i) { - d[i-1].block *= d[i].strid; - d[i-1].strid *= d[i].strid; - d[i-1].xtent *= d[i].strid; + d[i-1].block *= d[i].count * d[i].block; + d[i-1].strid *= d[i].count * d[i].block; + d[i-1].xtent *= d[i].count * d[i].block; assert( d[i].start == 0 ); /* d[i-1].start stays unchanged */ /* d[i-1].count stays unchanged */ @@ -236,96 +256,140 @@ H5S_mpio_hyper_type( const H5S_t *space, const size_t elmt_size, } } - /* initialize induction variables */ - s[0] = 0; /* stays constant */ - /* create contig type for inner contig dims */ +/******************************************************* +* Construct contig type for inner contig dims: +*******************************************************/ #ifdef H5Smpi_DEBUG fprintf(stdout, "hyper_type: Making contig type %d MPI_BYTEs\n", elmt_size ); + for (i=new_rank-1; i>=0; --i) { + HDfprintf(stdout, "d[%d].xtent=%Hu \n", i, d[i].xtent); + } #endif err = MPI_Type_contiguous( (int)elmt_size, MPI_BYTE, &inner_type ); if (err) { HRETURN_ERROR(H5E_DATASPACE, H5E_MPI, FAIL,"couldn't create MPI contiguous type"); } - /* construct the type by walking the hyperslab dims from the inside out */ +/******************************************************* +* Construct the type by walking the hyperslab dims +* from the inside out: +*******************************************************/ for ( i=new_rank-1; i>=0; --i) { #ifdef H5Smpi_DEBUG - fprintf(stdout, "hyper_type: i=%d Making vector type\n" + HDfprintf(stdout, "hyper_type: Dimension i=%d \n" "count=%Hu block=%Hu stride=%Hu\n", i, d[i].count, d[i].block, d[i].strid ); #endif - err = MPI_Type_vector( (int)(d[i].count), /* count */ - (int)(d[i].block), /* blocklength */ - (MPI_Aint)(d[i].strid), /* stride */ - inner_type, /* old type */ - &outer_type ); /* new type */ - if (err) { - MPI_Type_free( &inner_type ); /* free before abort */ - HRETURN_ERROR(H5E_DATASPACE, H5E_MPI, FAIL,"couldn't create MPI vector type"); - } - /* from here to end of loop, inner_type actually will get the value - * of the outermost type: it will be inner for the next iteration */ - if (0 == d[i].start) { - /* don't need to compensate for the start displacement */ - MPI_Type_free( &inner_type ); /* old inner no longer needed */ - inner_type = outer_type; /* prepare for next iter */ - } else { - /* need to compensate for the start displacement */ - int b[2]; /* array of rep counts */ - MPI_Datatype t[2]; /* array of MPI types */ - - /* fill in the b, d, and t arrays, length is 2 */ - /* b gives rep count for each type in t */ - b[0] = 1; - b[1] = 1; - - /* s gives the byte displacement for each "field" by induction: - * for 0<=i<rank-1 s[1]_i = start[i]*extent_length[i+1]; - * with base case s[1]_(rank-1) = elmt_size (i decreasing). - * (Assuming dimension index increases as we go deeper in.) - * Note that in this loop, extent_length[i+1] is the extent length - * of the inner type (i.e., the type constructed in previous trip). - */ - err = MPI_Type_extent( inner_type, &extent_len ); - if (err) { - MPI_Type_free( &inner_type ); /* free before abort */ - MPI_Type_free( &outer_type ); /* free before abort */ - HRETURN_ERROR(H5E_DATASPACE, H5E_MPI, FAIL, - "couldn't get extent of MPI type"); - } - start_Aint = (MPI_Aint)(d[i].start); - if (start_Aint != d[i].start) { - MPI_Type_free( &inner_type ); /* free before abort */ - MPI_Type_free( &outer_type ); /* free before abort */ - HRETURN_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, - "start value overflows MPI_Aint"); - } - s[1] = start_Aint * extent_len; - - /* t gives the MPI types for the "fields" */ - /* I think we could do without the LB type and just have - * one "field" consisting of the vector type with displacement, - * but I guess there's no harm in doing it this way. */ - t[0] = MPI_LB; - t[1] = outer_type; /* the just-created vector type */ - /* Create new struct type to compensate for start displacement. - * The struct's first "field" is the displacement, - * and its second "field" is the just-created vector type */ + +#ifdef H5Smpi_DEBUG + HDfprintf(stdout, "hyper_type: i=%d Making vector-type \n", i); +#endif + /**************************************** + * Build vector in current dimension: + ****************************************/ + err = MPI_Type_vector ( (int)(d[i].count), /* count */ + (int)(d[i].block), /* blocklength */ + (MPI_Aint)(d[i].strid), /* stride */ + inner_type, /* old type */ + &outer_type ); /* new type */ + + MPI_Type_free( &inner_type ); + if (err) { + HRETURN_ERROR(H5E_DATASPACE, H5E_MPI, FAIL,"couldn't create MPI vector type"); + } + + displacement[1] = elmt_size * max_xtent[i]; + err = MPI_Type_extent(outer_type, &extent_len); + + /************************************************* + * Restructure this datatype ("outer_type") + * so that it still starts at 0, but its extent + * is the full extent in this dimension. + *************************************************/ + if ((int)extent_len < displacement[1]) { + +#ifdef H5Smpi_DEBUG + HDfprintf(stdout, "hyper_type: i=%d Extending struct type\n" + "***displacements: 0, %d\n", i, displacement[1]); +#endif + +#ifdef HAVE_MPI2 /* have MPI-2 */ + err = MPI_Type_create_resized + ( outer_type, /* old type */ + 0, /* blocklengths */ + displacement[1], /* displacements */ + &inner_type); /* new type */ +#else /* do not have MPI-2 */ + block_length[0] = 1; + block_length[1] = 1; + + displacement[0] = 0; + + old_type[0] = outer_type; + old_type[1] = MPI_UB; #ifdef H5Smpi_DEBUG - fprintf(stdout, "hyper_type: i=%d Making struct type\n" - "b[1]=%d d[1]=%Hu\n", i, b[1], (hsize_t)s[1] ); + HDfprintf(stdout, "hyper_type: i=%d Extending struct type\n" + "***displacements: 0, %d\n", i, displacement[1]); #endif - err = MPI_Type_struct( 2, b, s, t, &inner_type/*becomes outer*/ ); - MPI_Type_free( &outer_type ); /* no longer needed */ - if (err) { - HRETURN_ERROR(H5E_DATASPACE, H5E_MPI, FAIL,"couldn't create MPI struct type"); - } - } /* end else */ - /* at this point, inner_type is actually the outermost type */ + err = MPI_Type_struct ( 2, /* count */ + block_length, /* blocklengths */ + displacement, /* displacements */ + old_type, /* old types */ + &inner_type); /* new type */ +#endif + + MPI_Type_free (&outer_type); + if (err) { + HRETURN_ERROR(H5E_DATASPACE, H5E_MPI, FAIL,"couldn't resize MPI vector type"); + } + } + else { + inner_type = outer_type; + } } /* end for */ +/*************************** +* End of loop, walking +* thru dimensions. +***************************/ + + + /* At this point inner_type is actually the outermost type, even for 0-trip loop */ + +/*************************************************************** +* Final task: create a struct which is a "clone" of the +* current struct, but displaced according to the d[i].start +* values given in the hyperslab description: +***************************************************************/ + displacement[0] = 0; + for (i=new_rank-1; i>=0; i--) + displacement[0] += d[i].start * offset[i]; + + if (displacement[0] > 0) { + displacement[0] *= elmt_size; + block_length[0] = 1; + old_type[0] = inner_type; + +#ifdef H5Smpi_DEBUG + HDfprintf(stdout, "hyper_type: Making final struct\n" + "***count=1:\n"); + HDfprintf(stdout, "\tblocklength[0]=%d; displacement[0]=%d\n", + block_length[0], displacement[0]); +#endif + + err = MPI_Type_struct( 1, /* count */ + block_length, /* blocklengths */ + displacement, /* displacements */ + old_type, /* old type */ + new_type ); /* new type */ + + if (err) { + HRETURN_ERROR(H5E_DATASPACE, H5E_MPI, FAIL,"couldn't create MPI struct type"); + } + } + else { + *new_type = inner_type; + } - /* here inner_type is actually the outermost type, even for 0-trip loop */ - *new_type = inner_type; /* return the just-constructed type */ err = MPI_Type_commit( new_type ); if (err) { HRETURN_ERROR(H5E_DATASPACE, H5E_MPI, FAIL,"couldn't commit MPI vector type"); @@ -340,6 +404,7 @@ H5S_mpio_hyper_type( const H5S_t *space, const size_t elmt_size, #endif FUNC_LEAVE (SUCCEED); } /* H5S_mpio_hyper_type() */ + /*------------------------------------------------------------------------- * Function: H5S_mpio_space_type |