diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2010-07-19 05:05:45 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2010-07-19 05:05:45 (GMT) |
commit | f82774c0d5a59c8ff48c91bd1339eb13605b2b87 (patch) | |
tree | 68289ae6df66d56f69371c6c540de2050abaa431 /src/H5Smpio.c | |
parent | 075f618e23fdfefb104e6df289a010a884aa5a02 (diff) | |
download | hdf5-f82774c0d5a59c8ff48c91bd1339eb13605b2b87.zip hdf5-f82774c0d5a59c8ff48c91bd1339eb13605b2b87.tar.gz hdf5-f82774c0d5a59c8ff48c91bd1339eb13605b2b87.tar.bz2 |
[svn-r19092] Description:
Bring "shape same" changes from LBL branch to trunk. These changes
allow shapes that are the same, but projected into dataspaces with different
ranks to be detected correctly, and also contains code to project a dataspace
into greater/lesser number of dimensions, so the I/O can proceed in a faster
way.
These changes also contain several bug fixes and _lots_ of code
cleanups to the MPI datatype creation code.
Many other misc. code cleanup are included as well...
Tested on:
FreeBSD/32 6.3 (duty) in debug mode
FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode
Linux/32 2.6 (jam) w/PGI compilers, w/default API=1.8.x,
w/C++ & FORTRAN, w/threadsafe, in debug mode
Linux/64-amd64 2.6 (amani) w/Intel compilers, w/default API=1.6.x,
w/C++ & FORTRAN, in production mode
Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN,
w/szip filter, in production mode
Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN,
in production mode
Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in debug mode
Mac OS X/32 10.6.3 (amazon) in debug mode
Mac OS X/32 10.6.3 (amazon) w/C++ & FORTRAN, w/threadsafe,
in production mode
Diffstat (limited to 'src/H5Smpio.c')
-rw-r--r-- | src/H5Smpio.c | 627 |
1 files changed, 265 insertions, 362 deletions
diff --git a/src/H5Smpio.c b/src/H5Smpio.c index f535122..e9d0541 100644 --- a/src/H5Smpio.c +++ b/src/H5Smpio.c @@ -31,45 +31,25 @@ #include "H5Fprivate.h" /* File access */ #include "H5FDprivate.h" /* File drivers */ #include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ #include "H5Oprivate.h" /* Object headers */ #include "H5Pprivate.h" /* Property lists */ #include "H5Spkg.h" /* Dataspaces */ #ifdef H5_HAVE_PARALLEL -static herr_t -H5S_mpio_all_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ); -static herr_t -H5S_mpio_none_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ); -static herr_t -H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ); - -static herr_t -H5S_mpio_span_hyper_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ); +static herr_t H5S_mpio_all_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type); +static herr_t H5S_mpio_none_type(MPI_Datatype *new_type, int *count, + hbool_t *is_derived_type); +static herr_t H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type); +static herr_t H5S_mpio_span_hyper_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type); +static herr_t H5S_obtain_datatype(const hsize_t down[], H5S_hyper_span_t* span, + const MPI_Datatype *elmt_type, MPI_Datatype *span_type, size_t elmt_size); -static herr_t H5S_obtain_datatype(const hsize_t size[], - H5S_hyper_span_t* span,MPI_Datatype *span_type, - size_t elmt_size,int dimindex); +#define H5S_MPIO_INITIAL_ALLOC_COUNT 256 /*------------------------------------------------------------------------- @@ -82,30 +62,20 @@ static herr_t H5S_obtain_datatype(const hsize_t size[], * Outputs: *new_type the MPI type corresponding to the selection * *count how many objects of the new_type in selection * (useful if this is the buffer type for xfer) - * *extra_offset Number of bytes of offset within dataset * *is_derived_type 0 if MPI primitive type, 1 if derived * * Programmer: rky 980813 * - * Modifications: - * - * Quincey Koziol, June 18, 2002 - * Added 'extra_offset' parameter - * *------------------------------------------------------------------------- */ static herr_t -H5S_mpio_all_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ) +H5S_mpio_all_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type) { hsize_t total_bytes; - hssize_t snelmts; /*total number of elmts (signed) */ - hsize_t nelmts; /*total number of elmts */ - herr_t ret_value = SUCCEED; + hssize_t snelmts; /* Total number of elmts (signed) */ + hsize_t nelmts; /* Total number of elmts */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_all_type) @@ -121,8 +91,7 @@ H5S_mpio_all_type( const H5S_t *space, size_t elmt_size, /* fill in the return values */ *new_type = MPI_BYTE; - H5_ASSIGN_OVERFLOW(*count, total_bytes, hsize_t, size_t); - *extra_offset = 0; + H5_ASSIGN_OVERFLOW(*count, total_bytes, hsize_t, int); *is_derived_type = FALSE; done: @@ -140,32 +109,23 @@ done: * Outputs: *new_type the MPI type corresponding to the selection * *count how many objects of the new_type in selection * (useful if this is the buffer type for xfer) - * *extra_offset Number of bytes of offset within dataset * *is_derived_type 0 if MPI primitive type, 1 if derived * * Programmer: Quincey Koziol, October 29, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t -H5S_mpio_none_type( const H5S_t UNUSED *space, size_t UNUSED elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ) +H5S_mpio_none_type(MPI_Datatype *new_type, int *count, hbool_t *is_derived_type) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_mpio_none_type); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_mpio_none_type) /* fill in the return values */ *new_type = MPI_BYTE; *count = 0; - *extra_offset = 0; *is_derived_type = FALSE; - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5S_mpio_none_type() */ @@ -179,35 +139,15 @@ H5S_mpio_none_type( const H5S_t UNUSED *space, size_t UNUSED elmt_size, * Outputs: *new_type the MPI type corresponding to the selection * *count how many objects of the new_type in selection * (useful if this is the buffer type for xfer) - * *extra_offset Number of bytes of offset within dataset * *is_derived_type 0 if MPI primitive type, 1 if derived * * Programmer: rky 980813 * - * Modifications: ppw 990401 - * rky, ppw 2000-09-26 Freed old type after creating struct type. - * rky 2000-10-05 Changed displacements to be MPI_Aint. - * rky 2000-10-06 Added code for cases of empty hyperslab. - * akc, rky 2000-11-16 Replaced hard coded dimension size with - * H5S_MAX_RANK. - * - * Quincey Koziol, June 18, 2002 - * Added 'extra_offset' parameter. Also accomodate selection - * offset in MPI type built. - * - * Albert Cheng, August 4, 2004 - * Reimplemented the algorithm of forming the outer_type by - * defining it as (start, vector, extent) in one call. - * *------------------------------------------------------------------------- */ static herr_t -H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ) +H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type) { H5S_sel_iter_t sel_iter; /* Selection iteration info */ hbool_t sel_iter_init = FALSE; /* Selection iteration info has been initialized */ @@ -231,18 +171,16 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, int mpi_code; /* MPI return code */ herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_hyper_type); + FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_hyper_type) /* Check args */ HDassert(space); HDassert(sizeof(MPI_Aint) >= sizeof(elmt_size)); - if(0 == elmt_size) - goto empty; /* Initialize selection iterator */ if(H5S_select_iter_init(&sel_iter, space, elmt_size) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") - sel_iter_init = 1; /* Selection iteration info has been initialized */ + sel_iter_init = TRUE; /* Selection iteration info has been initialized */ /* Abbreviate args */ diminfo = sel_iter.u.hyp.diminfo; @@ -251,18 +189,16 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, /* make a local copy of the dimension info so we can operate with them */ /* Check if this is a "flattened" regular hyperslab selection */ - if(sel_iter.u.hyp.iter_rank!=0 && sel_iter.u.hyp.iter_rank<space->extent.rank) { + if(sel_iter.u.hyp.iter_rank != 0 && sel_iter.u.hyp.iter_rank < space->extent.rank) { /* Flattened selection */ rank = sel_iter.u.hyp.iter_rank; HDassert(rank >= 0 && rank <= H5S_MAX_RANK); /* within array bounds */ - if (0==rank) - goto empty; #ifdef H5S_DEBUG if(H5DEBUG(S)) HDfprintf(H5DEBUG(S), "%s: Flattened selection\n",FUNC); #endif - for ( i=0; i<rank; ++i) { - d[i].start = diminfo[i].start+sel_iter.u.hyp.sel_off[i]; + for(i = 0; i < rank; ++i) { + d[i].start = diminfo[i].start + sel_iter.u.hyp.sel_off[i]; d[i].strid = diminfo[i].stride; d[i].block = diminfo[i].block; d[i].count = diminfo[i].count; @@ -277,26 +213,26 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, HDfprintf(H5DEBUG(S), "\n" ); } #endif - if (0==d[i].block) + if(0 == d[i].block) goto empty; - if (0==d[i].count) + if(0 == d[i].count) goto empty; - if (0==d[i].xtent) + if(0 == d[i].xtent) goto empty; - } + } /* end for */ } /* end if */ else { /* Non-flattened selection */ rank = space->extent.rank; - HDassert(rank >= 0 && rank<=H5S_MAX_RANK); /* within array bounds */ - if (0==rank) + HDassert(rank >= 0 && rank <= H5S_MAX_RANK); /* within array bounds */ + if(0 == rank) goto empty; #ifdef H5S_DEBUG if(H5DEBUG(S)) HDfprintf(H5DEBUG(S),"%s: Non-flattened selection\n",FUNC); #endif - for ( i=0; i<rank; ++i) { - d[i].start = diminfo[i].start+space->select.offset[i]; + for(i = 0; i < rank; ++i) { + d[i].start = diminfo[i].start + space->select.offset[i]; d[i].strid = diminfo[i].stride; d[i].block = diminfo[i].block; d[i].count = diminfo[i].count; @@ -311,40 +247,37 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, HDfprintf(H5DEBUG(S), "\n" ); } #endif - if (0==d[i].block) + if(0 == d[i].block) goto empty; - if (0==d[i].count) + if(0 == d[i].count) goto empty; - if (0==d[i].xtent) + if(0 == d[i].xtent) goto empty; - } + } /* end for */ } /* end else */ /********************************************************************** 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 */ /* leave the old way */ + offset[rank - 1] = 1; + max_xtent[rank - 1] = d[rank - 1].xtent; #ifdef H5S_DEBUG - if(H5DEBUG(S)){ + if(H5DEBUG(S)) { i=rank-1; - HDfprintf(H5DEBUG(S), " offset[%2d]=%d; max_xtent[%2d]=%d\n", + HDfprintf(H5DEBUG(S), " 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; + 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 H5S_DEBUG - if(H5DEBUG(S)){ + if(H5DEBUG(S)) HDfprintf(H5DEBUG(S), " offset[%2d]=%d; max_xtent[%2d]=%d\n", i, offset[i], i, max_xtent[i]); - } #endif - - } + } /* end for */ /* Create a type covering the selected hyperslab. * Multidimensional dataspaces are stored in row-major order. @@ -356,59 +289,58 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, *******************************************************/ #ifdef H5S_DEBUG if(H5DEBUG(S)) { - HDfprintf(H5DEBUG(S), "%s: Making contig type %d MPI_BYTEs\n", FUNC,elmt_size ); + HDfprintf(H5DEBUG(S), "%s: Making contig type %Zu MPI_BYTEs\n", FUNC, elmt_size); for (i=rank-1; i>=0; --i) HDfprintf(H5DEBUG(S), "d[%d].xtent=%Hu \n", i, d[i].xtent); } #endif - if (MPI_SUCCESS != (mpi_code= MPI_Type_contiguous( (int)elmt_size, MPI_BYTE, &inner_type ))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code); + if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)elmt_size, MPI_BYTE, &inner_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code) /******************************************************* * Construct the type by walking the hyperslab dims * from the inside out: *******************************************************/ - for ( i=rank-1; i>=0; --i) { + for(i = rank - 1; i >= 0; --i) { #ifdef H5S_DEBUG - if(H5DEBUG(S)) { - HDfprintf(H5DEBUG(S), "%s: Dimension i=%d \n" + if(H5DEBUG(S)) + HDfprintf(H5DEBUG(S), "%s: Dimension i=%d \n" "start=%Hd count=%Hu block=%Hu stride=%Hu, xtent=%Hu max_xtent=%d\n", FUNC, i, d[i].start, d[i].count, d[i].block, d[i].strid, d[i].xtent, max_xtent[i]); - } #endif #ifdef H5S_DEBUG if(H5DEBUG(S)) - HDfprintf(H5DEBUG(S), "%s: i=%d Making vector-type \n", FUNC,i); + HDfprintf(H5DEBUG(S), "%s: i=%d Making vector-type \n", FUNC,i); #endif /**************************************** * Build vector type of the selection. ****************************************/ - mpi_code =MPI_Type_vector((int)(d[i].count), /* count */ - (int)(d[i].block), /* blocklength */ - (int)(d[i].strid), /* stride */ - inner_type, /* old type */ - &outer_type); /* new type */ - - MPI_Type_free( &inner_type ); - if (mpi_code!=MPI_SUCCESS) - HMPI_GOTO_ERROR(FAIL, "couldn't create MPI vector type", mpi_code); - - /**************************************** - * Then build the dimension type as (start, vector type, xtent). - ****************************************/ - /* calculate start and extent values of this dimension */ + mpi_code = MPI_Type_vector((int)(d[i].count), /* count */ + (int)(d[i].block), /* blocklength */ + (int)(d[i].strid), /* stride */ + inner_type, /* old type */ + &outer_type); /* new type */ + + MPI_Type_free(&inner_type); + if(mpi_code != MPI_SUCCESS) + HMPI_GOTO_ERROR(FAIL, "couldn't create MPI vector type", mpi_code) + + /**************************************** + * Then build the dimension type as (start, vector type, xtent). + ****************************************/ + /* calculate start and extent values of this dimension */ displacement[1] = d[i].start * offset[i] * elmt_size; displacement[2] = (MPI_Aint)elmt_size * max_xtent[i]; if(MPI_SUCCESS != (mpi_code = MPI_Type_extent(outer_type, &extent_len))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_extent failed", mpi_code); + HMPI_GOTO_ERROR(FAIL, "MPI_Type_extent failed", mpi_code) - /************************************************* - * Restructure this datatype ("outer_type") - * so that it still starts at 0, but its extent - * is the full extent in this dimension. - *************************************************/ - if (displacement[1] > 0 || (int)extent_len < displacement[2]) { + /************************************************* + * Restructure this datatype ("outer_type") + * so that it still starts at 0, but its extent + * is the full extent in this dimension. + *************************************************/ + if(displacement[1] > 0 || (int)extent_len < displacement[2]) { block_length[0] = 1; block_length[1] = 1; @@ -420,42 +352,37 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, old_types[1] = outer_type; old_types[2] = MPI_UB; #ifdef H5S_DEBUG - if(H5DEBUG(S)){ - HDfprintf(H5DEBUG(S), "%s: i=%d Extending struct type\n" - "***displacements: %d, %d, %d\n", - FUNC, i, displacement[0], displacement[1], displacement[2]); - } + if(H5DEBUG(S)) + HDfprintf(H5DEBUG(S), "%s: i=%d Extending struct type\n" + "***displacements: %ld, %ld, %ld\n", + FUNC, i, (long)displacement[0], (long)displacement[1], (long)displacement[2]); #endif - mpi_code = MPI_Type_struct ( 3, /* count */ - block_length, /* blocklengths */ - displacement, /* displacements */ - old_types, /* old types */ - &inner_type); /* new type */ - - MPI_Type_free (&outer_type); - if (mpi_code!=MPI_SUCCESS) - HMPI_GOTO_ERROR(FAIL, "couldn't resize MPI vector type", mpi_code); - } - else { + mpi_code = MPI_Type_struct(3, /* count */ + block_length, /* blocklengths */ + displacement, /* displacements */ + old_types, /* old types */ + &inner_type); /* new type */ + + MPI_Type_free(&outer_type); + if(mpi_code != MPI_SUCCESS) + HMPI_GOTO_ERROR(FAIL, "couldn't resize MPI vector type", mpi_code) + } /* end if */ + 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 */ - *new_type = inner_type; - if (MPI_SUCCESS != (mpi_code= MPI_Type_commit( new_type ))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); + if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) /* fill in the remaining return values */ *count = 1; /* only have to move one of these suckers! */ - *extra_offset = 0; *is_derived_type = TRUE; HGOTO_DONE(SUCCEED); @@ -463,24 +390,21 @@ empty: /* special case: empty hyperslab */ *new_type = MPI_BYTE; *count = 0; - *extra_offset = 0; *is_derived_type = FALSE; done: /* Release selection iterator */ - if(sel_iter_init) { - if (H5S_SELECT_ITER_RELEASE(&sel_iter)<0) - HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); - } /* end if */ + if(sel_iter_init) + if(H5S_SELECT_ITER_RELEASE(&sel_iter) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") #ifdef H5S_DEBUG - if(H5DEBUG(S)){ + if(H5DEBUG(S)) HDfprintf(H5DEBUG(S), "Leave %s, count=%ld is_derived_type=%t\n", FUNC, *count, *is_derived_type ); - } #endif - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_mpio_hyper_type() */ /*------------------------------------------------------------------------- @@ -494,68 +418,57 @@ done: * Outputs: *new_type the MPI type corresponding to the selection * *count how many objects of the new_type in selection * (useful if this is the buffer type for xfer) - * *extra_offset Number of bytes of offset within dataset * *is_derived_type 0 if MPI primitive type, 1 if derived * * Programmer: kyang * + *------------------------------------------------------------------------- */ static herr_t -H5S_mpio_span_hyper_type( const H5S_t *space, - size_t elmt_size, - MPI_Datatype *new_type,/* out: */ - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ) +H5S_mpio_span_hyper_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type) { - MPI_Datatype span_type; - H5S_hyper_span_t *ospan; - H5S_hyper_span_info_t *odown; - hsize_t *size; - int mpi_code; - herr_t ret_value = SUCCEED; + MPI_Datatype elmt_type; /* MPI datatype for an element */ + hbool_t elmt_type_is_derived = FALSE; /* Whether the element type has been created */ + MPI_Datatype span_type; /* MPI datatype for overall span tree */ + hsize_t down[H5S_MAX_RANK]; /* 'down' sizes for each dimension */ + int mpi_code; /* MPI return code */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_span_hyper_type) /* Check args */ HDassert(space); - - if(0 == elmt_size) - goto empty; - size = space->extent.size; - if(0 == size) - goto empty; - - odown = space->select.sel_info.hslab->span_lst; - if(NULL == odown) - goto empty; - ospan = odown->head; - if(NULL == ospan) - goto empty; - - /* obtain derived data type */ - if(FAIL == H5S_obtain_datatype(space->extent.size, ospan, &span_type, elmt_size, space->extent.rank)) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't obtain MPI derived data type") - + HDassert(space->extent.size); + HDassert(space->select.sel_info.hslab->span_lst); + HDassert(space->select.sel_info.hslab->span_lst->head); + + /* Create the base type for an element */ + if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)elmt_size, MPI_BYTE, &elmt_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code) + elmt_type_is_derived = TRUE; + + /* Compute 'down' sizes for each dimension */ + if(H5V_array_down(space->extent.rank, space->extent.size, down) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGETSIZE, FAIL, "couldn't compute 'down' dimension sizes") + + /* Obtain derived data type */ + if(H5S_obtain_datatype(down, space->select.sel_info.hslab->span_lst->head, &elmt_type, &span_type, elmt_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't obtain MPI derived data type") if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&span_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); - + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) *new_type = span_type; + /* fill in the remaining return values */ *count = 1; - *extra_offset = 0; *is_derived_type = TRUE; - HGOTO_DONE(SUCCEED) - -empty: - /* special case: empty hyperslab */ - *new_type = MPI_BYTE; - *count = 0; - *extra_offset = 0; - *is_derived_type = FALSE; - done: + /* Release resources */ + if(elmt_type_is_derived) + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&elmt_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_mpio_span_hyper_type() */ @@ -564,7 +477,7 @@ done: * Function: H5S_obtain datatype * * Purpose: Obtain an MPI derived datatype based on span-tree - implementation + * implementation * * Return: non-negative on success, negative on failure. * @@ -572,165 +485,169 @@ done: * * Programmer: kyang * + *------------------------------------------------------------------------- */ static herr_t -H5S_obtain_datatype(const hsize_t size[], - H5S_hyper_span_t* span, - MPI_Datatype *span_type, - size_t elmt_size, - int dimindex) +H5S_obtain_datatype(const hsize_t *down, H5S_hyper_span_t *span, + const MPI_Datatype *elmt_type, MPI_Datatype *span_type, size_t elmt_size) { - int innercount, outercount; - MPI_Datatype bas_type; - MPI_Datatype temp_type; - MPI_Datatype tempinner_type; + size_t alloc_count; /* Number of span tree nodes allocated at this level */ + size_t outercount; /* Number of span tree nodes at this level */ MPI_Datatype *inner_type = NULL; + hbool_t inner_types_freed = FALSE; /* Whether the inner_type MPI datatypes have been freed */ + hbool_t span_type_valid = FALSE; /* Whether the span_type MPI datatypes is valid */ int *blocklen = NULL; MPI_Aint *disp = NULL; - MPI_Aint stride; - H5S_hyper_span_info_t *down; - H5S_hyper_span_t *tspan; -#ifdef H5_HAVE_MPI2 - MPI_Aint sizeaint, sizedtype; -#endif /* H5_HAVE_MPI2 */ - hsize_t total_lowd, total_lowd1; - int i; - int mpi_code; - herr_t ret_value = SUCCEED; + H5S_hyper_span_t *tspan; /* Temporary pointer to span tree node */ + int mpi_code; /* MPI return status code */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5S_obtain_datatype) + /* Sanity check */ HDassert(span); - inner_type = NULL; - down = NULL; - tspan = NULL; - down = span->down; - tspan = span; - - /* Obtain the number of span tree nodes for this dimension */ - outercount = 0; - while(tspan) { - tspan = tspan->next; - outercount++; - } /* end while */ - if(outercount == 0) - HGOTO_DONE(SUCCEED) - -/* MPI2 hasn't been widely acccepted, adding H5_HAVE_MPI2 for the future use */ -#ifdef H5_HAVE_MPI2 - MPI_Type_extent(MPI_Aint, &sizeaint); - MPI_Type_extent(MPI_Datatype, &sizedtype); - - blocklen = (int *)HDcalloc((size_t)outercount, sizeof(int)); - disp = (MPI_Aint *)HDcalloc((size_t)outercount, sizeaint); - inner_type = (MPI_Datatype *)HDcalloc((size_t)outercount, sizedtype); -#else - blocklen = (int *)HDcalloc((size_t)outercount, sizeof(int)); - disp = (MPI_Aint *)HDcalloc((size_t)outercount, sizeof(MPI_Aint)); - inner_type = (MPI_Datatype *)HDcalloc((size_t)outercount, sizeof(MPI_Datatype)); -#endif - - tspan = span; - outercount = 0; + /* Allocate the initial displacement & block length buffers */ + alloc_count = H5S_MPIO_INITIAL_ALLOC_COUNT; + if(NULL == (disp = (MPI_Aint *)H5MM_malloc(alloc_count * sizeof(MPI_Aint)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of displacements") + if(NULL == (blocklen = (int *)H5MM_malloc(alloc_count * sizeof(int)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of block lengths") /* if this is the fastest changing dimension, it is the base case for derived datatype. */ - if(down == NULL) { - - HDassert(dimindex <= 1); - - if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)elmt_size, MPI_BYTE, &bas_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code); - - if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&bas_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); - + if(NULL == span->down) { + tspan = span; + outercount = 0; while(tspan) { + /* Check if we need to increase the size of the buffers */ + if(outercount >= alloc_count) { + MPI_Aint *tmp_disp; /* Temporary pointer to new displacement buffer */ + int *tmp_blocklen; /* Temporary pointer to new block length buffer */ + + /* Double the allocation count */ + alloc_count *= 2; + + /* Re-allocate the buffers */ + if(NULL == (tmp_disp = (MPI_Aint *)H5MM_realloc(disp, alloc_count * sizeof(MPI_Aint)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of displacements") + disp = tmp_disp; + if(NULL == (tmp_blocklen = (int *)H5MM_realloc(blocklen, alloc_count * sizeof(int)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of block lengths") + blocklen = tmp_blocklen; + } /* end if */ + + /* Store displacement & block length */ disp[outercount] = (MPI_Aint)elmt_size * tspan->low; blocklen[outercount] = tspan->nelem; + tspan = tspan->next; outercount++; } /* end while */ - if(MPI_SUCCESS != (mpi_code = MPI_Type_hindexed(outercount, blocklen, disp, bas_type, span_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_hindexed failed", mpi_code); + if(MPI_SUCCESS != (mpi_code = MPI_Type_hindexed((int)outercount, blocklen, disp, *elmt_type, span_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_hindexed failed", mpi_code) + span_type_valid = TRUE; } /* end if */ - else { /* dimindex is the rank of the dimension */ - - HDassert(dimindex > 1); - - /* Calculate the total bytes of the lower dimensions */ - total_lowd = 1; /* one dimension down */ - total_lowd1 = 1; /* two dimensions down */ - - for(i = dimindex - 1; i > 0; i--) - total_lowd = total_lowd * size[i]; + else { + size_t u; /* Local index variable */ - for(i = dimindex - 1; i > 1; i--) - total_lowd1 = total_lowd1 * size[i]; + if(NULL == (inner_type = (MPI_Datatype *)H5MM_malloc(alloc_count * sizeof(MPI_Datatype)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of inner MPI datatypes") + tspan = span; + outercount = 0; while(tspan) { + MPI_Datatype down_type; /* Temporary MPI datatype for a span tree node's children */ + MPI_Aint stride; /* Distance between inner MPI datatypes */ + + /* Check if we need to increase the size of the buffers */ + if(outercount >= alloc_count) { + MPI_Aint *tmp_disp; /* Temporary pointer to new displacement buffer */ + int *tmp_blocklen; /* Temporary pointer to new block length buffer */ + MPI_Datatype *tmp_inner_type; /* Temporary pointer to inner MPI datatype buffer */ + + /* Double the allocation count */ + alloc_count *= 2; + + /* Re-allocate the buffers */ + if(NULL == (tmp_disp = (MPI_Aint *)H5MM_realloc(disp, alloc_count * sizeof(MPI_Aint)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of displacements") + disp = tmp_disp; + if(NULL == (tmp_blocklen = (int *)H5MM_realloc(blocklen, alloc_count * sizeof(int)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of block lengths") + blocklen = tmp_blocklen; + if(NULL == (tmp_inner_type = (MPI_Datatype *)H5MM_realloc(inner_type, alloc_count * sizeof(MPI_Datatype)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of inner MPI datatypes") + } /* end if */ /* Displacement should be in byte and should have dimension information */ /* First using MPI Type vector to build derived data type for this span only */ /* Need to calculate the disp in byte for this dimension. */ /* Calculate the total bytes of the lower dimension */ - - disp[outercount] = tspan->low * total_lowd * elmt_size; + disp[outercount] = tspan->low * (*down) * elmt_size; blocklen[outercount] = 1; - /* generating inner derived datatype by using MPI_Type_hvector */ - if(FAIL == H5S_obtain_datatype(size, tspan->down->head, &temp_type, elmt_size, dimindex - 1)) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't obtain MPI derived data type") - - if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&temp_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); - - /* building the inner vector datatype */ - stride = total_lowd * elmt_size; - innercount = tspan->nelem; + /* Generate MPI datatype for next dimension down */ + if(H5S_obtain_datatype(down + 1, tspan->down->head, elmt_type, &down_type, elmt_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't obtain MPI derived data type") - if(MPI_SUCCESS != (mpi_code = MPI_Type_hvector(innercount, 1, stride, temp_type, &tempinner_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_hvector failed", mpi_code); + /* Build the MPI datatype for this node */ + stride = (*down) * elmt_size; + H5_CHECK_OVERFLOW(tspan->nelem, hsize_t, int) + if(MPI_SUCCESS != (mpi_code = MPI_Type_hvector((int)tspan->nelem, 1, stride, down_type, &inner_type[outercount]))) { + MPI_Type_free(&down_type); + HMPI_GOTO_ERROR(FAIL, "MPI_Type_hvector failed", mpi_code) + } /* end if */ - if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&tempinner_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); + /* Release MPI datatype for next dimension down */ + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&down_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code) - if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&temp_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code); - - inner_type[outercount] = tempinner_type; - outercount ++; tspan = tspan->next; + outercount++; } /* end while */ /* building the whole vector datatype */ - if(MPI_SUCCESS != (mpi_code = MPI_Type_struct(outercount, blocklen, disp, inner_type, span_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code); + H5_CHECK_OVERFLOW(outercount, size_t, int) + if(MPI_SUCCESS != (mpi_code = MPI_Type_struct((int)outercount, blocklen, disp, inner_type, span_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code) + span_type_valid = TRUE; + + /* Release inner node types */ + for(u = 0; u < outercount; u++) + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&inner_type[u]))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + inner_types_freed = TRUE; } /* end else */ - if(inner_type != NULL && down != NULL) { - } /* end if */ - done: + /* General cleanup */ if(inner_type != NULL) { - if(down != NULL) { - for(i = 0; i < outercount; i++) - if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&inner_type[i]))) - HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code); + if(!inner_types_freed) { + size_t u; /* Local index variable */ + + for(u = 0; u < outercount; u++) + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&inner_type[u]))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) } /* end if */ - HDfree(inner_type); + H5MM_free(inner_type); } /* end if */ if(blocklen != NULL) - HDfree(blocklen); + H5MM_free(blocklen); if(disp != NULL) - HDfree(disp); + H5MM_free(disp); + + /* Error cleanup */ + if(ret_value < 0) { + if(span_type_valid) + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(span_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_obtain_datatype() */ - /*------------------------------------------------------------------------- * Function: H5S_mpio_space_type @@ -743,49 +660,38 @@ done: * Outputs: *new_type the MPI type corresponding to the selection * *count how many objects of the new_type in selection * (useful if this is the buffer type for xfer) - * *extra_offset Number of bytes of offset within dataset * *is_derived_type 0 if MPI primitive type, 1 if derived * * Programmer: rky 980813 * - * Modifications: - * - * Quincey Koziol, June 18, 2002 - * Added 'extra_offset' parameter - * *------------------------------------------------------------------------- */ herr_t -H5S_mpio_space_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ) +H5S_mpio_space_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type) { - herr_t ret_value = SUCCEED; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_space_type); + FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_space_type) /* Check args */ HDassert(space); + HDassert(elmt_size); /* Creat MPI type based on the kind of selection */ - switch (H5S_GET_EXTENT_TYPE(space)) { + switch(H5S_GET_EXTENT_TYPE(space)) { case H5S_NULL: case H5S_SCALAR: case H5S_SIMPLE: switch(H5S_GET_SELECT_TYPE(space)) { case H5S_SEL_NONE: - if ( H5S_mpio_none_type( space, elmt_size, - /* out: */ new_type, count, extra_offset, is_derived_type ) <0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert \"all\" selection to MPI type"); + if(H5S_mpio_none_type(new_type, count, is_derived_type) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert 'none' selection to MPI type") break; case H5S_SEL_ALL: - if ( H5S_mpio_all_type( space, elmt_size, - /* out: */ new_type, count, extra_offset, is_derived_type ) <0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert \"all\" selection to MPI type"); + if(H5S_mpio_all_type(space, elmt_size, new_type, count, is_derived_type) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert 'all' selection to MPI type") break; case H5S_SEL_POINTS: @@ -794,16 +700,14 @@ H5S_mpio_space_type( const H5S_t *space, size_t elmt_size, break; case H5S_SEL_HYPERSLABS: - if((H5S_SELECT_IS_REGULAR(space) == TRUE)) { - if(H5S_mpio_hyper_type( space, elmt_size, - /* out: */ new_type, count, extra_offset, is_derived_type )<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert \"all\" selection to MPI type"); - } - else { - if(H5S_mpio_span_hyper_type( space, elmt_size, - /* out: */ new_type, count, extra_offset, is_derived_type )<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert \"all\" selection to MPI type"); - } + if((H5S_SELECT_IS_REGULAR(space) == TRUE)) { + if(H5S_mpio_hyper_type(space, elmt_size, new_type, count, is_derived_type) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert regular 'hyperslab' selection to MPI type") + } /* end if */ + else { + if(H5S_mpio_span_hyper_type(space, elmt_size, new_type, count, is_derived_type) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert irregular 'hyperslab' selection to MPI type") + } /* end else */ break; default: @@ -815,11 +719,10 @@ H5S_mpio_space_type( const H5S_t *space, size_t elmt_size, default: HDassert("unknown data space type" && 0); break; - } + } /* end switch */ done: FUNC_LEAVE_NOAPI(ret_value); -} - +} /* end H5S_mpio_space_type() */ #endif /* H5_HAVE_PARALLEL */ |