summaryrefslogtreecommitdiffstats
path: root/src/H5Dio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Dio.c')
-rw-r--r--src/H5Dio.c363
1 files changed, 321 insertions, 42 deletions
diff --git a/src/H5Dio.c b/src/H5Dio.c
index b494596..9b0102f 100644
--- a/src/H5Dio.c
+++ b/src/H5Dio.c
@@ -77,6 +77,12 @@ static herr_t H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts,
const H5T_t *mem_type, const H5S_t *mem_space,
const H5S_t *file_space, H5T_path_t *tpath,
hid_t src_id, hid_t dst_id, const void *buf);
+static herr_t H5D_compound_opt_read(hsize_t nelmts, const H5S_t *mem_space,
+ H5S_sel_iter_t *iter, const H5D_dxpl_cache_t *dxpl_cache,
+ hid_t src_id, hid_t dst_id, H5T_subset_t subset, void *data_buf,
+ void *user_buf/*out*/);
+static herr_t H5D_compound_opt_write(hsize_t nelmts, hid_t src_id, hid_t dst_id,
+ void *data_buf);
#ifdef H5_HAVE_PARALLEL
static herr_t H5D_ioinfo_term(H5D_io_info_t *io_info);
@@ -116,6 +122,13 @@ H5FL_BLK_DEFINE(type_conv);
/* Declare a free list to manage the H5D_chunk_info_t struct */
H5FL_DEFINE_STATIC(H5D_chunk_info_t);
+/* Declare a free list to manage sequences of size_t */
+H5FL_SEQ_DEFINE_STATIC(size_t);
+
+/* Declare a free list to manage sequences of hsize_t */
+H5FL_SEQ_DEFINE_STATIC(hsize_t);
+
+
/*--------------------------------------------------------------------------
NAME
@@ -1167,6 +1180,23 @@ H5D_contig_read(H5D_io_info_t *io_info, hsize_t nelmts,
if (n!=smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
+ /* If the source and destination are compound types and subset of each other
+ * and no conversion is needed, copy the data directly into user's buffer and
+ * bypass the rest of steps. This optimization is for Chicago company */
+ if(H5T_SUBSET_SRC==H5T_path_compound_subset(tpath)) {
+ if(H5D_compound_opt_read(smine_nelmts, mem_space, &mem_iter, dxpl_cache,
+ src_id, dst_id, H5T_SUBSET_SRC, tconv_buf, buf /*out*/)<0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+
+ continue;
+ } else if(H5T_SUBSET_DST==H5T_path_compound_subset(tpath)) {
+ if(H5D_compound_opt_read(smine_nelmts, mem_space, &mem_iter, dxpl_cache,
+ src_id, dst_id, H5T_SUBSET_DST, tconv_buf, buf /*out*/)<0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+
+ continue;
+ }
+
if (H5T_BKG_YES==need_bkg) {
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
@@ -1421,33 +1451,44 @@ H5D_contig_write(H5D_io_info_t *io_info, hsize_t nelmts,
if (n!=smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed")
- if (H5T_BKG_YES==need_bkg) {
+ /* If the source and destination are compound types and the destination is
+ * is a subset of the source and no conversion is needed, copy the data
+ * directly into user's buffer and bypass the rest of steps. If the source
+ * is a subset of the destination, the optimization is done in conversion
+ * function H5T_conv_struct_opt to protect the background data. This
+ * optimization is for Chicago company */
+ if(H5T_SUBSET_DST==H5T_path_compound_subset(tpath)) {
+ if(H5D_compound_opt_write(smine_nelmts, src_id, dst_id, tconv_buf)<0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+ } else {
+ if (H5T_BKG_YES==need_bkg) {
#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
+ H5_timer_begin(&timer);
#endif
- n = H5D_select_fgath(io_info,
- file_space, &bkg_iter, smine_nelmts,
- bkg_buf/*out*/);
+ n = H5D_select_fgath(io_info,
+ file_space, &bkg_iter, smine_nelmts,
+ bkg_buf/*out*/);
#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].bkg_timer), &timer);
- io_info->stats->stats[0].bkg_nbytes += n * dst_type_size;
- io_info->stats->stats[0].bkg_ncalls++;
+ H5_timer_end(&(io_info->stats->stats[0].bkg_timer), &timer);
+ io_info->stats->stats[0].bkg_nbytes += n * dst_type_size;
+ io_info->stats->stats[0].bkg_ncalls++;
#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed")
- } /* end if */
+ if (n!=smine_nelmts)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed")
+ } /* end if */
- /*
- * Perform datatype conversion.
- */
- if(H5T_convert(tpath, src_id, dst_id, smine_nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+ /*
+ * Perform datatype conversion.
+ */
+ if(H5T_convert(tpath, src_id, dst_id, smine_nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, io_info->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
- /* Do the data transform after the type conversion (since we're using dataset->shared->type). */
- if(!H5Z_xform_noop(dxpl_cache->data_xform_prop))
- if( H5Z_xform_eval(dxpl_cache->data_xform_prop, tconv_buf, smine_nelmts, dataset->shared->type) < 0)
+ /* Do the data transform after the type conversion (since we're using dataset->shared->type). */
+ if(!H5Z_xform_noop(dxpl_cache->data_xform_prop))
+ if( H5Z_xform_eval(dxpl_cache->data_xform_prop, tconv_buf, smine_nelmts, dataset->shared->type) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
+ }
/*
* Scatter the data out to the file.
@@ -1455,9 +1496,8 @@ H5D_contig_write(H5D_io_info_t *io_info, hsize_t nelmts,
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
#endif
- status = H5D_select_fscat(io_info,
- file_space, &file_iter, smine_nelmts,
- tconv_buf);
+ status = H5D_select_fscat(io_info, file_space, &file_iter, smine_nelmts,
+ tconv_buf);
#ifdef H5S_DEBUG
H5_timer_end(&(io_info->stats->stats[0].scat_timer), &timer);
io_info->stats->stats[0].scat_nbytes += smine_nelmts * dst_type_size;
@@ -1723,6 +1763,23 @@ H5D_chunk_read(H5D_io_info_t *io_info, hsize_t nelmts,
if(n != smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
+ /* If the source and destination are compound types and subset of each other
+ * and no conversion is needed, copy the data directly into user's buffer and
+ * bypass the rest of steps. This optimization is for Chicago company */
+ if(H5T_SUBSET_SRC==H5T_path_compound_subset(tpath)) {
+ if(H5D_compound_opt_read(smine_nelmts, chunk_info->mspace, &mem_iter, dxpl_cache,
+ src_id, dst_id, H5T_SUBSET_SRC, tconv_buf, buf /*out*/)<0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+
+ continue;
+ } else if(H5T_SUBSET_DST==H5T_path_compound_subset(tpath)) {
+ if(H5D_compound_opt_read(smine_nelmts, chunk_info->mspace, &mem_iter, dxpl_cache,
+ src_id, dst_id, H5T_SUBSET_DST, tconv_buf, buf /*out*/)<0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+
+ continue;
+ }
+
if(H5T_BKG_YES == need_bkg) {
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
@@ -2041,33 +2098,43 @@ H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts,
if (n!=smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
- if (H5T_BKG_YES==need_bkg) {
+ /* If the source and destination are compound types and the destination is
+ * is a subset of the source and no conversion is needed, copy the data
+ * directly into user's buffer and bypass the rest of steps. If the source
+ * is a subset of the destination, the optimization is done in conversion
+ * function H5T_conv_struct_opt to protect the background data. This
+ * optimization is for Chicago company */
+ if(H5T_SUBSET_DST==H5T_path_compound_subset(tpath)) {
+ if(H5D_compound_opt_write(smine_nelmts, src_id, dst_id, tconv_buf)<0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+ } else {
+ if (H5T_BKG_YES==need_bkg) {
#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
+ H5_timer_begin(&timer);
#endif
- n = H5D_select_fgath(io_info,
- chunk_info->fspace, &bkg_iter, smine_nelmts,
- bkg_buf/*out*/);
+ n = H5D_select_fgath(io_info, chunk_info->fspace, &bkg_iter, smine_nelmts,
+ bkg_buf/*out*/);
#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].bkg_timer), &timer);
- io_info->stats->stats[0].bkg_nbytes += n * dst_type_size;
- io_info->stats->stats[0].bkg_ncalls++;
+ H5_timer_end(&(io_info->stats->stats[0].bkg_timer), &timer);
+ io_info->stats->stats[0].bkg_nbytes += n * dst_type_size;
+ io_info->stats->stats[0].bkg_ncalls++;
#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed")
- } /* end if */
+ if (n!=smine_nelmts)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed")
+ } /* end if */
- /*
- * Perform datatype conversion.
- */
- if(H5T_convert(tpath, src_id, dst_id, smine_nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+ /*
+ * Perform datatype conversion.
+ */
+ if(H5T_convert(tpath, src_id, dst_id, smine_nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, io_info->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
- /* Do the data transform after the type conversion (since we're using dataset->shared->type) */
- if(!H5Z_xform_noop(dxpl_cache->data_xform_prop))
- if( H5Z_xform_eval(dxpl_cache->data_xform_prop, tconv_buf, smine_nelmts, dataset->shared->type) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
+ /* Do the data transform after the type conversion (since we're using dataset->shared->type) */
+ if(!H5Z_xform_noop(dxpl_cache->data_xform_prop))
+ if( H5Z_xform_eval(dxpl_cache->data_xform_prop, tconv_buf, smine_nelmts, dataset->shared->type) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
+ }
/*
* Scatter the data out to the file.
@@ -2138,6 +2205,218 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5D_compound_opt_read
+ *
+ * Purpose: A shortcut optimization for the Chicago company for
+ * a special optimization case when the source and
+ * destination members are a subset of each other, and
+ * the order is the same, and no conversion is needed.
+ * For example:
+ * struct source { struct destination {
+ * TYPE1 A; --> TYPE1 A;
+ * TYPE2 B; --> TYPE2 B;
+ * TYPE3 C; --> TYPE3 C;
+ * }; TYPE4 D;
+ * TYPE5 E;
+ * };
+ * or
+ * struct destination { struct source {
+ * TYPE1 A; --> TYPE1 A;
+ * TYPE2 B; --> TYPE2 B;
+ * TYPE3 C; --> TYPE3 C;
+ * }; TYPE4 D;
+ * TYPE5 E;
+ * };
+ * The optimization is simply moving data to the appropriate
+ * places in the buffer.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * 11 June 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_compound_opt_read(hsize_t nelmts, const H5S_t *space,
+ H5S_sel_iter_t *iter, const H5D_dxpl_cache_t *dxpl_cache,
+ hid_t src_id, hid_t dst_id, H5T_subset_t subset,
+ void *data_buf, void *user_buf/*out*/)
+{
+ uint8_t *dbuf = (uint8_t *)data_buf; /*cast for pointer arithmetic */
+ uint8_t *ubuf = (uint8_t *)user_buf; /*cast for pointer arithmetic */
+ uint8_t *xdbuf;
+ uint8_t *xubuf;
+
+ hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
+ hsize_t *off=NULL; /* Pointer to sequence offsets */
+ size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
+ size_t *len=NULL; /* Pointer to sequence lengths */
+ size_t nseq; /* Number of sequences generated */
+ size_t curr_off; /* offset of bytes left to process in sequence */
+ size_t curr_seq; /* Current sequence being processed */
+ size_t curr_len; /* Length of bytes left to process in sequence */
+ size_t curr_nelmts; /* number of elements to process in sequence */
+ size_t i;
+
+ H5T_t *src, *dst;
+ size_t src_stride, dst_stride, type_size;
+ size_t elmtno; /*element counter */
+
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_compound_opt_read)
+
+ /* Check args */
+ assert (data_buf);
+ assert (user_buf);
+ assert (space);
+ assert (iter);
+ assert (nelmts>0);
+
+ /* Allocate the vector I/O arrays */
+ if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
+ if((len = H5FL_SEQ_MALLOC(size_t,dxpl_cache->vec_size))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
+ if((off = H5FL_SEQ_MALLOC(hsize_t,dxpl_cache->vec_size))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
+ } /* end if */
+ else {
+ len=_len;
+ off=_off;
+ } /* end else */
+
+ if (NULL == (src = H5I_object(src_id)) || NULL == (dst = H5I_object(dst_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+
+ src_stride = H5T_get_size(src);
+ dst_stride = H5T_get_size(dst);
+
+ if(H5T_SUBSET_SRC == subset)
+ type_size = src_stride;
+ else if(H5T_SUBSET_DST == subset)
+ type_size = dst_stride;
+
+ xdbuf = dbuf;
+
+ /* Loop until all elements are written */
+ while(nelmts>0) {
+ /* Get list of sequences for selection to write */
+ if(H5S_SELECT_GET_SEQ_LIST(space,0,iter,dxpl_cache->vec_size,nelmts,&nseq,&elmtno,off,len)<0)
+ HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed");
+
+ /* Loop, while sequences left to process */
+ for(curr_seq=0; curr_seq<nseq; curr_seq++) {
+ /* Get the number of bytes and offset in sequence */
+ curr_len=len[curr_seq];
+ curr_off=off[curr_seq];
+
+ /* Decide the number of elements and position in the buffer. */
+ curr_nelmts = curr_len/dst_stride;
+ xubuf = ubuf + curr_off;
+
+ /* Copy the data into the right place. */
+ for(i=0; i<curr_nelmts; i++) {
+ HDmemmove(xubuf, xdbuf, type_size);
+
+ /* Update pointers */
+ xdbuf += src_stride;
+ xubuf += dst_stride;
+ }
+
+ } /* end for */
+
+ /* Decrement number of elements left to process */
+ nelmts -= elmtno;
+ } /* end while */
+
+done:
+ if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
+ if(len!=NULL)
+ H5FL_SEQ_FREE(size_t,len);
+ if(off!=NULL)
+ H5FL_SEQ_FREE(hsize_t,off);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_compound_opt_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_compound_opt_write
+ *
+ * Purpose: A shortcut optimization for the Chicago company for
+ * a special optimization case when the source and
+ * destination members are a subset of each other, and
+ * the order is the same, and no conversion is needed.
+ * For example:
+ * struct source { struct destination {
+ * TYPE1 A; --> TYPE1 A;
+ * TYPE2 B; --> TYPE2 B;
+ * TYPE3 C; --> TYPE3 C;
+ * }; TYPE4 D;
+ * TYPE5 E;
+ * };
+ * or
+ * struct destination { struct source {
+ * TYPE1 A; --> TYPE1 A;
+ * TYPE2 B; --> TYPE2 B;
+ * TYPE3 C; --> TYPE3 C;
+ * }; TYPE4 D;
+ * TYPE5 E;
+ * };
+ * The optimization is simply moving data to the appropriate
+ * places in the buffer.
+ *
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * 11 June 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_compound_opt_write(hsize_t nelmts, hid_t src_id, hid_t dst_id, void *data_buf)
+{
+ uint8_t *dbuf = (uint8_t *)data_buf; /*cast for pointer arithmetic */
+ uint8_t *xsbuf, *xdbuf;
+ size_t i;
+ H5T_t *src, *dst;
+ size_t src_stride, dst_stride;
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_compound_opt_write)
+
+ /* Check args */
+ assert (data_buf);
+ assert (nelmts>0);
+
+ if (NULL == (src = H5I_object(src_id)) || NULL == (dst = H5I_object(dst_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+
+ src_stride = H5T_get_size(src);
+ dst_stride = H5T_get_size(dst);
+
+ xsbuf = dbuf;
+ xdbuf = dbuf;
+
+ /* Loop until all elements are written */
+ for(i=0; i<nelmts; i++) {
+ HDmemmove(xdbuf, xsbuf, dst_stride);
+
+ /* Update pointers */
+ xsbuf += src_stride;
+ xdbuf += dst_stride;
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_compound_opt_write() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D_create_chunk_map
*
* Purpose: Creates the mapping between elements selected in each chunk