From 7bd50661fe8096cafb488fc19b9f87fffd69a325 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Fri, 22 Sep 2000 14:28:05 -0500 Subject: [svn-r2587] Purpose: Bug fix (sorta) Description: When the stride and block size of a hyperslab selection are equal, the blocks that are selected are contiguous in the dataset. Prior to my hyperslab optimizations, this situation used to be detected and somewhat optimized to improve performance. I've added more code to optimize for this situation and integrated it with the new hyperslab optimization that weren't very efficient for that case as they should have been. Solution: Detect contiguous hyperslab selections (i.e. block size in a dimension is the same as the stride in that dimension) and store the optimized, contiguous version of that hyperslab. We also store the original, un- optimized version of the hyperslab to give back to the user if they query the hyperslab selection they just made. Platforms tested: FreeBSD 4.1 --- src/H5Shyper.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/H5Sprivate.h | 7 +++++++ src/H5Sselect.c | 8 ++++++-- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/H5Shyper.c b/src/H5Shyper.c index dbc61c9..90bc320 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -3512,6 +3512,8 @@ H5S_hyper_release (H5S_t *space) if(space->select.sel_info.hslab.diminfo!=NULL) { H5FL_ARR_FREE(H5S_hyper_dim_t,space->select.sel_info.hslab.diminfo); space->select.sel_info.hslab.diminfo = NULL; + H5FL_ARR_FREE(H5S_hyper_dim_t,space->select.sel_info.hslab.app_diminfo); + space->select.sel_info.hslab.app_diminfo = NULL; } /* end if */ /* Release irregular hyperslab information */ @@ -3684,8 +3686,25 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src) new_diminfo[i].count = src->select.sel_info.hslab.diminfo[i].count; new_diminfo[i].block = src->select.sel_info.hslab.diminfo[i].block; } /* end for */ + dst->select.sel_info.hslab.diminfo = new_diminfo; + + /* Create the per-dimension selection info */ + if((new_diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,src->extent.u.simple.rank,0))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate per-dimension array"); + + /* Copy the per-dimension selection info */ + for(i=0; iextent.u.simple.rank; i++) { + new_diminfo[i].start = src->select.sel_info.hslab.app_diminfo[i].start; + new_diminfo[i].stride = src->select.sel_info.hslab.app_diminfo[i].stride; + new_diminfo[i].count = src->select.sel_info.hslab.app_diminfo[i].count; + new_diminfo[i].block = src->select.sel_info.hslab.app_diminfo[i].block; + } /* end for */ + dst->select.sel_info.hslab.app_diminfo = new_diminfo; } /* end if */ - dst->select.sel_info.hslab.diminfo = new_diminfo; + else { + dst->select.sel_info.hslab.diminfo = new_diminfo; + dst->select.sel_info.hslab.app_diminfo = new_diminfo; + } /* end else */ /* Check if there is irregular hyperslab information to copy */ if(src->select.sel_info.hslab.hyper_lst!=NULL) { @@ -4515,6 +4534,9 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, const hsize_t count[/*space_id*/], const hsize_t block[/*space_id*/]) { + hssize_t real_stride[H5O_LAYOUT_NDIMS]; /* Location of the block to add for strided selections */ + hssize_t real_count[H5O_LAYOUT_NDIMS]; /* Location of the block to add for strided selections */ + hssize_t real_block[H5O_LAYOUT_NDIMS]; /* Location of the block to add for strided selections */ hsize_t *_stride=NULL; /* Stride array */ hsize_t *_block=NULL; /* Block size array */ int i; /* Counters */ @@ -4578,7 +4600,7 @@ for(i=0; iextent.u.simple.rank; i++) "can't release hyperslab"); } /* end if */ - /* Copy all the per-dimension selection info into the space descriptor */ + /* Copy all the application per-dimension selection info into the space descriptor */ if((diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank,0))==NULL) { HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate per-dimension vector"); } /* end if */ @@ -4588,6 +4610,34 @@ for(i=0; iextent.u.simple.rank; i++) diminfo[i].count = count[i]; diminfo[i].block = block[i]; } /* end for */ + space->select.sel_info.hslab.app_diminfo = diminfo; + + /* Optimize the hyperslab selection to detect contiguously selected block/stride information */ + /* Modify the stride, block & count for contiguous hyperslab selections */ + for(i=0; iextent.u.simple.rank; i++) { + /* contiguous hyperslabs have the block size equal to the stride */ + if(stride[i]==block[i]) { + real_count[i]=1; + real_stride[i]=1; + real_block[i]=count[i]*block[i]; + } /* end if */ + else { + real_stride[i]=stride[i]; + real_count[i]=count[i]; + real_block[i]=block[i]; + } /* end else */ + } /* end for */ + + /* Copy all the per-dimension selection info into the space descriptor */ + if((diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank,0))==NULL) { + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate per-dimension vector"); + } /* end if */ + for(i=0; iextent.u.simple.rank; i++) { + diminfo[i].start = start[i]; + diminfo[i].stride = real_stride[i]; + diminfo[i].count = real_count[i]; + diminfo[i].block = real_block[i]; + } /* end for */ space->select.sel_info.hslab.diminfo = diminfo; /* Set the number of elements in the hyperslab selection */ @@ -4631,6 +4681,10 @@ for(i=0; iextent.u.simple.rank; i++) H5FL_ARR_FREE(H5S_hyper_dim_t,space->select.sel_info.hslab.diminfo); space->select.sel_info.hslab.diminfo = NULL; + /* Remove the 'app_diminfo' information also, since we're adding to it */ + H5FL_ARR_FREE(H5S_hyper_dim_t,space->select.sel_info.hslab.app_diminfo); + space->select.sel_info.hslab.app_diminfo = NULL; + /* Add in the new hyperslab information */ H5S_generate_hyperslab (space, op, start, stride, count, block); } /* end if */ diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 4de6e34..2824af0 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -127,6 +127,13 @@ typedef struct { * for one hyperslab selection. Perhaps this might need to be * expanded into a list of arrays when the H5Sselect_hyperslab's * restriction to H5S_SELECT_SET is removed. */ + H5S_hyper_dim_t *app_diminfo;/* ->[rank] of per-dim selection info */ + /* 'diminfo' points to a [potentially] optimized version of the user's + * hyperslab information. 'app_diminfo' points to the actual parameters + * that the application used for setting the hyperslab selection. These + * are only used for re-gurgitating the original values used to set the + * hyperslab to the application when it queries the hyperslab selection + * information. */ H5S_hyper_list_t *hyper_lst; /* List of selected hyperslabs (order is not important) */ } H5S_hyper_sel_t; diff --git a/src/H5Sselect.c b/src/H5Sselect.c index fc931e1..f31bba4 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -608,7 +608,7 @@ for(i=0; iextent.u.simple.rank; i++) #endif /*QAK */ /* Check each dimension */ for(ret_value=1,i=0; iextent.u.simple.rank; i++) - ret_value*=space->select.sel_info.hslab.diminfo[i].count; + ret_value*=space->select.sel_info.hslab.app_diminfo[i].count; } /* end if */ else ret_value = (hssize_t)space->select.sel_info.hslab.hyper_lst->count; @@ -784,7 +784,11 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hsize_t startblock, hsize_t numbloc /* Set some convienence values */ ndims=space->extent.u.simple.rank; fast_dim=ndims-1; - diminfo=space->select.sel_info.hslab.diminfo; + /* + * Use the "application dimension information" to pass back to the user + * the blocks they set, not the optimized, internal information. + */ + diminfo=space->select.sel_info.hslab.app_diminfo; /* Build the tables of count sizes as well as the initial offset */ for(i=0; i