summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2001-10-01 15:42:33 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2001-10-01 15:42:33 (GMT)
commitb8b6227850c7d0205a1bfaa1accaa836743670da (patch)
tree1b7d7b6e89733fc7e197e7cdde1b172475c56488
parent79b4c1677dd673a521e502cbdfdc45496a2292d0 (diff)
downloadhdf5-b8b6227850c7d0205a1bfaa1accaa836743670da.zip
hdf5-b8b6227850c7d0205a1bfaa1accaa836743670da.tar.gz
hdf5-b8b6227850c7d0205a1bfaa1accaa836743670da.tar.bz2
[svn-r4506] Purpose:
Bug fix/optimization. Description: Single, contiguous (in memory) hyperslabs are able to be transferred in one I/O operation, but weren't being detected correctly by the code in H5S_all_read()/H5S_all_write() and were getting routed into slower I/O routines. (Or, possibly failing in some circumstances) Solution: Wrote code to correctly detect single contiguous hyperslabs in memory and adjust arrays and buffer pointers describing the memory information so that the entire hyperslab can be transferred in one operation. Platforms Tested: FreeBSD 4.4 (hawkwind)
-rw-r--r--src/H5Sall.c158
1 files changed, 155 insertions, 3 deletions
diff --git a/src/H5Sall.c b/src/H5Sall.c
index 5d79baf..a676f73 100644
--- a/src/H5Sall.c
+++ b/src/H5Sall.c
@@ -389,9 +389,10 @@ H5S_all_mscat (const void *tconv_buf, size_t elmt_size,
herr_t
H5S_all_read(H5F_t *f, const H5O_layout_t *layout, const H5O_pline_t *pline,
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*/,
+ const H5S_t *mem_space, hid_t dxpl_id, void *_buf/*out*/,
hbool_t *must_convert/*out*/)
{
+ char *buf=(char*)_buf; /* Get pointer to buffer */
H5S_hyper_node_t *file_node=NULL,*mem_node=NULL; /* Hyperslab node */
hsize_t mem_size,file_size;
hssize_t file_off,mem_off;
@@ -400,6 +401,11 @@ H5S_all_read(H5F_t *f, const H5O_layout_t *layout, const H5O_pline_t *pline,
hssize_t file_offset[H5O_LAYOUT_NDIMS];
hssize_t mem_offset[H5O_LAYOUT_NDIMS];
unsigned u;
+ unsigned small_contiguous=0, /* Flags for indicating contiguous hyperslabs */
+ large_contiguous=0;
+ int i;
+ size_t down_size[H5O_LAYOUT_NDIMS];
+ size_t acc;
FUNC_ENTER(H5S_all_read, FAIL);
*must_convert = TRUE;
@@ -502,8 +508,81 @@ printf("%s: check 1.0\n",FUNC);
file_offset[u] = 0;
mem_offset[u] = 0;
+ /* Disallow reading a memory hyperslab in the "middle" of a dataset which */
+ /* spans multiple rows in "interior" dimensions, but allow reading a */
+ /* hyperslab which is in the "middle" of the fastest or slowest changing */
+ /* dimension because a hyperslab which "fills" the interior dimensions is */
+ /* contiguous in memory. i.e. these are allowed: */
+ /* --------------------- --------------------- */
+ /* | | | | */
+ /* |*******************| | ********* | */
+ /* |*******************| | | */
+ /* | | | | */
+ /* | | | | */
+ /* --------------------- --------------------- */
+ /* ("large" contiguous block) ("small" contiguous block) */
+ /* But this is not: */
+ /* --------------------- */
+ /* | | */
+ /* | ********* | */
+ /* | ********* | */
+ /* | | */
+ /* | | */
+ /* --------------------- */
+ /* (not contiguous in memory) */
+ if(mem_space->select.type==H5S_SEL_HYPERSLABS) {
+ /* Check for a "small" contiguous block */
+ if(size[0]==1) {
+ small_contiguous=1;
+ /* size of block in all dimensions except the fastest must be '1' */
+ for (u=0; u<(mem_space->extent.u.simple.rank-1); u++) {
+ if(size[u]>1) {
+ small_contiguous=0;
+ break;
+ } /* end if */
+ } /* end for */
+ } /* end if */
+ /* Check for a "large" contiguous block */
+ else {
+ large_contiguous=1;
+ /* size of block in all dimensions except the slowest must be the */
+ /* full size of the dimension */
+ for (u=1; u<mem_space->extent.u.simple.rank; u++) {
+ if(size[u]!=mem_space->extent.u.simple.size[u]) {
+ large_contiguous=0;
+ break;
+ } /* end if */
+ } /* end for */
+ } /* end else */
+
+ /* Check for contiguous block */
+ if(small_contiguous || large_contiguous) {
+ /* Compute the "down sizes" for each dimension */
+ for (acc=elmt_size, i=(mem_space->extent.u.simple.rank-1); i>=0; i--) {
+ down_size[i]=acc;
+ acc*=mem_space->extent.u.simple.size[i];
+ } /* end for */
+
+ /* Adjust the buffer offset and memory offsets by the proper amount */
+ for (u=0; u<mem_space->extent.u.simple.rank; u++) {
+ buf+=mem_offset[u]*down_size[u];
+ mem_offset[u]=0;
+ } /* end for */
+ } /* end if */
+ else {
+ /* Non-contiguous hyperslab block */
+ goto fall_through;
+ } /* end else */
+ } /* end if */
+
#ifdef QAK
printf("%s: check 2.0\n",FUNC);
+for (u=0; u<mem_space->extent.u.simple.rank; u++)
+ printf("size[%u]=%lu\n",u,(unsigned long)size[u]);
+for (u=0; u<=mem_space->extent.u.simple.rank; u++)
+ printf("mem_offset[%u]=%lu\n",u,(unsigned long)mem_offset[u]);
+for (u=0; u<=mem_space->extent.u.simple.rank; u++)
+ printf("file_offset[%u]=%lu\n",u,(unsigned long)file_offset[u]);
#endif /* QAK */
/* Read data from the file */
if (H5F_arr_read(f, dxpl_id, layout, pline, NULL, efl, size,
@@ -546,9 +625,10 @@ herr_t
H5S_all_write(H5F_t *f, const struct H5O_layout_t *layout,
const H5O_pline_t *pline, 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,
+ const H5S_t *mem_space, hid_t dxpl_id, const void *_buf,
hbool_t *must_convert/*out*/)
{
+ const char *buf=(const char*)_buf; /* Get pointer to buffer */
H5S_hyper_node_t *file_node=NULL,*mem_node=NULL; /* Hyperslab node */
hsize_t mem_size,file_size;
hssize_t file_off,mem_off;
@@ -556,7 +636,12 @@ H5S_all_write(H5F_t *f, const struct H5O_layout_t *layout,
hsize_t size[H5O_LAYOUT_NDIMS];
hssize_t file_offset[H5O_LAYOUT_NDIMS];
hssize_t mem_offset[H5O_LAYOUT_NDIMS];
- unsigned u;
+ unsigned u;
+ unsigned small_contiguous=0, /* Flags for indicating contiguous hyperslabs */
+ large_contiguous=0;
+ int i;
+ size_t down_size[H5O_LAYOUT_NDIMS];
+ size_t acc;
FUNC_ENTER(H5S_all_write, FAIL);
*must_convert = TRUE;
@@ -656,6 +741,73 @@ H5S_all_write(H5F_t *f, const struct H5O_layout_t *layout,
file_offset[u] = 0;
mem_offset[u] = 0;
+ /* Disallow reading a memory hyperslab in the "middle" of a dataset which */
+ /* spans multiple rows in "interior" dimensions, but allow reading a */
+ /* hyperslab which is in the "middle" of the fastest or slowest changing */
+ /* dimension because a hyperslab which "fills" the interior dimensions is */
+ /* contiguous in memory. i.e. these are allowed: */
+ /* --------------------- --------------------- */
+ /* | | | | */
+ /* |*******************| | ********* | */
+ /* |*******************| | | */
+ /* | | | | */
+ /* | | | | */
+ /* --------------------- --------------------- */
+ /* ("large" contiguous block) ("small" contiguous block) */
+ /* But this is not: */
+ /* --------------------- */
+ /* | | */
+ /* | ********* | */
+ /* | ********* | */
+ /* | | */
+ /* | | */
+ /* --------------------- */
+ /* (not contiguous in memory) */
+ if(mem_space->select.type==H5S_SEL_HYPERSLABS) {
+ /* Check for a "small" contiguous block */
+ if(size[0]==1) {
+ small_contiguous=1;
+ /* size of block in all dimensions except the fastest must be '1' */
+ for (u=0; u<(mem_space->extent.u.simple.rank-1); u++) {
+ if(size[u]>1) {
+ small_contiguous=0;
+ break;
+ } /* end if */
+ } /* end for */
+ } /* end if */
+ /* Check for a "large" contiguous block */
+ else {
+ large_contiguous=1;
+ /* size of block in all dimensions except the slowest must be the */
+ /* full size of the dimension */
+ for (u=1; u<mem_space->extent.u.simple.rank; u++) {
+ if(size[u]!=mem_space->extent.u.simple.size[u]) {
+ large_contiguous=0;
+ break;
+ } /* end if */
+ } /* end for */
+ } /* end else */
+
+ /* Check for contiguous block */
+ if(small_contiguous || large_contiguous) {
+ /* Compute the "down sizes" for each dimension */
+ for (acc=elmt_size, i=(mem_space->extent.u.simple.rank-1); i>=0; i--) {
+ down_size[i]=acc;
+ acc*=mem_space->extent.u.simple.size[i];
+ } /* end for */
+
+ /* Adjust the buffer offset and memory offsets by the proper amount */
+ for (u=0; u<mem_space->extent.u.simple.rank; u++) {
+ buf+=mem_offset[u]*down_size[u];
+ mem_offset[u]=0;
+ } /* end for */
+ } /* end if */
+ else {
+ /* Non-contiguous hyperslab block */
+ goto fall_through;
+ } /* end else */
+ } /* end if */
+
/* Write data to the file */
if (H5F_arr_write(f, dxpl_id, layout, pline, NULL, efl, size,
size, mem_offset, file_offset, buf)<0) {