diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2003-05-31 16:26:19 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2003-05-31 16:26:19 (GMT) |
commit | f04d4aea61c6becc0f0299cc98b4e5b120ce20ab (patch) | |
tree | d0f5a2b7db8f4a2c0cac30e4bf5e41fd68ef5a6c /src | |
parent | 862520b80e8e1b29f5b5a719b40506e348c2ee47 (diff) | |
download | hdf5-f04d4aea61c6becc0f0299cc98b4e5b120ce20ab.zip hdf5-f04d4aea61c6becc0f0299cc98b4e5b120ce20ab.tar.gz hdf5-f04d4aea61c6becc0f0299cc98b4e5b120ce20ab.tar.bz2 |
[svn-r6942] Purpose:
Performance improment
Description:
Speed up chunked dataset I/O. This breaks down into several areas:
- Compute chunk selections in the file by using hyperslab operations
instead of iterating over each element in the selection.
- If the file and memory selections are the same shape, use the file
chunk selections to compute the memory chunk selections.
This required several additional dataspace, dataspace selection and
hyperslab routines.
Platforms tested:
h5committestted (although Fortran tests failed for some reason)
Diffstat (limited to 'src')
-rw-r--r-- | src/H5Dio.c | 650 | ||||
-rw-r--r-- | src/H5Distore.c | 24 | ||||
-rw-r--r-- | src/H5Fistore.c | 24 | ||||
-rw-r--r-- | src/H5S.c | 69 | ||||
-rw-r--r-- | src/H5Shyper.c | 452 | ||||
-rw-r--r-- | src/H5Sprivate.h | 13 | ||||
-rw-r--r-- | src/H5Sselect.c | 176 |
7 files changed, 1234 insertions, 174 deletions
diff --git a/src/H5Dio.c b/src/H5Dio.c index c1f6d4b..731b4c7 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -65,9 +65,10 @@ typedef struct fm_map { H5TB_TREE *fsel; /* TBBT containing file dataspaces for all chunks */ H5TB_TREE *msel; /* TBBT containing memory dataspaces for all chunks */ hsize_t last_index; /* Index of last chunk operated on */ - H5S_t *last_fchunk; /* Pointer to last file chunk's dataspace */ + H5S_t *file_space; /* Pointer to the file dataspace */ + H5S_t *mem_space; /* Pointer to the memory dataspace */ + hsize_t f_dims[H5O_LAYOUT_NDIMS]; /* File dataspace dimensions */ H5S_t *last_mchunk; /* Pointer to last memory chunk's dataspace */ - H5S_t *fchunk_tmpl; /* Dataspace template for new file chunks */ H5S_t *mchunk_tmpl; /* Dataspace template for new memory chunks */ unsigned f_ndims; /* Number of dimensions for file dataspace */ H5S_sel_iter_t mem_iter; /* Iterator for elements in memory selection */ @@ -120,7 +121,9 @@ static void H5D_free_fchunk_info(void *fchunk_info); static void H5D_free_mchunk_info(void *mchunk_info); static herr_t H5D_chunk_coords_assist(hssize_t *coords, size_t ndims, hsize_t chunks[], hsize_t chunk_idx); -static herr_t H5D_chunk_cb(void *elem, hid_t type_id, hsize_t ndims, +static herr_t H5D_create_chunk_file_map(fm_map *fm); +static herr_t H5D_create_chunk_mem_map(fm_map *fm); +static herr_t H5D_chunk_mem_cb(void *elem, hid_t type_id, hsize_t ndims, hssize_t *coords, void *fm); static herr_t H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_type, const H5S_t *space, hid_t dxpl_id); @@ -1837,9 +1840,27 @@ nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, FUNC_ENTER_NOINIT(H5D_chunk_write); +#ifdef QAK +{ + int mpi_rank; + double time; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + time = MPI_Wtime(); + HDfprintf(stderr,"%s: rank=%d - Entering, time=%f\n",FUNC,mpi_rank,time); +} +#endif /* QAK */ /* Map elements between file and memory for each chunk*/ if(H5D_create_chunk_map(dataset, mem_type, file_space, mem_space, &fm)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't build chunk mapping"); +#ifdef QAK +{ + int mpi_rank; + double time; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + time = MPI_Wtime(); + HDfprintf(stderr,"%s: rank=%d - After creating chunk map, time=%f\n",FUNC,mpi_rank,time); +} +#endif /* QAK */ /* * If there is no type conversion then write directly from the @@ -1849,6 +1870,15 @@ nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, #ifdef H5S_DEBUG H5_timer_begin(&timer); #endif +#ifdef QAK +{ + int mpi_rank; + double time; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + time = MPI_Wtime(); + HDfprintf(stderr,"%s: rank=%d - Performing optimized I/O, time=%f\n",FUNC,mpi_rank,time); +} +#endif /* QAK */ /* Get first node in chunk trees */ fchunk_node=H5TB_first(fm.fsel->root); mchunk_node=H5TB_first(fm.msel->root); @@ -1896,6 +1926,15 @@ nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, */ assert((fchunk_node && mchunk_node) || (!fchunk_node && !mchunk_node)); } /* end while */ +#ifdef QAK +{ + int mpi_rank; + double time; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + time = MPI_Wtime(); + HDfprintf(stderr,"%s: rank=%d - Done performing optimized I/O, time=%f\n",FUNC,mpi_rank,time); +} +#endif /* QAK */ #ifdef H5S_DEBUG H5_timer_end(&(sconv->stats[0].write_timer), &timer); @@ -1906,6 +1945,13 @@ nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, /* direct xfer accomplished successfully */ HGOTO_DONE(SUCCEED); } /* end if */ +#ifdef QAK +{ + int mpi_rank; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + HDfprintf(stderr,"%s: rank=%d - Performing NON-optimized I/O\n",FUNC,mpi_rank); +} +#endif /* QAK */ /* * This is the general case(type conversion). @@ -2242,14 +2288,13 @@ static herr_t H5D_create_chunk_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_space, const H5S_t *mem_space, fm_map *fm) { - H5S_t *tmp_fspace=NULL, /* Temporary file dataspace */ - *tmp_mspace=NULL; /* Temporary memory dataspace */ + H5S_t *tmp_mspace=NULL; /* Temporary memory dataspace */ hid_t f_tid=(-1); /* Temporary copy of file datatype for iteration */ size_t elmt_size; /* Memory datatype size */ hbool_t iter_init=0; /* Selection iteration info has been initialized */ unsigned f_ndims; /* The number of dimensions of the file's dataspace */ int sm_ndims; /* The number of dimensions of the memory buffer's dataspace (signed) */ - hsize_t f_dims[H5O_LAYOUT_NDIMS]; /* Dimensionality of file dataspace */ + hsize_t offset[H5O_LAYOUT_NDIMS]; /* Offset of selection for chunk */ hsize_t nchunks, last_nchunks; /* Number of chunks in dataset */ H5TB_NODE *curr_node; /* Current node in TBBT */ char bogus; /* "bogus" buffer to pass to selection iterator */ @@ -2257,6 +2302,15 @@ H5D_create_chunk_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_sp herr_t ret_value = SUCCEED; /*return value */ FUNC_ENTER_NOINIT(H5D_create_chunk_map); +#ifdef QAK +{ + int mpi_rank; + double time; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + time = MPI_Wtime(); + HDfprintf(stderr,"%s: rank=%d - Entering, time=%f\n",FUNC,mpi_rank,time); +} +#endif /* QAK */ /* Initialize fm_map structure */ HDmemset(fm, 0, sizeof(fm_map)); @@ -2264,34 +2318,29 @@ H5D_create_chunk_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_sp /* Get layout for dataset */ fm->layout = &(dataset->layout); - /* Create a file space of a chunk's size, instead of whole file space*/ - if(NULL==(tmp_fspace=H5S_create_simple((dataset->layout.ndims-1),dataset->layout.dim,NULL))) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace"); - /*make a copy of mem_space*/ if((tmp_mspace = H5S_copy(mem_space))==NULL) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space"); - /*de-select the file space and mem space copies*/ - if(H5S_select_none(tmp_fspace)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select file space"); - if(H5S_select_none(tmp_mspace)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select memory space"); - /* Get dim number and dimensionality for each dataspace */ fm->f_ndims=f_ndims=dataset->layout.ndims-1; if((sm_ndims = H5S_get_simple_extent_ndims(tmp_mspace))<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimension number"); fm->m_ndims=sm_ndims; - if(H5S_get_simple_extent_dims(file_space, f_dims, NULL)<0) + /* De-select the mem space copy */ + if(H5S_select_none(tmp_mspace)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select memory space"); + + if(H5S_get_simple_extent_dims(file_space, fm->f_dims, NULL)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality"); /* Decide the number of chunks in each dimension*/ last_nchunks=0; nchunks=1; for(u=0; u<f_ndims; u++) { - fm->chunks[u] = ((f_dims[u]+dataset->layout.dim[u])-1) / dataset->layout.dim[u]; + /* Round up to the next integer # of chunks, to accomodate partial chunks */ + fm->chunks[u] = ((fm->f_dims[u]+dataset->layout.dim[u])-1) / dataset->layout.dim[u]; /* Track total number of chunks in dataset */ nchunks *= fm->chunks[u]; @@ -2312,28 +2361,47 @@ H5D_create_chunk_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_sp if((fm->msel=H5TB_fast_dmake(H5TB_FAST_HSIZE_COMPARE))==NULL) HGOTO_ERROR(H5E_DATASET,H5E_CANTMAKETREE,FAIL,"can't create TBBT for memory chunk selections"); - /* Save chunk template information */ - fm->fchunk_tmpl=tmp_fspace; - fm->mchunk_tmpl=tmp_mspace; + /* Save chunk template information */ + fm->mchunk_tmpl=tmp_mspace; - /* Initialize "last chunk" information */ - fm->last_index=(hsize_t)-1; - fm->last_fchunk=fm->last_mchunk=NULL; - - /* Create temporary datatypes for selection iteration */ - if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->type, H5T_COPY_ALL)))<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register file datatype"); - - /* Create selection iterator for memory selection */ - if((elmt_size=H5T_get_size(mem_type))==0) - HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid"); - if (H5S_select_iter_init(&(fm->mem_iter), mem_space, elmt_size)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); - iter_init=1; /* Selection iteration info has been initialized */ + /* Initialize "last chunk" information */ + fm->last_index=(hsize_t)-1; + fm->last_mchunk=NULL; + + /* Copy the file dataspace */ + if((fm->file_space = H5S_copy(file_space))==NULL) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file dataspace"); + if(H5S_hyper_convert(fm->file_space)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to convert selection to span trees"); - /* Build the file & memory selection for each chunk */ - if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_cb, fm)<0) - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to iterate file space"); + /* Copy the memory dataspace */ + if((fm->mem_space = H5S_copy(mem_space))==NULL) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory dataspace"); + if(H5S_hyper_convert(fm->mem_space)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to convert selection to span trees"); + +#ifdef QAK +{ + int mpi_rank; + double time; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + time = MPI_Wtime(); + HDfprintf(stderr,"%s: rank=%d - Before creating chunk selections, time=%f\n",FUNC,mpi_rank,time); +} +#endif /* QAK */ + /* Build the file selection for each chunk */ + if(H5D_create_chunk_file_map(fm)<0) + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections"); +#ifdef QAK +{ + int mpi_rank; + double time; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + time = MPI_Wtime(); + HDfprintf(stderr,"%s: rank=%d - After creating file chunk selections, time=%f\n",FUNC,mpi_rank,time); + HDfprintf(stderr,"%s: rank=%d - H5S_select_shape_same=%d\n",FUNC,mpi_rank,H5S_select_shape_same(file_space,mem_space)); +} +#endif /* QAK */ /* Clean file chunks' hyperslab span "scratch" information */ curr_node=H5TB_first(fm->fsel->root); @@ -2352,34 +2420,64 @@ H5D_create_chunk_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_sp curr_node=H5TB_next(curr_node); } /* end while */ - /* Clean memory chunks' hyperslab span "scratch" information */ - curr_node=H5TB_first(fm->msel->root); - while(curr_node) { - H5D_mchunk_info_t *chunk_info; /* Pointer chunk information */ - - /* Get pointer to chunk's information */ - chunk_info=curr_node->data; - assert(chunk_info); - - /* Clean hyperslab span's "scratch" information */ - if(H5S_hyper_reset_scratch(chunk_info->space)<0) - HGOTO_ERROR (H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info"); + /* Build the memory selection for each chunk */ + if(H5S_select_shape_same(file_space,mem_space)==TRUE) { + /* If the selections are the same shape, use the file chunk information + * to generate the memory chunk information quickly. + */ + if(H5D_create_chunk_mem_map(fm)<0) + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections"); + } /* end if */ + else { + /* Create temporary datatypes for selection iteration */ + if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->type, H5T_COPY_ALL)))<0) + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register file datatype"); + + /* Create selection iterator for memory selection */ + if((elmt_size=H5T_get_size(mem_type))==0) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid"); + if (H5S_select_iter_init(&(fm->mem_iter), mem_space, elmt_size)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); + iter_init=1; /* Selection iteration info has been initialized */ + + /* Spaces aren't the same shape, iterate over the memory selection directly */ + if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_mem_cb, fm)<0) + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections"); + + /* Clean memory chunks' hyperslab span "scratch" information */ + curr_node=H5TB_first(fm->msel->root); + while(curr_node) { + H5D_mchunk_info_t *chunk_info; /* Pointer chunk information */ + + /* Get pointer to chunk's information */ + chunk_info=curr_node->data; + assert(chunk_info); + + /* Clean hyperslab span's "scratch" information */ + if(H5S_hyper_reset_scratch(chunk_info->space)<0) + HGOTO_ERROR (H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info"); + + /* Get the next chunk node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ + } /* end else */ - /* Get the next chunk node in the TBBT */ - curr_node=H5TB_next(curr_node); - } /* end while */ +#ifdef QAK +{ + int mpi_rank; + double time; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + time = MPI_Wtime(); + HDfprintf(stderr,"%s: rank=%d - After creating chunk selections, time=%f\n",FUNC,mpi_rank,time); +} +#endif /* QAK */ done: /* Release the [potentially partially built] chunk mapping information if an error occurs */ if(ret_value<0) { - if(tmp_fspace && !fm->fchunk_tmpl) { - if(H5S_close(tmp_fspace)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release file chunk dataspace template"); - } /* end if */ - if(tmp_mspace && !fm->mchunk_tmpl) { if(H5S_close(tmp_mspace)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template"); + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template"); } /* end if */ if (H5D_destroy_chunk_map(fm)<0) @@ -2393,6 +2491,15 @@ done: if(f_tid!=(-1)) H5Tclose(f_tid); +#ifdef QAK +{ + int mpi_rank; + double time; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + time = MPI_Wtime(); + HDfprintf(stderr,"%s: rank=%d - Leaving, time=%f\n",FUNC,mpi_rank,time); +} +#endif /* QAK */ FUNC_LEAVE_NOAPI(ret_value); } /* end H5D_create_chunk_map() */ @@ -2500,10 +2607,15 @@ H5D_destroy_chunk_map(fm_map *fm) if(fm->msel) H5TB_dfree(fm->msel,H5D_free_mchunk_info,NULL); - /* Free the file chunk dataspace template */ - if(fm->fchunk_tmpl) - if(H5S_close(fm->fchunk_tmpl)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release file chunk dataspace template"); + /* Free the file dataspace */ + if(fm->file_space) + if(H5S_close(fm->file_space)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release file dataspace"); + + /* Free the memory dataspace */ + if(fm->mem_space) + if(H5S_close(fm->mem_space)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory dataspace"); /* Free the memory chunk dataspace template */ if(fm->mchunk_tmpl) @@ -2516,10 +2628,338 @@ done: /*------------------------------------------------------------------------- - * Function: H5D_chunk_cb + * Function: H5D_create_chunk_file_map + * + * Purpose: Create all chunk selections in file. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Thursday, May 29, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_create_chunk_file_map(fm_map *fm) +{ + H5S_t *tmp_fspace=NULL; /* Temporary file dataspace */ + hssize_t sel_points; /* Number of elements in file selection */ + hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */ + hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */ + hssize_t start_coords[H5O_LAYOUT_NDIMS]; /* Starting coordinates of selection */ + hssize_t coords[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */ + hsize_t count[H5O_LAYOUT_NDIMS]; /* Hyperslab count information */ + hsize_t chunk_index; /* Index of chunk */ + int curr_dim; /* Current dimension to increment */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5D_create_chunk_file_map); + + /* Make a copy of file dataspace */ + if((tmp_fspace = H5S_copy(fm->file_space))==NULL) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space"); + + /* Get number of elements selected in file */ + if((sel_points=H5S_get_select_npoints(tmp_fspace))<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection # of elements"); + + /* Get offset of first block in file selection */ + if(H5S_get_select_bounds(tmp_fspace, sel_start, sel_end)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info"); + + /* Set initial chunk location & hyperslab size */ + for(u=0; u<fm->f_ndims; u++) { + start_coords[u]=(sel_start[u]/fm->layout->dim[u])*fm->layout->dim[u]; + coords[u]=start_coords[u]; + count[u]=fm->layout->dim[u]; + } /* end for */ + + /* Select initial chunk as hyperslab */ + if(H5S_select_hyperslab(tmp_fspace,H5S_SELECT_SET,coords,NULL,count,NULL)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't create hyperslab selection"); + + /* Calculate the index of this chunk */ + if(H5V_chunk_index(fm->f_ndims,coords,fm->layout->dim,fm->chunks,fm->down_chunks,&chunk_index)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index"); + + /* Iterate through each chunk in the dataset */ + while(1) { + /* Check for intersection of temporary chunk and file selection */ + if(H5S_hyper_intersect(tmp_fspace,fm->file_space)==TRUE) { + H5S_t *tmp_fchunk; /* Temporary file dataspace */ + H5D_fchunk_info_t *new_fchunk_info; /* File chunk information to insert into tree */ + hssize_t chunk_points; /* Number of elements in chunk selection */ + + /* Create "temporary" chunk for selection operations (copy file space) */ + if((tmp_fchunk = H5S_copy(fm->file_space))==NULL) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space"); + + /* "AND" temporary chunk and current chunk */ + if(H5S_select_hyperslab(tmp_fchunk,H5S_SELECT_AND,coords,NULL,count,NULL)<0) { + H5S_close(tmp_fchunk); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't create chunk selection"); + } /* end if */ + + /* Resize chunk's dataspace dimensions to size of chunk */ + if(H5S_set_extent_real(tmp_fchunk,count)<0) { + H5S_close(tmp_fchunk); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk dimensions"); + } /* end if */ + + /* Move selection back to have correct offset in chunk */ + if(H5S_hyper_adjust(tmp_fchunk,coords)<0) { + H5S_close(tmp_fchunk); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection"); + } /* end if */ + + /* Add temporary chunk to the list of file chunks */ + + /* Allocate the file & memory chunk information */ + if (NULL==(new_fchunk_info = H5FL_MALLOC (H5D_fchunk_info_t))) { + H5S_close(tmp_fchunk); + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate file chunk info"); + } /* end if */ + + /* Initialize the file chunk information */ + + /* Set the chunk index */ + new_fchunk_info->index=chunk_index; + + /* Set the file chunk dataspace */ + new_fchunk_info->space=tmp_fchunk; + + /* Compute the chunk's coordinates */ + H5D_chunk_coords_assist(new_fchunk_info->coords, fm->f_ndims, fm->chunks, chunk_index); + + /* Insert the new file chunk into the TBBT tree */ + if(H5TB_dins(fm->fsel,new_fchunk_info,new_fchunk_info)==NULL) { + H5D_free_fchunk_info(new_fchunk_info); + HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert file chunk into TBBT"); + } /* end if */ + + /* Get number of elements selected in chunk */ + if((chunk_points=H5S_get_select_npoints(tmp_fchunk))<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection # of elements"); + + /* Decrement # of points left in file selection */ + sel_points-=chunk_points; + + /* Leave if we are done */ + if(sel_points==0) + HGOTO_DONE(SUCCEED); + assert(sel_points>0); + } /* end if */ + + /* Increment chunk index */ + chunk_index++; + + /* Set current increment dimension */ + curr_dim=fm->f_ndims-1; + + /* Increment chunk location in fastest changing dimension */ + coords[curr_dim]+=count[curr_dim]; + + /* Bring chunk location back into bounds, if necessary */ + if(coords[curr_dim]>sel_end[curr_dim]) { + do { + /* Reset current dimension's location to 0 */ + coords[curr_dim]=start_coords[curr_dim]; + + /* Decrement current dimension */ + curr_dim--; + + /* Increment chunk location in current dimension */ + coords[curr_dim]+=count[curr_dim]; + } while(coords[curr_dim]>sel_end[curr_dim]); + + /* Re-Calculate the index of this chunk */ + if(H5V_chunk_index(fm->f_ndims,coords,fm->layout->dim,fm->chunks,fm->down_chunks,&chunk_index)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index"); + } /* end if */ + + /* Move template chunk's offset to current location of chunk */ + if(H5S_hyper_move(tmp_fspace,coords)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't move chunk selection"); + } /* end while */ + +done: + if(tmp_fspace) + if(H5S_close(tmp_fspace)<0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release file dataspace copy"); + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5D_create_chunk_file_map() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_create_chunk_mem_map + * + * Purpose: Create all chunk selections in memory by copying the file + * chunk selections and adjusting their offsets to be correct + * for the memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Thursday, May 29, 2003 + * + * Assumptions: That the file and memory selections are the same shape. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_create_chunk_mem_map(fm_map *fm) +{ + H5TB_NODE *curr_node; /* Current node in TBBT */ + hsize_t file_off[H5O_LAYOUT_NDIMS*2]; /* Offset of first block in file selection */ + hsize_t mem_off[H5O_LAYOUT_NDIMS*2]; /* Offset of first block in memory selection */ + hssize_t adjust[H5O_LAYOUT_NDIMS]; /* Adjustment to make to all file chunks */ + hssize_t chunk_adjust[H5O_LAYOUT_NDIMS]; /* Adjustment to make to a particular chunk */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5D_create_chunk_mem_map); +#ifdef QAK +{ + hsize_t mem_dims[H5O_LAYOUT_NDIMS]; /* Dimensions of memory space */ + + if(H5S_get_simple_extent_dims(fm->mem_space, mem_dims, NULL)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality"); + + HDfprintf(stderr,"%s: mem_dims={",FUNC); + for(u=0; u<fm->m_ndims; u++) + HDfprintf(stderr,"%Hd%s",mem_dims[u],(u<(fm->m_ndims-1) ? ", " : "}\n")); +} +#endif /* QAK */ + + /* Get offset of first block in file selection */ + if(H5S_get_select_hyper_blocklist(fm->file_space, 0, 1, file_off)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection block info"); + + /* Get offset of first block in memory selection */ + if(H5S_get_select_hyper_blocklist(fm->mem_space, 0, 1, mem_off)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection block info"); + + /* Calculate the adjustment for memory selection from file selection */ + assert(fm->m_ndims==fm->f_ndims); + for(u=0; u<fm->f_ndims; u++) + adjust[u]=file_off[u]-mem_off[u]; +#ifdef QAK +{ + int mpi_rank; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + if(mpi_rank==1) { + HDfprintf(stderr,"%s: rank=%d - adjust={",FUNC,mpi_rank); + for(u=0; u<fm->f_ndims; u++) + HDfprintf(stderr,"%Hd%s",adjust[u],(u<(fm->f_ndims-1) ? ", " : "}\n")); + } /* end if */ +} +#endif /* QAK */ +#ifdef QAK +HDfprintf(stderr,"%s: adjust={",FUNC); +for(u=0; u<fm->f_ndims; u++) + HDfprintf(stderr,"%Hd%s",adjust[u],(u<(fm->f_ndims-1) ? ", " : "}\n")); +#endif /* QAK */ + + /* Iterate over each chunk in the file chunk list */ + curr_node=H5TB_first(fm->fsel->root); + while(curr_node) { + H5D_fchunk_info_t *fchunk_info; /* Pointer to file chunk information */ + H5D_mchunk_info_t *mchunk_info; /* Pointer to memory chunk information */ + + /* Get pointer to chunk's information */ + fchunk_info=curr_node->data; + assert(fchunk_info); + + /* Allocate space for the memory chunk information */ + if (NULL==(mchunk_info = H5FL_MALLOC (H5D_mchunk_info_t))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate memory chunk info"); + + /* Copy the information */ + + /* Set the chunk index */ + mchunk_info->index=fchunk_info->index; + + /* Copy the memory dataspace */ + if((mchunk_info->space = H5S_copy(fm->mem_space))==NULL) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space"); + + /* Release the current selection */ + if(H5S_select_release(mchunk_info->space)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection"); + + /* Copy the file chunk's selection */ + if(H5S_select_copy(mchunk_info->space,fchunk_info->space)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy selection"); + + /* Compensate for the chunk offset */ + for(u=0; u<fm->f_ndims; u++) + chunk_adjust[u]=adjust[u]-(fchunk_info->coords[u]*fm->layout->dim[u]); +#ifdef QAK +{ + int mpi_rank; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + if(mpi_rank==1) { + HDfprintf(stderr,"%s: rank=%d - Before adjusting memory selection\n",FUNC,mpi_rank); + HDfprintf(stderr,"%s: rank=%d - chunk_adjust={",FUNC,mpi_rank); + for(u=0; u<fm->f_ndims; u++) + HDfprintf(stderr,"%Hd%s",chunk_adjust[u],(u<(fm->f_ndims-1) ? ", " : "}\n")); + } /* end if */ +} +#endif /* QAK */ +#ifdef QAK +HDfprintf(stderr,"%s: Before adjusting memory selection\n",FUNC); +HDfprintf(stderr,"%s: chunk_adjust={",FUNC); +for(u=0; u<fm->f_ndims; u++) + HDfprintf(stderr,"%Hd%s",chunk_adjust[u],(u<(fm->f_ndims-1) ? ", " : "}\n")); +#endif /* QAK */ + /* Adjust the selection */ + if(H5S_hyper_adjust(mchunk_info->space,chunk_adjust)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection"); +#ifdef QAK +{ + int mpi_rank; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + if(mpi_rank==1) + HDfprintf(stderr,"%s: rank=%d - After adjusting memory selection\n",FUNC,mpi_rank); +} +#endif /* QAK */ +#ifdef QAK +HDfprintf(stderr,"%s: After adjusting memory selection\n",FUNC); + +{ + hsize_t mem_dims[H5O_LAYOUT_NDIMS]; /* Dimensions of memory space */ + + if(H5S_get_simple_extent_dims(mchunk_info->space, mem_dims, NULL)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality"); + + HDfprintf(stderr,"%s: mem_dims={",FUNC); + for(u=0; u<fm->m_ndims; u++) + HDfprintf(stderr,"%Hd%s",mem_dims[u],(u<(fm->m_ndims-1) ? ", " : "}\n")); +} +#endif /* QAK */ + /* Insert the new memory chunk into the TBBT tree */ + if(H5TB_dins(fm->msel,mchunk_info,mchunk_info)==NULL) + HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert memory chunk into TBBT"); + + /* Get the next chunk node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5D_create_chunk_mem_map() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_chunk_mem_cb * * Purpose: Callback routine for file selection iterator. Used when - * creating selections in memory and each chunk for each chunk. + * creating selections in memory for each chunk. * * Return: Non-negative on success/Negative on failure * @@ -2533,54 +2973,26 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5D_chunk_cb(void UNUSED *elem, hid_t UNUSED type_id, hsize_t ndims, hssize_t *coords, void *_fm) +H5D_chunk_mem_cb(void UNUSED *elem, hid_t UNUSED type_id, hsize_t ndims, hssize_t *coords, void *_fm) { fm_map *fm = (fm_map*)_fm; /* File<->memory chunk mapping info */ - H5S_t *fspace; /* File chunk's dataspace */ H5S_t *mspace; /* Memory chunk's dataspace */ - hssize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */ hssize_t coords_in_mem[H5O_LAYOUT_NDIMS]; /* Coordinates of element in memory */ hsize_t chunk_index; /* Chunk index */ hsize_t u; /* Local index variables */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOINIT(H5D_chunk_cb); -#ifdef QAK -{ - unsigned u; - HDfprintf(stderr,"%s: coords={",FUNC); - for(u=0; u<ndims; u++) - HDfprintf(stderr,"%Hd%s",coords[u],(u<(ndims-1)?", ":"}\n")); -} -#endif /* QAK */ + FUNC_ENTER_NOINIT(H5D_chunk_mem_cb); /* Calculate the index of this chunk */ if(H5V_chunk_index((unsigned)ndims,coords,fm->layout->dim,fm->chunks,fm->down_chunks,&chunk_index)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index"); -#ifdef QAK -HDfprintf(stderr,"%s: chunk_index=%Hu\n",FUNC,chunk_index); -#endif /* QAK */ - - /*convert coords from relative to whole file space to relative to its chunk space, - *pass into H5S_select_hyperslab.*/ - for(u=0; u<ndims; u++) - coords_in_chunk[u] = coords[u] % fm->layout->dim[u]; - -#ifdef QAK -{ - unsigned u; - HDfprintf(stderr,"%s: coords_in_chunk={",FUNC); - for(u=0; u<ndims; u++) - HDfprintf(stderr,"%Hd%s",coords_in_chunk[u],(u<(ndims-1)?", ":"}\n")); -} -#endif /* QAK */ /* Find correct chunk in file & memory TBBTs */ if(chunk_index==fm->last_index) { /* If the chunk index is the same as the last chunk index we used, * get the cached spaces to operate on. */ - fspace=fm->last_fchunk; mspace=fm->last_mchunk; } /* end if */ else { @@ -2589,48 +3001,22 @@ HDfprintf(stderr,"%s: chunk_index=%Hu\n",FUNC,chunk_index); * find the chunk in the tree. */ /* Get the chunk node from the TBBT */ - if((chunk_node=H5TB_dfind(fm->fsel,&chunk_index,NULL))!=NULL) { + if((chunk_node=H5TB_dfind(fm->msel,&chunk_index,NULL))!=NULL) { /* We found the correct chunk already in the tree */ - /* Get the file space information from the node */ - fspace=((H5D_fchunk_info_t *)(chunk_node->data))->space; - - /* Look up the memory space information for the chunk */ - if((chunk_node=H5TB_dfind(fm->msel,&chunk_index,NULL))==NULL) - HGOTO_ERROR (H5E_DATASPACE, H5E_NOTFOUND, FAIL, "can't find memory chunk info"); - - /* Get the file space information from the node */ + /* Get the memory space information from the node */ mspace=((H5D_mchunk_info_t *)(chunk_node->data))->space; } /* end if */ else { - H5D_fchunk_info_t *new_fchunk_info; /* File chunk information to insert into tree */ H5D_mchunk_info_t *new_mchunk_info; /* Memory chunk information to insert into tree */ /* The correct chunk is not already in the tree, create a new node */ /* in both the file and memory chunk trees */ - /* Allocate the file & memory chunk information */ - if (NULL==(new_fchunk_info = H5FL_MALLOC (H5D_fchunk_info_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate file chunk info"); + /* Allocate the memory chunk information */ if (NULL==(new_mchunk_info = H5FL_MALLOC (H5D_mchunk_info_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate memory chunk info"); - /* Initialize the file chunk information */ - - /* Set the chunk index */ - new_fchunk_info->index=chunk_index; - - /* Copy the template file chunk dataspace */ - if((new_fchunk_info->space = H5S_copy(fm->fchunk_tmpl))==NULL) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space"); - - /* Compute the chunk's coordinates */ - H5D_chunk_coords_assist(new_fchunk_info->coords, fm->f_ndims, fm->chunks, chunk_index); - - /* Insert the new file chunk into the TBBT tree */ - if(H5TB_dins(fm->fsel,new_fchunk_info,new_fchunk_info)==NULL) - HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert file chunk into TBBT"); - /* Initialize the memory chunk information */ /* Set the chunk index */ @@ -2645,32 +3031,18 @@ HDfprintf(stderr,"%s: chunk_index=%Hu\n",FUNC,chunk_index); HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert memory chunk into TBBT"); /* Get the dataspaces for use in this routine */ - fspace=new_fchunk_info->space; mspace=new_mchunk_info->space; } /* end else */ /* Update the "last chunk seen" information */ fm->last_index=chunk_index; - fm->last_fchunk=fspace; fm->last_mchunk=mspace; } /* end else */ - /* Add point to file selection for chunk */ - if(H5S_hyper_add_span_element(fspace, fm->f_ndims, coords_in_chunk)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element"); - /* Get coordinates of selection iterator for memory */ if(H5S_select_iter_coords(&fm->mem_iter,coords_in_mem)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator coordinates"); -#ifdef QAK -{ - unsigned u; - HDfprintf(stderr,"%s: coords_in_mem={",FUNC); - for(u=0; u<fm->m_ndims; u++) - HDfprintf(stderr,"%Hd%s",coords_in_mem[u],(u<(fm->m_ndims-1)?", ":"}\n")); -} -#endif /* QAK */ /* Add point to memory selection for chunk */ if(H5S_hyper_add_span_element(mspace, fm->m_ndims, coords_in_mem)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element"); @@ -2681,4 +3053,4 @@ HDfprintf(stderr,"%s: chunk_index=%Hu\n",FUNC,chunk_index); done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5D_chunk_cb() */ +} /* end H5D_chunk_mem_cb() */ diff --git a/src/H5Distore.c b/src/H5Distore.c index a5362cc..ffbc6de 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -1743,7 +1743,19 @@ H5F_istore_readvv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, chunk_coords_in_elmts[u] = chunk_coords[u] * (hssize_t)(layout->dim[u]); /* Get the address of this chunk on disk */ +#ifdef QAK +HDfprintf(stderr,"%s: chunk_coords_in_elmts={",FUNC); +for(u=0; u<layout->ndims; u++) + HDfprintf(stderr,"%Hd%s",chunk_coords_in_elmts[u],(u<(layout->ndims-1) ? ", " : "}\n")); +#endif /* QAK */ chunk_addr=H5F_istore_get_addr(f, dxpl_id, layout, chunk_coords_in_elmts); +#ifdef QAK +HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Hu\n",FUNC,chunk_addr,chunk_size); +HDfprintf(stderr,"%s: chunk_len_arr[%Zu]=%Zu\n",FUNC,*chunk_curr_seq,chunk_len_arr[*chunk_curr_seq]); +HDfprintf(stderr,"%s: chunk_offset_arr[%Zu]=%Hu\n",FUNC,*chunk_curr_seq,chunk_offset_arr[*chunk_curr_seq]); +HDfprintf(stderr,"%s: mem_len_arr[%Zu]=%Zu\n",FUNC,*mem_curr_seq,mem_len_arr[*mem_curr_seq]); +HDfprintf(stderr,"%s: mem_offset_arr[%Zu]=%Hu\n",FUNC,*mem_curr_seq,mem_offset_arr[*mem_curr_seq]); +#endif /* QAK */ /* * If the chunk is too large to load into the cache and it has no @@ -1850,7 +1862,19 @@ H5F_istore_writevv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, chunk_coords_in_elmts[u] = chunk_coords[u] * (hssize_t)(layout->dim[u]); /* Get the address of this chunk on disk */ +#ifdef QAK +HDfprintf(stderr,"%s: chunk_coords_in_elmts={",FUNC); +for(u=0; u<layout->ndims; u++) + HDfprintf(stderr,"%Hd%s",chunk_coords_in_elmts[u],(u<(layout->ndims-1) ? ", " : "}\n")); +#endif /* QAK */ chunk_addr=H5F_istore_get_addr(f, dxpl_id, layout, chunk_coords_in_elmts); +#ifdef QAK +HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Hu\n",FUNC,chunk_addr,chunk_size); +HDfprintf(stderr,"%s: chunk_len_arr[%Zu]=%Zu\n",FUNC,*chunk_curr_seq,chunk_len_arr[*chunk_curr_seq]); +HDfprintf(stderr,"%s: chunk_offset_arr[%Zu]=%Hu\n",FUNC,*chunk_curr_seq,chunk_offset_arr[*chunk_curr_seq]); +HDfprintf(stderr,"%s: mem_len_arr[%Zu]=%Zu\n",FUNC,*mem_curr_seq,mem_len_arr[*mem_curr_seq]); +HDfprintf(stderr,"%s: mem_offset_arr[%Zu]=%Hu\n",FUNC,*mem_curr_seq,mem_offset_arr[*mem_curr_seq]); +#endif /* QAK */ /* * If the chunk is too large to load into the cache and it has no diff --git a/src/H5Fistore.c b/src/H5Fistore.c index a5362cc..ffbc6de 100644 --- a/src/H5Fistore.c +++ b/src/H5Fistore.c @@ -1743,7 +1743,19 @@ H5F_istore_readvv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, chunk_coords_in_elmts[u] = chunk_coords[u] * (hssize_t)(layout->dim[u]); /* Get the address of this chunk on disk */ +#ifdef QAK +HDfprintf(stderr,"%s: chunk_coords_in_elmts={",FUNC); +for(u=0; u<layout->ndims; u++) + HDfprintf(stderr,"%Hd%s",chunk_coords_in_elmts[u],(u<(layout->ndims-1) ? ", " : "}\n")); +#endif /* QAK */ chunk_addr=H5F_istore_get_addr(f, dxpl_id, layout, chunk_coords_in_elmts); +#ifdef QAK +HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Hu\n",FUNC,chunk_addr,chunk_size); +HDfprintf(stderr,"%s: chunk_len_arr[%Zu]=%Zu\n",FUNC,*chunk_curr_seq,chunk_len_arr[*chunk_curr_seq]); +HDfprintf(stderr,"%s: chunk_offset_arr[%Zu]=%Hu\n",FUNC,*chunk_curr_seq,chunk_offset_arr[*chunk_curr_seq]); +HDfprintf(stderr,"%s: mem_len_arr[%Zu]=%Zu\n",FUNC,*mem_curr_seq,mem_len_arr[*mem_curr_seq]); +HDfprintf(stderr,"%s: mem_offset_arr[%Zu]=%Hu\n",FUNC,*mem_curr_seq,mem_offset_arr[*mem_curr_seq]); +#endif /* QAK */ /* * If the chunk is too large to load into the cache and it has no @@ -1850,7 +1862,19 @@ H5F_istore_writevv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, chunk_coords_in_elmts[u] = chunk_coords[u] * (hssize_t)(layout->dim[u]); /* Get the address of this chunk on disk */ +#ifdef QAK +HDfprintf(stderr,"%s: chunk_coords_in_elmts={",FUNC); +for(u=0; u<layout->ndims; u++) + HDfprintf(stderr,"%Hd%s",chunk_coords_in_elmts[u],(u<(layout->ndims-1) ? ", " : "}\n")); +#endif /* QAK */ chunk_addr=H5F_istore_get_addr(f, dxpl_id, layout, chunk_coords_in_elmts); +#ifdef QAK +HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Hu\n",FUNC,chunk_addr,chunk_size); +HDfprintf(stderr,"%s: chunk_len_arr[%Zu]=%Zu\n",FUNC,*chunk_curr_seq,chunk_len_arr[*chunk_curr_seq]); +HDfprintf(stderr,"%s: chunk_offset_arr[%Zu]=%Hu\n",FUNC,*chunk_curr_seq,chunk_offset_arr[*chunk_curr_seq]); +HDfprintf(stderr,"%s: mem_len_arr[%Zu]=%Zu\n",FUNC,*mem_curr_seq,mem_len_arr[*mem_curr_seq]); +HDfprintf(stderr,"%s: mem_offset_arr[%Zu]=%Hu\n",FUNC,*mem_curr_seq,mem_offset_arr[*mem_curr_seq]); +#endif /* QAK */ /* * If the chunk is too large to load into the cache and it has no @@ -454,12 +454,8 @@ H5S_close(H5S_t *ds) assert(ds); - /* If there was a previous offset for the selection, release it */ - if(ds->select.offset!=NULL) - ds->select.offset=H5FL_ARR_FREE(hssize_t,ds->select.offset); - /* Release selection (this should come before the extent release) */ - (*ds->select.release)(ds); + H5S_select_release(ds); /* Release extent */ H5S_extent_release(ds); @@ -1913,14 +1909,9 @@ H5Soffset_simple(hid_t space_id, const hssize_t *offset) if (offset == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no offset specified"); - /* Allocate space for new offset */ - if(space->select.offset==NULL) { - if (NULL==(space->select.offset = H5FL_ARR_MALLOC(hssize_t,space->extent.u.simple.rank))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - } - - /* Copy the offset over */ - HDmemcpy(space->select.offset,offset,sizeof(hssize_t)*space->extent.u.simple.rank); + /* Set the selection offset */ + if(H5S_select_offset(space,offset)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set offset"); done: FUNC_LEAVE_API(ret_value); @@ -1964,16 +1955,8 @@ H5S_set_extent( H5S_t *space, const hsize_t *size ) } /* end for */ /* Update */ - if (ret_value) { - hsize_t nelem; /* Number of elements in extent */ - - /* Change the dataspace size & re-compute the number of elements in the extent */ - for (u=0, nelem=1; u < space->extent.u.simple.rank; u++ ) { - space->extent.u.simple.size[u] = size[u]; - nelem*=space->extent.u.simple.size[u]; - } /* end for */ - space->extent.nelem = nelem; - } /* end if */ + if (ret_value) + H5S_set_extent_real(space,size); done: FUNC_LEAVE_NOAPI(ret_value); @@ -1981,6 +1964,46 @@ done: /*------------------------------------------------------------------------- + * Function: H5S_set_extent_real + * + * Purpose: Modify the dimensions of a data space. Based on H5S_extend + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: March 13, 2002 + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_set_extent_real( H5S_t *space, const hsize_t *size ) +{ + hsize_t nelem; /* Number of elements in extent */ + unsigned u; /* Local index variable */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_set_extent_real, FAIL ); + + /* Check args */ + assert(space && H5S_SIMPLE==space->extent.type ); + assert(size); + + /* Change the dataspace size & re-compute the number of elements in the extent */ + for (u=0, nelem=1; u < space->extent.u.simple.rank; u++ ) { + space->extent.u.simple.size[u] = size[u]; + nelem*=space->extent.u.simple.size[u]; + } /* end for */ + space->extent.nelem = nelem; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5S_set_extent_real() */ + + +/*------------------------------------------------------------------------- * Function: H5S_debug * * Purpose: Prints debugging information about a data space. diff --git a/src/H5Shyper.c b/src/H5Shyper.c index 0687251..e62dc4f 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -1783,8 +1783,14 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t *buf) UINT32ENCODE(buf, (uint32_t)offset[i]); /* Encode hyperslab ending location */ - for(i=0; i<ndims; i++) - UINT32ENCODE(buf, (uint32_t)(offset[i]+(diminfo[i].block-1))); + for(i=0; i<ndims; i++) { + if(diminfo[i].stride==1) { + UINT32ENCODE(buf, (uint32_t)(offset[i]+(diminfo[i].count-1))); + } /* end if */ + else { + UINT32ENCODE(buf, (uint32_t)(offset[i]+(diminfo[i].block-1))); + } /* end else */ + } /* end for */ /* Move the offset to the next sequence to start */ offset[fast_dim]+=diminfo[fast_dim].stride; @@ -1878,10 +1884,12 @@ H5S_hyper_deserialize (H5S_t *space, const uint8_t *buf) size_t num_elem=0; /* number of elements in selection */ hssize_t *start=NULL; /* hyperslab start information */ hssize_t *end=NULL; /* hyperslab end information */ + hsize_t *stride=NULL; /* hyperslab stride information */ hsize_t *count=NULL; /* hyperslab count information */ hsize_t *block=NULL; /* hyperslab block information */ hssize_t *tstart=NULL; /* temporary hyperslab pointers */ hssize_t *tend=NULL; /* temporary hyperslab pointers */ + hsize_t *tstride=NULL; /* temporary hyperslab pointers */ hsize_t *tcount=NULL; /* temporary hyperslab pointers */ hsize_t *tblock=NULL; /* temporary hyperslab pointers */ unsigned i,j; /* local counting variables */ @@ -1909,10 +1917,14 @@ H5S_hyper_deserialize (H5S_t *space, const uint8_t *buf) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab information"); if((count = H5FL_ARR_MALLOC(hsize_t,rank))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab information"); + if((stride = H5FL_ARR_MALLOC(hsize_t,rank))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab information"); - /* Set the count for all blocks */ - for(tcount=count,j=0; j<rank; j++,tcount++) + /* Set the count & stride for all blocks */ + for(tcount=count,tstride=stride,j=0; j<rank; j++,tstride++,tcount++) { *tcount=1; + *tstride=0; + } /* end for */ /* Retrieve the coordinates from the buffer */ for(i=0; i<num_elem; i++) { @@ -1929,13 +1941,14 @@ H5S_hyper_deserialize (H5S_t *space, const uint8_t *buf) *tblock=(*tend-*tstart)+1; /* Select or add the hyperslab to the current selection */ - if((ret_value=H5S_select_hyperslab(space,(i==0 ? H5S_SELECT_SET : H5S_SELECT_OR),start,NULL,count,block))<0) + if((ret_value=H5S_select_hyperslab(space,(i==0 ? H5S_SELECT_SET : H5S_SELECT_OR),start,stride,count,block))<0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection"); } /* end for */ /* Free temporary buffers */ H5FL_ARR_FREE(hsize_t,start); H5FL_ARR_FREE(hsize_t,end); + H5FL_ARR_FREE(hsize_t,stride); H5FL_ARR_FREE(hsize_t,count); H5FL_ARR_FREE(hsize_t,block); @@ -2078,7 +2091,7 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -static herr_t +herr_t H5S_get_select_hyper_blocklist(H5S_t *space, hsize_t startblock, hsize_t numblocks, hsize_t *buf) { H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */ @@ -2132,8 +2145,12 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hsize_t startblock, hsize_t numbloc /* Compute the ending location */ HDmemcpy(buf,offset,sizeof(hsize_t)*ndims); - for(i=0; i<ndims; i++) - buf[i]+=(diminfo[i].block-1); + for(i=0; i<ndims; i++) { + if(diminfo[i].stride==1) + buf[i]+=(diminfo[i].count-1); + else + buf[i]+=(diminfo[i].block-1); + } /* end for */ buf+=ndims; /* Decrement the number of blocks to retrieve */ @@ -3174,6 +3191,423 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_hyper_convert + PURPOSE + Convert a compatible selection to span tree form + USAGE + herr_t H5S_hyper_convert(space) + H5S_t *space; IN/OUT: Pointer to dataspace to convert + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Converts a compatible selection (currently only "all" selections) to the + span-tree form of a hyperslab selection. (Point and "none" selection aren't + currently supported and hyperslab selection always have the span-tree form + available). + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_hyper_convert(H5S_t *space) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5S_hyper_convert); + + assert(space); + + /* Check the type of selection */ + switch(space->select.type) { + case H5S_SEL_ALL: /* All elements selected in dataspace */ + /* Convert current "all" selection to "real" hyperslab selection */ + { + hssize_t tmp_start[H5O_LAYOUT_NDIMS]; /* Temporary start information */ + hsize_t tmp_stride[H5O_LAYOUT_NDIMS]; /* Temporary stride information */ + hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary count information */ + hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary block information */ + unsigned u; /* Local index variable */ + + /* Fill in temporary information for the dimensions */ + for(u=0; u<space->extent.u.simple.rank; u++) { + tmp_start[u]=0; + tmp_stride[u]=0; + tmp_count[u]=1; + tmp_block[u]=space->extent.u.simple.size[u]; + } /* end for */ + + /* Convert to hyperslab selection */ + if(H5S_select_hyperslab(space,H5S_SELECT_SET,tmp_start,tmp_stride,tmp_count,tmp_block)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection"); + } /* end case */ + break; + + case H5S_SEL_HYPERSLABS: /* Hyperslab selection */ + break; + + case H5S_SEL_NONE: /* No elements selected in dataspace */ + case H5S_SEL_POINTS: /* Point selection */ + default: + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "can't convert to span tree selection"); + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_hyper_convert() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_intersect_helper + PURPOSE + Helper routine to detect intersections in span trees + USAGE + htri_t H5S_hyper_intersect_helper(spans1, spans2) + H5S_hyper_span_info_t *spans1; IN: First span tree to operate with + H5S_hyper_span_info_t *spans2; IN: Second span tree to operate with + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Quickly detect intersections between two span trees + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static htri_t +H5S_hyper_intersect_helper (H5S_hyper_span_info_t *spans1, H5S_hyper_span_info_t *spans2) +{ + H5S_hyper_span_t *curr1; /* Pointer to current span in 1st span tree */ + H5S_hyper_span_t *curr2; /* Pointer to current span in 2nd span tree */ + htri_t status; /* Status from recursive call */ + htri_t ret_value=FALSE; /* Return value */ + + FUNC_ENTER_NOINIT(H5S_hyper_intersect_helper); + + /* Sanity check */ + assert((spans1 && spans2) || (spans1==NULL && spans2==NULL)); + + /* "NULL" span trees compare as overlapping */ + if(spans1==NULL && spans2==NULL) + HGOTO_DONE(TRUE); + + /* Get the span lists for each span in this tree */ + curr1=spans1->head; + curr2=spans2->head; + + /* Iterate over the spans in each tree */ + while(curr1!=NULL && curr2!=NULL) { + /* Check for 1st span entirely before 2nd span */ + if(curr1->high<curr2->low) + curr1=curr1->next; + /* Check for 2nd span entirely before 1st span */ + else if(curr2->high<curr1->low) + curr2=curr2->next; + /* Spans must overlap */ + else { + /* Recursively check spans in next dimension down */ + if((status=H5S_hyper_intersect_helper(curr1->down,curr2->down))<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab intersection check"); + + /* If there is a span intersection in the down dimensions, the span trees overlap */ + if(status==TRUE) + HGOTO_DONE(TRUE); + + /* No intersection in down dimensions, advance to next span */ + if(curr1->high<curr2->high) + curr1=curr1->next; + else + curr2=curr2->next; + } /* end else */ + } /* end while */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_hyper_intersect_helper() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_intersect + PURPOSE + Detect intersections in span trees + USAGE + htri_t H5S_hyper_intersect_helper(space1, space2) + H5S_t *space1; IN: First dataspace to operate on span tree + H5S_t *space2; IN: Second dataspace to operate on span tree + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Quickly detect intersections between two span trees + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +htri_t +H5S_hyper_intersect (H5S_t *space1, H5S_t *space2) +{ + htri_t ret_value=FAIL; /* Return value */ + + FUNC_ENTER_NOINIT(H5S_hyper_intersect); + + /* Sanity check */ + assert(space1); + assert(space2); + + /* Check that the space selections both have span trees */ + if(space1->select.sel_info.hslab.span_lst==NULL || + space2->select.sel_info.hslab.span_lst==NULL) + HGOTO_ERROR(H5E_DATASPACE, H5E_ARGS, FAIL, "dataspace does not have span tree"); + + /* Check that the dataspaces are both the same rank */ + if(space1->extent.u.simple.rank!=space2->extent.u.simple.rank) + HGOTO_ERROR(H5E_DATASPACE, H5E_ARGS, FAIL, "dataspace ranks don't match"); + + /* Perform the span-by-span intersection check */ + if((ret_value=H5S_hyper_intersect_helper(space1->select.sel_info.hslab.span_lst,space2->select.sel_info.hslab.span_lst))<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab intersection check"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_hyper_intersect() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_adjust_helper + PURPOSE + Helper routine to adjust offsets in span trees + USAGE + herr_t H5S_hyper_adjust_helper(spans, offset) + H5S_hyper_span_info_t *spans; IN: Span tree to operate with + const hssize_t *offset; IN: Offset to subtract + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Adjust the location of the spans in a span tree by subtracting an offset + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S_hyper_adjust_helper (H5S_hyper_span_info_t *spans, const hssize_t *offset) +{ + H5S_hyper_span_t *span; /* Pointer to current span in span tree */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5S_hyper_adjust_helper); + + /* Sanity check */ + assert(spans); + assert(offset); + + /* Check if we've already set this down span tree */ + if(spans->scratch!=(H5S_hyper_span_info_t *)~((size_t)NULL)) { + /* Set the tree's scratch pointer */ + spans->scratch=(H5S_hyper_span_info_t *)~((size_t)NULL); + + /* Get the span lists for each span in this tree */ + span=spans->head; + + /* Iterate over the spans in tree */ + while(span!=NULL) { +#ifdef QAK +HDfprintf(stderr,"%s: span={%Hd, %Hd}, *offset=%Hd\n",FUNC,span->low,span->high,*offset); +#endif /* QAK */ + /* Adjust span offset */ + span->low-=*offset; + assert(span->low>=0); + span->high-=*offset; + assert(span->high>=0); + + /* Recursively adjust spans in next dimension down */ + if(span->down!=NULL) { + if(H5S_hyper_adjust_helper(span->down,offset+1)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab adjustment"); + } /* end if */ + + /* Advance to next span in this dimension */ + span=span->next; + } /* end while */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_hyper_adjust_helper() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_adjust + PURPOSE + Adjust a hyperslab selection by subtracting an offset + USAGE + herr_t H5S_hyper_adjust(space,offset) + H5S_t *space; IN/OUT: Pointer to dataspace to adjust + const hssize_t *offset; IN: Offset to subtract + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Moves a hyperslab selection by subtracting an offset from it. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_hyper_adjust(H5S_t *space, const hssize_t *offset) +{ + unsigned u; /* Local index variable */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5S_hyper_adjust); + + assert(space); + assert(offset); + + /* Subtract the offset from the "regular" coordinates, if they exist */ + if(space->select.sel_info.hslab.diminfo) { + for(u=0; u<space->extent.u.simple.rank; u++) { + space->select.sel_info.hslab.diminfo[u].start-=offset[u]; + assert(space->select.sel_info.hslab.diminfo[u].start>=0); + } /* end for */ + } /* end if */ + + /* Subtract the offset from the span tree coordinates, if they exist */ + if(space->select.sel_info.hslab.span_lst) { + if(H5S_hyper_adjust_helper(space->select.sel_info.hslab.span_lst,offset)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab offset adjustment"); + + /* Reset the scratch pointers for the next routine which needs them */ + if(H5S_hyper_span_scratch(space->select.sel_info.hslab.span_lst,NULL)==FAIL) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't reset hyperslab scratch pointer"); + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_hyper_adjust() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_move_helper + PURPOSE + Helper routine to move offset in span trees + USAGE + herr_t H5S_hyper_move_helper(spans, offset) + H5S_hyper_span_info_t *spans; IN: Span tree to operate with + const hssize_t *offset; IN: Offset to move to + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Adjust the location of the spans in a span tree by moving selection to an + offset. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S_hyper_move_helper (H5S_hyper_span_info_t *spans, const hssize_t *offset) +{ + H5S_hyper_span_t *span; /* Pointer to current span in span tree */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5S_hyper_move_helper); + + /* Sanity check */ + assert(spans); + assert(offset); + + /* Check if we've already set this down span tree */ + if(spans->scratch!=(H5S_hyper_span_info_t *)~((size_t)NULL)) { + /* Set the tree's scratch pointer */ + spans->scratch=(H5S_hyper_span_info_t *)~((size_t)NULL); + + /* Get the span lists for each span in this tree */ + span=spans->head; + + /* Iterate over the spans in tree */ + while(span!=NULL) { + /* Adjust span location */ + span->high=*offset+(span->high-span->low); + assert(span->high>=0); + span->low=*offset; + assert(span->low>=0); + + /* Recursively move spans in next dimension down */ + if(span->down!=NULL) { + if(H5S_hyper_move_helper(span->down,offset+1)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab movement"); + } /* end if */ + + /* Advance to next span in this dimension */ + span=span->next; + } /* end while */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_hyper_move_helper() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_move + PURPOSE + Move a hyperslab selection by to an offset + USAGE + herr_t H5S_hyper_move(space,offset) + H5S_t *space; IN/OUT: Pointer to dataspace to move + const hssize_t *offset; IN: Offset to move to + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Moves a hyperslab selection to a new offset. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_hyper_move(H5S_t *space, const hssize_t *offset) +{ + unsigned u; /* Local index variable */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5S_hyper_move); + + assert(space); + assert(offset); + + /* Move to the offset with the "regular" coordinates, if they exist */ + if(space->select.sel_info.hslab.diminfo) { + for(u=0; u<space->extent.u.simple.rank; u++) { + space->select.sel_info.hslab.diminfo[u].start=offset[u]; + assert(space->select.sel_info.hslab.diminfo[u].start>=0); + } /* end for */ + } /* end if */ + + /* Subtract the offset from the span tree coordinates, if they exist */ + if(space->select.sel_info.hslab.span_lst) { + if(H5S_hyper_move_helper(space->select.sel_info.hslab.span_lst,offset)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab offset movement"); + + /* Reset the scratch pointers for the next routine which needs them */ + if(H5S_hyper_span_scratch(space->select.sel_info.hslab.span_lst,NULL)==FAIL) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't reset hyperslab scratch pointer"); + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_hyper_move() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_hyper_append_span PURPOSE Create a new span and append to span list @@ -5158,7 +5592,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, /* Fill in temporary information for the dimensions */ for(u=0; u<space->extent.u.simple.rank; u++) { tmp_start[u]=0; - tmp_stride[u]=1; + tmp_stride[u]=0; tmp_count[u]=1; tmp_block[u]=space->extent.u.simple.size[u]; } /* end for */ diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 5792e67..4e6eda7 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -168,6 +168,7 @@ H5_DLL herr_t H5S_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, const H5S_t H5_DLL H5S_t *H5S_read(struct H5G_entry_t *ent, hid_t dxpl_id); H5_DLL int H5S_extend(H5S_t *space, const hsize_t *size); H5_DLL int H5S_set_extent(H5S_t *space, const hsize_t *size); +H5_DLL herr_t H5S_set_extent_real(H5S_t *space, const hsize_t *size); H5_DLL H5S_t *H5S_create_simple(unsigned rank, const hsize_t dims[/*rank*/], const hsize_t maxdims[/*rank*/]); H5_DLL herr_t H5S_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *stream, @@ -204,14 +205,22 @@ H5_DLL herr_t H5S_select_write(H5F_t *f, struct H5O_layout_t *layout, const void *buf/*out*/); H5_DLL htri_t H5S_select_valid(const H5S_t *space); H5_DLL hssize_t H5S_get_select_npoints(const H5S_t *space); +H5_DLL herr_t H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); +H5_DLL herr_t H5S_select_offset(H5S_t *space, const hssize_t *offset); +H5_DLL herr_t H5S_select_release(H5S_t *ds); H5_DLL herr_t H5S_select_all(H5S_t *space, unsigned rel_prev); H5_DLL herr_t H5S_select_none(H5S_t *space); H5_DLL herr_t H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, const hssize_t start[], - const hsize_t *stride, const hsize_t count[], - const hsize_t *block); + const hsize_t *stride, const hsize_t count[], const hsize_t *block); +H5_DLL herr_t H5S_get_select_hyper_blocklist(H5S_t *space, hsize_t startblock, + hsize_t numblocks, hsize_t *buf); H5_DLL herr_t H5S_hyper_add_span_element(H5S_t *space, unsigned rank, hssize_t *coords); H5_DLL herr_t H5S_hyper_reset_scratch(H5S_t *space); +H5_DLL herr_t H5S_hyper_convert(H5S_t *space); +H5_DLL htri_t H5S_hyper_intersect (H5S_t *space1, H5S_t *space2); +H5_DLL herr_t H5S_hyper_adjust(H5S_t *space, const hssize_t *offset); +H5_DLL herr_t H5S_hyper_move(H5S_t *space, const hssize_t *offset); /* Operations on selection iterators */ H5_DLL herr_t H5S_select_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size); diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 5551412..6c3d42d 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -92,6 +92,50 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_select_offset + PURPOSE + Set the selection offset for a datapace + USAGE + herr_t H5S_select_offset(space, offset) + H5S_t *space; IN/OUT: Dataspace object to set selection offset + const hssize_t *offset; IN: Offset to position the selection at + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Sets the selection offset for the dataspace + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Only works for simple dataspaces currently + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_select_offset(H5S_t *space, const hssize_t *offset) +{ + herr_t ret_value=SUCCEED; /* return value */ + + FUNC_ENTER_NOAPI(H5S_select_offset, FAIL); + + /* Check args */ + assert(space); + assert(offset); + + /* Allocate space for new offset */ + if(space->select.offset==NULL) { + if (NULL==(space->select.offset = H5FL_ARR_MALLOC(hssize_t,space->extent.u.simple.rank))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + } + + /* Copy the offset over */ + HDmemcpy(space->select.offset,offset,sizeof(hssize_t)*space->extent.u.simple.rank); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_select_offset() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_select_copy PURPOSE Copy a selection from one dataspace to another @@ -173,6 +217,41 @@ done: } /* H5S_select_copy() */ +/*------------------------------------------------------------------------- + * Function: H5S_select_release + * + * Purpose: Releases all memory associated with a dataspace selection. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, May 30, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_select_release(H5S_t *ds) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_select_release, FAIL); + + assert(ds); + + /* If there was a previous offset for the selection, release it */ + if(ds->select.offset!=NULL) + ds->select.offset=H5FL_ARR_FREE(hssize_t,ds->select.offset); + + /* Call the selection type's release function */ + (*ds->select.release)(ds); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5S_select_release() */ + + /*-------------------------------------------------------------------------- NAME H5Sget_select_npoints @@ -423,7 +502,7 @@ H5Sget_select_bounds(hid_t spaceid, hsize_t *start, hsize_t *end) if (NULL == (space=H5I_object_verify(spaceid, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); - ret_value = (*space->select.bounds)(space,start,end); + ret_value = H5S_get_select_bounds(space,start,end); done: FUNC_LEAVE_API(ret_value); @@ -432,6 +511,52 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_get_select_bounds + PURPOSE + Gets the bounding box containing the selection. + USAGE + herr_t H5S_get_select_bounds(space, start, end) + H5S_t *space; IN: Dataspace ID of selection to query + hsize_t *start; OUT: Starting coordinate of bounding box + hsize_t *end; OUT: Opposite coordinate of bounding box + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Retrieves the bounding box containing the current selection and places + it into the user's buffers. The start and end buffers must be large + enough to hold the dataspace rank number of coordinates. The bounding box + exactly contains the selection, ie. if a 2-D element selection is currently + defined with the following points: (4,5), (6,8) (10,7), the bounding box + with be (4, 5), (10, 8). Calling this function on a "none" selection + returns fail. + The bounding box calculations _does_ include the current offset of the + selection within the dataspace extent. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) +{ + herr_t ret_value; /* return value */ + + FUNC_ENTER_NOAPI(H5S_get_select_bounds, FAIL); + + /* Check args */ + assert(space); + assert(start); + assert(end); + + ret_value = (*space->select.bounds)(space,start,end); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_get_select_bounds() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_select_iter_init PURPOSE Initializes iteration information for a selection. @@ -1578,6 +1703,12 @@ H5S_select_read(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist, curr_mem_seq=0; } /* end if */ +#ifdef QAK +HDfprintf(stderr,"%s: curr_file_seq=%Zu, file_nseq=%Zu\n",FUNC,curr_file_seq,file_nseq); +HDfprintf(stderr,"%s: curr_mem_seq=%Zu, mem_nseq=%Zu\n",FUNC,curr_mem_seq,mem_nseq); +HDfprintf(stderr,"%s: file_off[%Zu]=%Hu, file_len[%Zu]=%Zu\n",FUNC,curr_file_seq,file_off[curr_file_seq],curr_file_seq,file_len[curr_file_seq]); +HDfprintf(stderr,"%s: mem_off[%Zu]=%Hu, mem_len[%Zu]=%Zu\n",FUNC,curr_mem_seq,mem_off[curr_mem_seq],curr_mem_seq,mem_len[curr_mem_seq]); +#endif /* QAK */ /* Read file sequences into current memory sequence */ if ((tmp_file_len=H5F_seq_readvv(f, dxpl_id, layout, dc_plist, store, file_nseq, &curr_file_seq, file_len, file_off, @@ -1654,6 +1785,15 @@ H5S_select_write(H5F_t *f, H5O_layout_t *layout, H5P_genplist_t *dc_plist, herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5S_select_write, FAIL); +#ifdef QAK +{ + int mpi_rank; + double time; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + time = MPI_Wtime(); + HDfprintf(stderr,"%s: rank=%d - Entering, time=%f\n",FUNC,mpi_rank,time); +} +#endif /* QAK */ /* Check args */ assert(f); @@ -1721,6 +1861,31 @@ H5S_select_write(H5F_t *f, H5O_layout_t *layout, H5P_genplist_t *dc_plist, curr_mem_seq=0; } /* end if */ +#ifdef QAK +{ + int mpi_rank; + double time; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + time = MPI_Wtime(); + HDfprintf(stderr,"%s: rank=%d - time=%f\n",FUNC,mpi_rank,time); + HDfprintf(stderr,"%s: rank=%d - curr_file_seq=%Zu, file_nseq=%Zu\n",FUNC,mpi_rank,curr_file_seq,file_nseq); + HDfprintf(stderr,"%s: rank=%d - curr_mem_seq=%Zu, mem_nseq=%Zu\n",FUNC,mpi_rank,curr_mem_seq,mem_nseq); + HDfprintf(stderr,"%s: rank=%d - file_off[%Zu]=%Hu, file_len[%Zu]=%Zu\n",FUNC,mpi_rank,curr_file_seq,file_off[curr_file_seq],curr_file_seq,file_len[curr_file_seq]); + HDfprintf(stderr,"%s: rank=%d - mem_off[%Zu]=%Hu, mem_len[%Zu]=%Zu\n",FUNC,mpi_rank,curr_mem_seq,mem_off[curr_mem_seq],curr_mem_seq,mem_len[curr_mem_seq]); +} +#endif /* QAK */ +#ifdef QAK +{ + unsigned u; + +HDfprintf(stderr,"%s: curr_file_seq=%Zu, file_nseq=%Zu\n",FUNC,curr_file_seq,file_nseq); +HDfprintf(stderr,"%s: curr_mem_seq=%Zu, mem_nseq=%Zu\n",FUNC,curr_mem_seq,mem_nseq); +for(u=curr_file_seq; u<file_nseq; u++) + HDfprintf(stderr,"%s: file_off[%u]=%Hu, file_len[%u]=%Zu\n",FUNC,u,file_off[u],u,file_len[u]); +for(u=curr_mem_seq; u<mem_nseq; u++) + HDfprintf(stderr,"%s: mem_off[%u]=%Hu, mem_len[%u]=%Zu\n",FUNC,u,mem_off[u],u,mem_len[u]); +} +#endif /* QAK */ /* Write memory sequences into file sequences */ if ((tmp_file_len=H5F_seq_writevv(f, dxpl_id, layout, dc_plist, store, file_nseq, &curr_file_seq, file_len, file_off, @@ -1754,6 +1919,15 @@ done: H5FL_ARR_FREE(size_t,mem_len); if(mem_off!=NULL) H5FL_ARR_FREE(hsize_t,mem_off); +#ifdef QAK +{ + int mpi_rank; + double time; + MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); + time = MPI_Wtime(); + HDfprintf(stderr,"%s: rank=%d - Leaving, time=%f\n",FUNC,mpi_rank,time); +} +#endif /* QAK */ FUNC_LEAVE_NOAPI(ret_value); } /* end H5S_select_write() */ |