summaryrefslogtreecommitdiffstats
path: root/src/H5Smpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Smpio.c')
-rw-r--r--src/H5Smpio.c627
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 */