summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2002-04-03 17:07:14 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2002-04-03 17:07:14 (GMT)
commit7ae00db7a4a4e8330245b15aa1e2fa1659cb9b1b (patch)
treea01c9d03f52334938852b8f509bbe6bc8bcdac36
parentad641fa7b617c8ca2ec11602cde0f72fa12696cd (diff)
downloadhdf5-7ae00db7a4a4e8330245b15aa1e2fa1659cb9b1b.zip
hdf5-7ae00db7a4a4e8330245b15aa1e2fa1659cb9b1b.tar.gz
hdf5-7ae00db7a4a4e8330245b15aa1e2fa1659cb9b1b.tar.bz2
[svn-r5138] Purpose:
Bug Fix & Code Cleanup Description: The MPI-IO optimized transfer routines (H5S_mpio_spaces_read/H5S_mpio_space_write) are not being invoked in all the cases where they could be used. Additionally, the code for determining if an optimized transfer is wrapped into the actual I/O transfer routine in a very confusing way. Solution: Re-enabled MPI-IO optimized transfer routines in all the cases where they should work. Extracted all the pre-conditions for optimized transfers into separate routines from the transfer routines. Platforms tested: FreeBSD 4.5 (sleipnir) & IRIX64 6.5 (modi4)
-rw-r--r--release_docs/RELEASE.txt2
-rw-r--r--src/H5D.c61
-rw-r--r--src/H5S.c89
-rw-r--r--src/H5Sall.c101
-rw-r--r--src/H5Shyper.c43
-rw-r--r--src/H5Smpio.c107
-rw-r--r--src/H5Spkg.h15
-rw-r--r--src/H5Spoint.c42
-rw-r--r--src/H5Sprivate.h36
-rw-r--r--src/H5Sselect.c171
10 files changed, 517 insertions, 150 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 90e2386..f477b99 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -156,6 +156,8 @@ Documentation
New Features
============
+ * Improved performance of "regular" hyperslab I/O when using MPI-IO and the
+ datatype conversion is unneccessary. QAK - 2002/04/02
* Improved performance of single hyperslab I/O when datatype conversion is
unneccessary. QAK - 2002/04/02
* Added new "H5Sget_select_type" API function to determine which type of
diff --git a/src/H5D.c b/src/H5D.c
index acfd055..2b0b717 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -1969,6 +1969,10 @@ H5D_close(H5D_t *dataset)
* Raymond Lu, 2001-10-2
* Changed the way to retrieve property for generic property list.
*
+ * QAK - 2002/04/02
+ * Removed the must_convert parameter and move preconditions to
+ * H5S_<foo>_opt_possible() routine
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -1994,7 +1998,6 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
hsize_t request_nelmts; /*requested strip mine */
H5T_bkg_t need_bkg; /*type of background buf*/
H5S_t *free_this_space=NULL; /*data space to free */
- hbool_t must_convert; /*have to xfer the slow way*/
#ifdef H5_HAVE_PARALLEL
H5FD_mpio_dxpl_t *dx = NULL;
H5FD_mpio_xfer_t xfer_mode; /*xfer_mode for this request */
@@ -2089,6 +2092,24 @@ printf("%s: check 1.0, nelmts=%d, H5S_get_select_npoints(file_space)=%d\n",FUNC,
HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion");
} /* end if */
+ /* Set the storage flags for the space conversion check */
+ switch(dataset->layout.type) {
+ case H5D_COMPACT:
+ sconv_flags |= H5S_CONV_STORAGE_COMPACT;
+ break;
+
+ case H5D_CONTIGUOUS:
+ sconv_flags |= H5S_CONV_STORAGE_CONTIGUOUS;
+ break;
+
+ case H5D_CHUNKED:
+ sconv_flags |= H5S_CONV_STORAGE_CHUNKED;
+ break;
+
+ default:
+ assert(0 && "Unhandled layout type!");
+ } /* end switch */
+
/* Get dataspace functions */
if (NULL==(sconv=H5S_find(mem_space, file_space, sconv_flags)))
HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert from file to memory data space");
@@ -2112,15 +2133,11 @@ printf("%s: check 1.1, \n",FUNC);
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get external file list");
status = (sconv->read)(dataset->ent.file, &(dataset->layout), &pline,
&fill, &efl, H5T_get_size(dataset->type), file_space,
- mem_space, dxpl_id, buf/*out*/, &must_convert);
+ mem_space, dxpl_id, buf/*out*/);
/* Supports only no conversion, type or space, for now. */
- if (status<0)
+ if (status<0) {
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed");
-
- if (must_convert) {
- /* sconv->read cannot do a direct transfer;
- * fall through and xfer the data in the more roundabout way */
} else {
/* direct xfer accomplished successfully */
#ifdef H5S_DEBUG
@@ -2424,6 +2441,10 @@ done:
* Raymond Lu, 2001-10-2
* Changed the way to retrieve property for generic property list.
*
+ * QAK - 2002/04/02
+ * Removed the must_convert parameter and move preconditions to
+ * H5S_<foo>_opt_possible() routine
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -2449,7 +2470,6 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
hsize_t request_nelmts; /*requested strip mine */
H5T_bkg_t need_bkg; /*type of background buf*/
H5S_t *free_this_space=NULL; /*data space to free */
- hbool_t must_convert; /*have to xfer the slow way*/
#ifdef H5_HAVE_PARALLEL
H5FD_mpio_dxpl_t *dx = NULL;
H5FD_mpio_xfer_t xfer_mode; /*xfer_mode for this request */
@@ -2571,6 +2591,24 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
printf("%s: check 0.6, after H5T_find, tpath=%p, tpath->name=%s\n",FUNC,tpath,tpath->name);
#endif /* QAK */
+ /* Set the storage flags for the space conversion check */
+ switch(dataset->layout.type) {
+ case H5D_COMPACT:
+ sconv_flags |= H5S_CONV_STORAGE_COMPACT;
+ break;
+
+ case H5D_CONTIGUOUS:
+ sconv_flags |= H5S_CONV_STORAGE_CONTIGUOUS;
+ break;
+
+ case H5D_CHUNKED:
+ sconv_flags |= H5S_CONV_STORAGE_CHUNKED;
+ break;
+
+ default:
+ assert(0 && "Unhandled layout type!");
+ } /* end switch */
+
/* Get dataspace functions */
if (NULL==(sconv=H5S_find(mem_space, file_space, sconv_flags)))
HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert from memory to file data space");
@@ -2594,14 +2632,11 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get external file list");
status = (sconv->write)(dataset->ent.file, &(dataset->layout), &pline,
&fill, &efl, H5T_get_size(dataset->type), file_space,
- mem_space, dxpl_id, buf/*out*/, &must_convert);
+ mem_space, dxpl_id, buf/*out*/);
/* Supports only no conversion, type or space, for now. */
- if (status<0)
+ if (status<0) {
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed");
- if (must_convert) {
- /* sconv->write cannot do a direct transfer;
- * fall through and xfer the data in the more roundabout way */
} else {
/* direct xfer accomplished successfully */
#ifdef H5S_DEBUG
diff --git a/src/H5S.c b/src/H5S.c
index 20241a8..383c851 100644
--- a/src/H5S.c
+++ b/src/H5S.c
@@ -1497,7 +1497,7 @@ H5S_conv_t *
H5S_find (const H5S_t *mem_space, const H5S_t *file_space, unsigned flags)
{
H5S_conv_t *path; /* Space conversion path */
- htri_t c1,c2; /* Flags whether a selection is contiguous */
+ htri_t opt; /* Flag whether a selection is optimizable */
size_t i; /* Index variable */
FUNC_ENTER (H5S_find, NULL);
@@ -1522,33 +1522,41 @@ H5S_find (const H5S_t *mem_space, const H5S_t *file_space, unsigned flags)
for (i=0; i<H5S_nconv_g; i++) {
if (H5S_conv_g[i]->f->type==file_space->select.type &&
H5S_conv_g[i]->m->type==mem_space->select.type) {
+
+#ifdef H5_HAVE_PARALLEL
/*
- * Initialize direct read/write functions
+ * Check if we can set direct MPI-IO read/write functions
*/
- c1=H5S_select_single(file_space);
- c2=H5S_select_single(mem_space);
- if(c1==FAIL || c2==FAIL)
+ opt=H5S_mpio_opt_possible(mem_space,file_space,flags);
+ if(opt==FAIL)
HRETURN_ERROR(H5E_DATASPACE, H5E_BADRANGE, NULL, "invalid check for contiguous dataspace ");
- if (c1==TRUE && c2==TRUE) {
-#ifdef H5_HAVE_PARALLEL
- if(flags&H5S_CONV_PAR_IO_POSSIBLE) {
- H5S_conv_g[i]->read = H5S_mpio_spaces_read;
- H5S_conv_g[i]->write = H5S_mpio_spaces_write;
- } /* end if */
- else {
+ /* Check if we can use the optimized parallel I/O routines */
+ if(opt==TRUE) {
+ H5S_conv_g[i]->read = H5S_mpio_spaces_read;
+ H5S_conv_g[i]->write = H5S_mpio_spaces_write;
+ } /* end if */
+ else {
+#endif /* H5_HAVE_PARALLEL */
+ /*
+ * Check if we can set direct "all" read/write functions
+ */
+ opt=H5S_all_opt_possible(mem_space,file_space,flags);
+ if(opt==FAIL)
+ HRETURN_ERROR(H5E_DATASPACE, H5E_BADRANGE, NULL, "invalid check for contiguous dataspace ");
+
+ /* Check if we can use the optimized "all" I/O routines */
+ if(opt==TRUE) {
H5S_conv_g[i]->read = H5S_all_read;
H5S_conv_g[i]->write = H5S_all_write;
+ } /* end if */
+ else {
+ H5S_conv_g[i]->read = NULL;
+ H5S_conv_g[i]->write = NULL;
} /* end else */
-#else /* H5_HAVE_PARALLEL */
- H5S_conv_g[i]->read = H5S_all_read;
- H5S_conv_g[i]->write = H5S_all_write;
+#ifdef H5_HAVE_PARALLEL
+ } /* end else */
#endif /* H5_HAVE_PARALLEL */
- }
- else {
- H5S_conv_g[i]->read = NULL;
- H5S_conv_g[i]->write = NULL;
- }
HRETURN(H5S_conv_g[i]);
}
@@ -1571,29 +1579,40 @@ H5S_find (const H5S_t *mem_space, const H5S_t *file_space, unsigned flags)
path->f = H5S_fconv_g[file_space->select.type];
path->m = H5S_mconv_g[mem_space->select.type];
+#ifdef H5_HAVE_PARALLEL
/*
- * Initialize direct read/write functions
+ * Check if we can set direct MPI-IO read/write functions
*/
- c1=H5S_select_single(file_space);
- c2=H5S_select_single(mem_space);
- if(c1==FAIL || c2==FAIL)
+ opt=H5S_mpio_opt_possible(mem_space,file_space,flags);
+ if(opt==FAIL)
HRETURN_ERROR(H5E_DATASPACE, H5E_BADRANGE, NULL, "invalid check for contiguous dataspace ");
- if (c1==TRUE && c2==TRUE) {
-#ifdef H5_HAVE_PARALLEL
- if(flags&H5S_CONV_PAR_IO_POSSIBLE) {
- path->read = H5S_mpio_spaces_read;
- path->write = H5S_mpio_spaces_write;
- } /* end if */
- else {
+ /* Check if we can use the optimized parallel I/O routines */
+ if(opt==TRUE) {
+ path->read = H5S_mpio_spaces_read;
+ path->write = H5S_mpio_spaces_write;
+ } /* end if */
+ else {
+#endif /* H5_HAVE_PARALLEL */
+ /*
+ * Check if we can set direct "all" read/write functions
+ */
+ opt=H5S_all_opt_possible(mem_space,file_space,flags);
+ if(opt==FAIL)
+ HRETURN_ERROR(H5E_DATASPACE, H5E_BADRANGE, NULL, "invalid check for contiguous dataspace ");
+
+ /* Check if we can use the optimized "all" I/O routines */
+ if(opt==TRUE) {
path->read = H5S_all_read;
path->write = H5S_all_write;
+ } /* end if */
+ else {
+ path->read = NULL;
+ path->write = NULL;
} /* end else */
-#else /* H5_HAVE_PARALLEL */
- path->read = H5S_all_read;
- path->write = H5S_all_write;
+#ifdef H5_HAVE_PARALLEL
+ } /* end else */
#endif /* H5_HAVE_PARALLEL */
- } /* end if */
/*
* Add the new path to the table.
diff --git a/src/H5Sall.c b/src/H5Sall.c
index 1692ff7..e38607b 100644
--- a/src/H5Sall.c
+++ b/src/H5Sall.c
@@ -368,6 +368,58 @@ H5S_all_mscat (const void *tconv_buf, size_t elmt_size,
/*-------------------------------------------------------------------------
+ * Function: H5S_all_opt_possible
+ *
+ * Purpose: Checks if an direct I/O transfer is possible between memory and
+ * the file.
+ *
+ * Return: Success: Non-negative: TRUE or FALSE
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, April 3, 2002
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5S_all_opt_possible( const H5S_t *mem_space, const H5S_t *file_space, const unsigned UNUSED flags)
+{
+ htri_t c1,c2; /* Flags whether a selection is optimizable */
+ htri_t ret_value=TRUE;
+
+ FUNC_ENTER(H5S_all_opt_possible, FAIL);
+
+ /* Check args */
+ assert(mem_space);
+ assert(file_space);
+
+ /* Check whether these are both simple dataspaces */
+ if (H5S_SIMPLE!=mem_space->extent.type || H5S_SIMPLE!=file_space->extent.type)
+ HGOTO_DONE(FALSE);
+
+ /* Check whether both selections are single blocks */
+ c1=H5S_select_single(file_space);
+ c2=H5S_select_single(mem_space);
+ if(c1==FAIL || c2==FAIL)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "invalid check for single selection blocks");
+ if(c1==FALSE || c2==FALSE)
+ HGOTO_DONE(FALSE);
+
+ /* Check whether the shape of each block is the same */
+ c1=H5S_select_shape_same(mem_space,file_space);
+ if(c1==FAIL)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "invalid check for selection blocks same");
+ if(c1==FALSE)
+ HGOTO_DONE(FALSE);
+
+done:
+ FUNC_LEAVE(ret_value);
+} /* H5S_all_opt_possible() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5S_all_read
*
* Purpose: Reads directly from file into application memory if possible.
@@ -395,12 +447,11 @@ herr_t
H5S_all_read(H5F_t *f, const H5O_layout_t *layout, const H5O_pline_t *pline,
const struct H5O_fill_t *fill,
const H5O_efl_t *efl, size_t elmt_size, const H5S_t *file_space,
- const H5S_t *mem_space, hid_t dxpl_id, void *_buf/*out*/,
- hbool_t *must_convert/*out*/)
+ const H5S_t *mem_space, hid_t dxpl_id, void *_buf/*out*/)
{
H5S_hyper_span_t *file_span=NULL,*mem_span=NULL; /* Hyperslab span node */
char *buf=(char*)_buf; /* Get pointer to buffer */
- hsize_t mem_elmts,file_elmts; /* Number of elements in each dimension of selection */
+ hsize_t file_elmts; /* Number of elements in each dimension of selection */
hssize_t file_off,mem_off; /* Offset (in elements) of selection */
hsize_t mem_size[H5O_LAYOUT_NDIMS]; /* Size of memory buffer */
hsize_t size[H5O_LAYOUT_NDIMS]; /* Size of selection */
@@ -410,30 +461,19 @@ H5S_all_read(H5F_t *f, const H5O_layout_t *layout, const H5O_pline_t *pline,
herr_t ret_value=SUCCEED;
FUNC_ENTER(H5S_all_read, FAIL);
- *must_convert = TRUE;
#ifdef QAK
printf("%s: check 1.0\n",FUNC);
#endif /* QAK */
- /* Check whether we can handle this */
- if (H5S_SIMPLE!=mem_space->extent.type)
- HGOTO_DONE(SUCCEED);
- if (H5S_SIMPLE!=file_space->extent.type)
- HGOTO_DONE(SUCCEED);
- if (mem_space->extent.u.simple.rank!=file_space->extent.u.simple.rank)
- HGOTO_DONE(SUCCEED);
-
/* Get information about memory and file */
for (u=0; u<mem_space->extent.u.simple.rank; u++) {
switch(mem_space->select.type) {
case H5S_SEL_HYPERSLABS:
/* Check for a "regular" hyperslab selection */
if(mem_space->select.sel_info.hslab.diminfo != NULL) {
- mem_elmts=mem_space->select.sel_info.hslab.diminfo[u].block;
mem_off=mem_space->select.sel_info.hslab.diminfo[u].start;
} /* end if */
else {
- mem_elmts=(mem_span->high-mem_span->low)+1;
mem_off=mem_span->low;
mem_span=mem_span->down->head;
} /* end else */
@@ -441,12 +481,10 @@ printf("%s: check 1.0\n",FUNC);
break;
case H5S_SEL_ALL:
- mem_elmts=mem_space->extent.u.simple.size[u];
mem_off=0;
break;
case H5S_SEL_POINTS:
- mem_elmts=1;
mem_off=mem_space->select.sel_info.pnt_lst->head->pnt[u]
+mem_space->select.offset[u];
break;
@@ -485,9 +523,6 @@ printf("%s: check 1.0\n",FUNC);
assert(0 && "Invalid selection type!");
} /* end switch */
- if (mem_elmts!=file_elmts)
- HGOTO_DONE(SUCCEED);
-
mem_size[u]=mem_space->extent.u.simple.size[u];
size[u] = file_elmts;
file_offset[u] = file_off;
@@ -511,11 +546,8 @@ for (u=0; u<=mem_space->extent.u.simple.rank; u++)
#endif /* QAK */
/* Read data from the file */
if (H5F_arr_read(f, dxpl_id, layout, pline, fill, efl, size,
- mem_size, mem_offset, file_offset, buf/*out*/)<0) {
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL,
- "unable to read data from the file");
- }
- *must_convert = FALSE;
+ mem_size, mem_offset, file_offset, buf/*out*/)<0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read data from the file");
done:
FUNC_LEAVE(ret_value);
@@ -552,8 +584,7 @@ H5S_all_write(H5F_t *f, const struct H5O_layout_t *layout,
const struct H5O_fill_t *fill,
const H5O_efl_t *efl,
size_t elmt_size, const H5S_t *file_space,
- const H5S_t *mem_space, hid_t dxpl_id, const void *_buf,
- hbool_t *must_convert/*out*/)
+ const H5S_t *mem_space, hid_t dxpl_id, const void *_buf)
{
H5S_hyper_span_t *file_span=NULL,*mem_span=NULL; /* Hyperslab span node */
const char *buf=(const char*)_buf; /* Get pointer to buffer */
@@ -567,18 +598,10 @@ H5S_all_write(H5F_t *f, const struct H5O_layout_t *layout,
herr_t ret_value=SUCCEED;
FUNC_ENTER(H5S_all_write, FAIL);
- *must_convert = TRUE;
#ifdef QAK
printf("%s: check 1.0\n",FUNC);
#endif /* QAK */
- /* Check whether we can handle this */
- if (H5S_SIMPLE!=mem_space->extent.type)
- HGOTO_DONE(SUCCEED);
- if (H5S_SIMPLE!=file_space->extent.type)
- HGOTO_DONE(SUCCEED);
- if (mem_space->extent.u.simple.rank!=file_space->extent.u.simple.rank)
- HGOTO_DONE(SUCCEED);
/* Get information about memory and file */
for (u=0; u<mem_space->extent.u.simple.rank; u++) {
@@ -642,9 +665,6 @@ printf("%s: check 1.0\n",FUNC);
assert(0 && "Invalid selection type!");
} /* end switch */
- if (mem_elmts!=file_elmts)
- HGOTO_DONE(SUCCEED);
-
mem_size[u]=mem_space->extent.u.simple.size[u];
size[u] = file_elmts;
file_offset[u] = file_off;
@@ -668,11 +688,8 @@ for (u=0; u<=mem_space->extent.u.simple.rank; u++)
#endif /* QAK */
/* Write data to the file */
if (H5F_arr_write(f, dxpl_id, layout, pline, fill, efl, size,
- mem_size, mem_offset, file_offset, buf)<0) {
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL,
- "unable to write data to the file");
- }
- *must_convert = FALSE;
+ mem_size, mem_offset, file_offset, buf)<0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write data to the file");
done:
FUNC_LEAVE(ret_value);
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index 487de1b..4c1f3f5 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -5963,7 +5963,7 @@ H5S_hyper_select_single(const H5S_t *space)
assert(space);
- /* Check for a "regular" hyperslab selection */
+ /* Check for a "single" hyperslab selection */
if(space->select.sel_info.hslab.diminfo != NULL) {
/*
* For a regular hyperslab to be single, it must have only one
@@ -6013,6 +6013,47 @@ H5S_hyper_select_single(const H5S_t *space)
/*--------------------------------------------------------------------------
NAME
+ H5S_hyper_select_regular
+ PURPOSE
+ Check if a hyperslab selection is "regular"
+ USAGE
+ htri_t H5S_hyper_select_regular(space)
+ const H5S_t *space; IN: Dataspace pointer to check
+ RETURNS
+ TRUE/FALSE/FAIL
+ DESCRIPTION
+ Checks to see if the current selection in a dataspace is the a regular
+ pattern.
+ This is primarily used for reading the entire selection in one swoop.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Doesn't check for "regular" hyperslab selections composed of spans
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+htri_t
+H5S_hyper_select_regular(const H5S_t *space)
+{
+ htri_t ret_value=FAIL; /* return value */
+
+ FUNC_ENTER (H5S_hyper_select_regular, FAIL);
+
+ /* Check args */
+ assert(space);
+
+ /* Only simple check for regular hyperslabs for now... */
+ if(space->select.sel_info.hslab.diminfo != NULL)
+ ret_value=TRUE;
+ else
+ ret_value=FALSE;
+
+done:
+ FUNC_LEAVE (ret_value);
+} /* H5S_hyper_select_regular() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_hyper_select_iterate_helper
PURPOSE
Internal routine to iterate over the elements of a span tree hyperslab selection
diff --git a/src/H5Smpio.c b/src/H5Smpio.c
index b5e7028..13293c3 100644
--- a/src/H5Smpio.c
+++ b/src/H5Smpio.c
@@ -63,8 +63,7 @@ H5S_mpio_spaces_xfer(H5F_t *f, const struct H5O_layout_t *layout,
const struct H5O_fill_t UNUSED *fill,
const struct H5O_efl_t UNUSED *efl, size_t elmt_size,
const H5S_t *file_space, const H5S_t *mem_space,
- hid_t dxpl_id, void *buf/*out*/,
- hbool_t *must_convert/*out*/, const hbool_t do_write);
+ hid_t dxpl_id, void *buf/*out*/, const hbool_t do_write);
/*-------------------------------------------------------------------------
* Function: H5S_mpio_all_type
@@ -533,9 +532,6 @@ H5S_mpio_space_type( const H5S_t *space, const size_t elmt_size,
* directly between app buffer and file.
*
* Return: non-negative on success, negative on failure.
- * If MPI-IO is indeed used, must_convert is set to 0;
- * otherwise it is set to 1 with return code succeed (so that the
- * calling routine may try other means.)
*
* Programmer: rky 980813
*
@@ -547,6 +543,10 @@ H5S_mpio_space_type( const H5S_t *space, const size_t elmt_size,
* Albert Cheng, 001123
* Include the MPI_type freeing as part of cleanup code.
*
+ * QAK - 2002/04/02
+ * Removed the must_convert parameter and move preconditions to
+ * H5S_mpio_opt_possible() routine
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -556,7 +556,6 @@ H5S_mpio_spaces_xfer(H5F_t *f, const struct H5O_layout_t *layout,
const struct H5O_efl_t UNUSED *efl, size_t elmt_size,
const H5S_t *file_space, const H5S_t *mem_space,
hid_t dxpl_id, void *buf /*out*/,
- hbool_t *must_convert /*out*/,
const hbool_t do_write )
{
herr_t ret_value = SUCCEED;
@@ -571,8 +570,6 @@ H5S_mpio_spaces_xfer(H5F_t *f, const struct H5O_layout_t *layout,
FUNC_ENTER (H5S_mpio_spaces_xfer, FAIL);
- *must_convert = 0; /* means we at least tried to do optimized xfer */
-
/* Check args */
assert (f);
assert (layout);
@@ -584,18 +581,6 @@ H5S_mpio_spaces_xfer(H5F_t *f, const struct H5O_layout_t *layout,
assert(H5I_GENPROP_LST==H5I_get_type(dxpl_id));
assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER));
- /* INCOMPLETE!!! rky 980816 */
- /* Currently can only handle H5D_CONTIGUOUS layout */
- if (layout->type != H5D_CONTIGUOUS) {
-#ifdef H5S_DEBUG
- if (H5DEBUG(S)) {
- HDfprintf (H5DEBUG(S), "H5S: can only create MPI datatype for hyperslab when layout is contiguous.\n" );
- }
-#endif
- *must_convert = 1; /* can't do optimized xfer; do the old way */
- HGOTO_DONE(SUCCEED);
- }
-
/*
* For collective data transfer only since this would eventually
* call H5FD_mpio_setup to do setup to eveually call MPI_File_set_view
@@ -624,12 +609,6 @@ H5S_mpio_spaces_xfer(H5F_t *f, const struct H5O_layout_t *layout,
/* Get the driver information */
if(H5P_get(plist, H5D_XFER_VFL_INFO_NAME, &dx)<0)
HGOTO_ERROR (H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve VFL driver info");
-
- /* Check if we are using the MPIO driver */
- if(H5FD_MPIO!=driver_id || H5FD_MPIO_COLLECTIVE!=dx->xfer_mode) {
- *must_convert = 1; /* can't do optimized xfer; do the old way */
- HGOTO_DONE(SUCCEED);
- } /* end if */
}
#endif
@@ -717,6 +696,10 @@ done:
* rky 980918
* Added must_convert parameter to let caller know we can't optimize the xfer.
*
+ * QAK - 2002/04/02
+ * Removed the must_convert parameter and move preconditions to
+ * H5S_mpio_opt_possible() routine
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -725,8 +708,7 @@ H5S_mpio_spaces_read(H5F_t *f, const struct H5O_layout_t *layout,
const struct H5O_fill_t *fill,
const struct H5O_efl_t *efl, size_t elmt_size,
const H5S_t *file_space, const H5S_t *mem_space,
- hid_t dxpl_id, void *buf/*out*/,
- hbool_t *must_convert/*out*/)
+ hid_t dxpl_id, void *buf/*out*/)
{
herr_t ret_value = FAIL;
@@ -734,7 +716,7 @@ H5S_mpio_spaces_read(H5F_t *f, const struct H5O_layout_t *layout,
ret_value = H5S_mpio_spaces_xfer(f, layout, pline, fill, efl, elmt_size,
file_space, mem_space, dxpl_id,
- buf, must_convert/*out*/, 0/*read*/);
+ buf, 0/*read*/);
FUNC_LEAVE (ret_value);
}
@@ -754,6 +736,10 @@ H5S_mpio_spaces_read(H5F_t *f, const struct H5O_layout_t *layout,
* rky 980918
* Added must_convert parameter to let caller know we can't optimize the xfer.
*
+ * QAK - 2002/04/02
+ * Removed the must_convert parameter and move preconditions to
+ * H5S_mpio_opt_possible() routine
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -762,8 +748,7 @@ H5S_mpio_spaces_write(H5F_t *f, const struct H5O_layout_t *layout,
const struct H5O_fill_t *fill,
const struct H5O_efl_t *efl, size_t elmt_size,
const H5S_t *file_space, const H5S_t *mem_space,
- hid_t dxpl_id, const void *buf,
- hbool_t *must_convert/*out*/)
+ hid_t dxpl_id, const void *buf)
{
herr_t ret_value = FAIL;
@@ -771,10 +756,66 @@ H5S_mpio_spaces_write(H5F_t *f, const struct H5O_layout_t *layout,
ret_value = H5S_mpio_spaces_xfer(f, layout, pline, fill, efl, elmt_size,
file_space, mem_space, dxpl_id,
- (void*)buf, must_convert/*out*/,
- 1/*write*/);
+ (void*)buf, 1/*write*/);
FUNC_LEAVE (ret_value);
}
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_mpio_opt_possible
+ *
+ * Purpose: Checks if an direct I/O transfer is possible between memory and
+ * the file.
+ *
+ * Return: Success: Non-negative: TRUE or FALSE
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, April 3, 2002
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5S_mpio_opt_possible( const H5S_t *mem_space, const H5S_t *file_space, const unsigned flags)
+{
+ htri_t c1,c2; /* Flags whether a selection is optimizable */
+ htri_t ret_value=TRUE;
+
+ FUNC_ENTER(H5S_all_opt_possible, FAIL);
+
+ /* Check args */
+ assert(mem_space);
+ assert(file_space);
+
+ /* Check whether these are both simple dataspaces */
+ if (H5S_SIMPLE!=mem_space->extent.type || H5S_SIMPLE!=file_space->extent.type)
+ HGOTO_DONE(FALSE);
+
+ /* Check whether both selections are "regular" */
+ c1=H5S_select_regular(file_space);
+ c2=H5S_select_regular(mem_space);
+ if(c1==FAIL || c2==FAIL)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "invalid check for single selection blocks");
+ if(c1==FALSE || c2==FALSE)
+ HGOTO_DONE(FALSE);
+
+ /* Can't currently handle point selections */
+ if (H5S_SEL_POINTS==mem_space->select.type || H5S_SEL_POINTS==file_space->select.type)
+ HGOTO_DONE(FALSE);
+
+ /* Dataset storage must be contiguous currently */
+ if ((sconv_flags&H5S_CONV_STORAGE_MASK)!=H5S_CONV_STORAGE_CONTIGUOUS)
+ HGOTO_DONE(FALSE);
+
+ /* Parallel I/O conversion flag must be set */
+ if(!(flags&H5S_CONV_PAR_IO_POSSIBLE))
+ HGOTO_DONE(FALSE);
+
+done:
+ FUNC_LEAVE(ret_value);
+} /* H5S_mpio_opt_possible() */
+
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5Spkg.h b/src/H5Spkg.h
index 0e6a0c5..0fc4513 100644
--- a/src/H5Spkg.h
+++ b/src/H5Spkg.h
@@ -133,11 +133,11 @@ __DLL__ herr_t H5S_point_select_deserialize(H5S_t *space, const uint8_t *buf);
__DLL__ herr_t H5S_point_bounds(H5S_t *space, hsize_t *start, hsize_t *end);
__DLL__ htri_t H5S_point_select_contiguous(const H5S_t *space);
__DLL__ htri_t H5S_point_select_single(const H5S_t *space);
+__DLL__ htri_t H5S_point_select_regular(const H5S_t *space);
__DLL__ herr_t H5S_select_elements (H5S_t *space, H5S_seloper_t op,
size_t num_elem, const hssize_t **coord);
__DLL__ herr_t H5S_point_select_iterate(void *buf, hid_t type_id, H5S_t *space,
- H5D_operator_t op,
- void *operator_data);
+ H5D_operator_t op, void *operator_data);
/* "All" select functions */
__DLL__ herr_t H5S_all_release(H5S_t *space);
@@ -150,17 +150,17 @@ __DLL__ herr_t H5S_all_read(H5F_t *f, const struct H5O_layout_t *layout,
const struct H5O_fill_t *fill,
const struct H5O_efl_t *efl, size_t elmt_size,
const H5S_t *file_space, const H5S_t *mem_space,
- hid_t dxpl_id, void *buf/*out*/,
- hbool_t *must_convert/*out*/);
+ hid_t dxpl_id, void *buf/*out*/);
__DLL__ herr_t H5S_all_write(H5F_t *f, const struct H5O_layout_t *layout,
const struct H5O_pline_t *pline,
const struct H5O_fill_t *fill,
const struct H5O_efl_t *efl, size_t elmt_size,
const H5S_t *file_space, const H5S_t *mem_space,
- hid_t dxpl_id, const void *buf,
- hbool_t *must_convert/*out*/);
+ hid_t dxpl_id, const void *buf);
__DLL__ herr_t H5S_all_select_iterate(void *buf, hid_t type_id, H5S_t *space,
- H5D_operator_t op, void *operator_data);
+ H5D_operator_t op, void *operator_data);
+__DLL__ htri_t H5S_all_opt_possible(const H5S_t *mem_space,
+ const H5S_t *file_space, const unsigned flags);
/* Hyperslab selection functions */
__DLL__ herr_t H5S_hyper_release(H5S_t *space);
@@ -176,6 +176,7 @@ __DLL__ herr_t H5S_hyper_span_blocklist(H5S_hyper_span_info_t *spans, hssize_t s
__DLL__ herr_t H5S_hyper_bounds(H5S_t *space, hsize_t *start, hsize_t *end);
__DLL__ htri_t H5S_hyper_select_contiguous(const H5S_t *space);
__DLL__ htri_t H5S_hyper_select_single(const H5S_t *space);
+__DLL__ htri_t H5S_hyper_select_regular(const H5S_t *space);
__DLL__ herr_t H5S_hyper_select_iterate(void *buf, hid_t type_id, H5S_t *space,
H5D_operator_t op, void *operator_data);
diff --git a/src/H5Spoint.c b/src/H5Spoint.c
index 5cb9079..7ca1bed 100644
--- a/src/H5Spoint.c
+++ b/src/H5Spoint.c
@@ -1167,6 +1167,48 @@ H5S_point_select_single(const H5S_t *space)
/*--------------------------------------------------------------------------
NAME
+ H5S_point_select_regular
+ PURPOSE
+ Check if a point selection is "regular"
+ USAGE
+ htri_t H5S_point_select_regular(space)
+ const H5S_t *space; IN: Dataspace pointer to check
+ RETURNS
+ TRUE/FALSE/FAIL
+ DESCRIPTION
+ Checks to see if the current selection in a dataspace is the a regular
+ pattern.
+ This is primarily used for reading the entire selection in one swoop.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Doesn't check for points selected to be next to one another in a regular
+ pattern yet.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+htri_t
+H5S_point_select_regular(const H5S_t *space)
+{
+ htri_t ret_value=FAIL; /* return value */
+
+ FUNC_ENTER (H5S_point_select_regular, FAIL);
+
+ /* Check args */
+ assert(space);
+
+ /* Only simple check for regular points for now... */
+ if(space->select.num_elem==1)
+ ret_value=TRUE;
+ else
+ ret_value=FALSE;
+
+done:
+ FUNC_LEAVE (ret_value);
+} /* H5S_point_select_regular() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_select_elements
PURPOSE
Specify a series of elements in the dataspace to select
diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h
index 713d52f..5af635d 100644
--- a/src/H5Sprivate.h
+++ b/src/H5Sprivate.h
@@ -32,6 +32,12 @@
/* Flags for H5S_find */
#define H5S_CONV_PAR_IO_POSSIBLE 0x0001
+/* The storage options are mutually exclusive */
+/* (2-bits reserved for storage type currently) */
+#define H5S_CONV_STORAGE_COMPACT 0x0000 /* i.e. '0' */
+#define H5S_CONV_STORAGE_CONTIGUOUS 0x0002 /* i.e. '1' */
+#define H5S_CONV_STORAGE_CHUNKED 0x0004 /* i.e. '2' */
+#define H5S_CONV_STORAGE_MASK 0x0006
/* Forward references of common typedefs */
typedef struct H5S_t H5S_t;
@@ -129,17 +135,6 @@ typedef struct H5S_conv_t {
* If there is no data type conversion then it might be possible to
* transfer data points between application memory and the file in one
* step without going through the data type conversion buffer.
- *
- * rky 980918
- * If the direct read or write function determines that the transfer
- * must be done indirectly, i.e., through the conversion buffer or
- * (in the case of parallel MPI-IO) in block-by-block transfers
- * then the function returns with the value of must_convert!=0,
- * the function's return value is SUCCEED,
- * and no transfer of data is attempted.
- * Otherwise the direct read or write function returns must_convert 0,
- * with the function's return value being SUCCEED or FAIL
- * depending on whether or not the transfer of data was successful.
*/
/* Read from file to application w/o intermediate scratch buffer */
@@ -148,8 +143,7 @@ typedef struct H5S_conv_t {
const struct H5O_fill_t *fill,
const struct H5O_efl_t *efl, size_t elmt_size,
const H5S_t *file_space, const H5S_t *mem_space,
- hid_t dxpl_id, void *buf/*out*/,
- hbool_t *must_convert/*out*/);
+ hid_t dxpl_id, void *buf/*out*/);
/* Write directly from app buffer to file */
@@ -158,8 +152,7 @@ typedef struct H5S_conv_t {
const struct H5O_fill_t *fill,
const struct H5O_efl_t *efl, size_t elmt_size,
const H5S_t *file_space, const H5S_t *mem_space,
- hid_t dxpl_id, const void *buf,
- hbool_t *must_convert/*out*/);
+ hid_t dxpl_id, const void *buf);
#ifdef H5S_DEBUG
struct {
@@ -224,12 +217,19 @@ __DLL__ herr_t H5S_select_serialize(const H5S_t *space, uint8_t *buf);
__DLL__ herr_t H5S_select_deserialize(H5S_t *space, const uint8_t *buf);
__DLL__ htri_t H5S_select_contiguous(const H5S_t *space);
__DLL__ htri_t H5S_select_single(const H5S_t *space);
+__DLL__ htri_t H5S_select_regular(const H5S_t *space);
+__DLL__ htri_t H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2);
__DLL__ herr_t H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space,
H5D_operator_t op, void *operator_data);
__DLL__ herr_t H5S_sel_iter_release(const H5S_t *space,
H5S_sel_iter_t *sel_iter);
#ifdef H5_HAVE_PARALLEL
+
+/* MPI-IO function to check whether its possible to transfer directly from app buffer to file */
+__DLL__ htri_t H5S_all_opt_possible(const H5S_t *mem_space,
+ const H5S_t *file_space, const unsigned flags);
+
/* MPI-IO function to read directly from app buffer to file rky980813 */
__DLL__ herr_t H5S_mpio_spaces_read(H5F_t *f,
const struct H5O_layout_t *layout,
@@ -238,8 +238,7 @@ __DLL__ herr_t H5S_mpio_spaces_read(H5F_t *f,
const struct H5O_efl_t *efl,
size_t elmt_size, const H5S_t *file_space,
const H5S_t *mem_space, hid_t dxpl_id,
- void *buf/*out*/,
- hbool_t *must_convert /*out*/ );
+ void *buf/*out*/);
/* MPI-IO function to write directly from app buffer to file rky980813 */
__DLL__ herr_t H5S_mpio_spaces_write(H5F_t *f,
@@ -249,8 +248,7 @@ __DLL__ herr_t H5S_mpio_spaces_write(H5F_t *f,
const struct H5O_efl_t *efl,
size_t elmt_size, const H5S_t *file_space,
const H5S_t *mem_space, hid_t dxpl_id,
- const void *buf,
- hbool_t *must_convert /*out*/ );
+ const void *buf);
#ifndef _H5S_IN_H5S_C
/* Global var whose value comes from environment variable */
__DLLVAR__ hbool_t H5_mpi_opt_types_g;
diff --git a/src/H5Sselect.c b/src/H5Sselect.c
index b592e9f..92f9832 100644
--- a/src/H5Sselect.c
+++ b/src/H5Sselect.c
@@ -1342,6 +1342,7 @@ H5S_select_single(const H5S_t *space)
FUNC_ENTER (H5S_select_single, FAIL);
+ /* Check args */
assert(space);
switch(space->select.type) {
@@ -1369,3 +1370,173 @@ H5S_select_single(const H5S_t *space)
FUNC_LEAVE (ret_value);
} /* H5S_select_single() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_select_shape_same
+ PURPOSE
+ Check if two selections are the same shape
+ USAGE
+ htri_t H5S_select_shape_same(space1, space2)
+ const H5S_t *space1; IN: 1st Dataspace pointer to compare
+ const H5S_t *space2; IN: 2nd Dataspace pointer to compare
+ RETURNS
+ TRUE/FALSE/FAIL
+ DESCRIPTION
+ Checks to see if the current selection in the dataspaces are the same
+ dimensionality and shape.
+ This is primarily used for reading the entire selection in one swoop.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Assumes that there is only a single "block" for hyperslab selections.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+htri_t
+H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
+{
+ H5S_hyper_span_t *span1=NULL,*span2=NULL; /* Hyperslab span node */
+ hsize_t elmts1,elmts2; /* Number of elements in each dimension of selection */
+ unsigned u; /* Index variable */
+ htri_t ret_value=TRUE; /* return value */
+
+ FUNC_ENTER (H5S_select_shape_same, FAIL);
+
+ /* Check args */
+ assert(space1);
+ assert(space2);
+
+ if (space1->extent.u.simple.rank!=space2->extent.u.simple.rank)
+ HGOTO_DONE(FALSE);
+
+ /* Get information about memory and file */
+ for (u=0; u<space1->extent.u.simple.rank; u++) {
+ switch(space1->select.type) {
+ case H5S_SEL_HYPERSLABS:
+ /* Check size hyperslab selection in this dimension */
+ if(space1->select.sel_info.hslab.diminfo != NULL) {
+ elmts1=space1->select.sel_info.hslab.diminfo[u].block;
+ } /* end if */
+ else {
+ /* Check for the first dimension */
+ if(span1==NULL)
+ span1=space1->select.sel_info.hslab.span_lst->head;
+
+ /* Get the number of elements in the span */
+ elmts1=(span1->high-span1->low)+1;
+
+ /* Advance to the next dimension */
+ span1=span1->down->head;
+ } /* end else */
+ break;
+
+ case H5S_SEL_ALL:
+ elmts1=space1->extent.u.simple.size[u];
+ break;
+
+ case H5S_SEL_POINTS:
+ elmts1=1;
+ break;
+
+ default:
+ assert(0 && "Invalid selection type!");
+ } /* end switch */
+
+ switch(space2->select.type) {
+ case H5S_SEL_HYPERSLABS:
+ /* Check size hyperslab selection in this dimension */
+ if(space2->select.sel_info.hslab.diminfo != NULL) {
+ elmts2=space2->select.sel_info.hslab.diminfo[u].block;
+ } /* end if */
+ else {
+ /* Check for the first dimension */
+ if(span2==NULL)
+ span2=space2->select.sel_info.hslab.span_lst->head;
+
+ /* Get the number of elements in the span */
+ elmts2=(span2->high-span2->low)+1;
+
+ /* Advance to the next dimension */
+ span2=span2->down->head;
+ } /* end else */
+ break;
+
+ case H5S_SEL_ALL:
+ elmts2=space2->extent.u.simple.size[u];
+ break;
+
+ case H5S_SEL_POINTS:
+ elmts2=1;
+ break;
+
+ default:
+ assert(0 && "Invalid selection type!");
+ } /* end switch */
+
+ /* Make certaint the selections have the same number of elements in this dimension */
+ if (elmts1!=elmts2)
+ HGOTO_DONE(FALSE);
+ } /* end for */
+
+done:
+ FUNC_LEAVE (ret_value);
+} /* H5S_select_shape_same() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_select_regular
+ PURPOSE
+ Check if a selection is "regular"
+ USAGE
+ htri_t H5S_select_regular(space)
+ const H5S_t *space; IN: Dataspace pointer to check
+ RETURNS
+ TRUE/FALSE/FAIL
+ DESCRIPTION
+ Checks to see if the current selection in a dataspace is the a regular
+ pattern.
+ This is primarily used for reading the entire selection in one swoop.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+htri_t
+H5S_select_regular(const H5S_t *space)
+{
+ htri_t ret_value=FAIL; /* return value */
+
+ FUNC_ENTER (H5S_select_regular, FAIL);
+
+ /* Check args */
+ assert(space);
+
+ /* Check for a "regular" selection */
+ /* [Defer (mostly) to the selection routines] */
+ switch(space->select.type) {
+ case H5S_SEL_POINTS: /* Sequence of points selected */
+ ret_value=H5S_point_select_regular(space);
+ break;
+
+ case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */
+ ret_value=H5S_hyper_select_regular(space);
+ break;
+
+ case H5S_SEL_ALL: /* Entire extent selected */
+ ret_value=TRUE;
+ break;
+
+ case H5S_SEL_NONE: /* Nothing selected */
+ ret_value=FALSE;
+ break;
+
+ case H5S_SEL_ERROR:
+ case H5S_SEL_N:
+ break;
+ } /* end switch */
+
+done:
+ FUNC_LEAVE (ret_value);
+} /* H5S_select_regular() */
+