diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c index 6cd8a788d2e..bd9ebdb4b28 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -1117,6 +1117,26 @@ H5D__chunk_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo) if (H5D__chunk_may_use_select_io(io_info, dinfo) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if selection I/O is possible") + /* Calculate type conversion buffer size if necessary */ + if (!(dinfo->type_info.is_xform_noop && dinfo->type_info.is_conv_noop)) { + H5SL_node_t *chunk_node; /* Current node in chunk skip list */ + + /* Iterate through nodes in chunk skip list */ + chunk_node = H5D_CHUNK_GET_FIRST_NODE(dinfo); + while (chunk_node) { + H5D_piece_info_t *piece_info; /* Chunk information */ + + /* Get the actual chunk information from the skip list node */ + piece_info = H5D_CHUNK_GET_NODE_INFO(dinfo, chunk_node); + + /* Handle type conversion buffer */ + H5D_INIT_PIECE_TCONV(io_info, dinfo, piece_info) + + /* Advance to next chunk in list */ + chunk_node = H5D_CHUNK_GET_NEXT_NODE(dinfo, chunk_node); + } + } + done: if (file_space_normalized == TRUE) if (H5S_hyper_denormalize_offset(dinfo->file_space, old_offset) < 0) @@ -1568,6 +1588,10 @@ H5D__create_piece_map_single(H5D_dset_io_info_t *di, H5D_io_info_t *io_info) /* Indicate that the chunk's memory dataspace is shared */ piece_info->mspace_shared = TRUE; + /* Initialize in-place type conversion info. Start with it disabled. */ + piece_info->in_place_tconv = FALSE; + piece_info->buf_off = 0; + /* make connection to related dset info from this piece_info */ piece_info->dset_info = di; @@ -1697,6 +1721,10 @@ H5D__create_piece_file_map_all(H5D_dset_io_info_t *di, H5D_io_info_t *io_info) /* make connection to related dset info from this piece_info */ new_piece_info->dset_info = di; + /* Initialize in-place type conversion info. Start with it disabled. */ + new_piece_info->in_place_tconv = FALSE; + new_piece_info->buf_off = 0; + /* Insert the new chunk into the skip list */ if (H5SL_insert(fm->dset_sel_pieces, new_piece_info, &new_piece_info->index) < 0) { H5D__free_piece_info(new_piece_info, NULL, NULL); @@ -1893,6 +1921,10 @@ H5D__create_piece_file_map_hyper(H5D_dset_io_info_t *dinfo, H5D_io_info_t *io_in /* make connection to related dset info from this piece_info */ new_piece_info->dset_info = dinfo; + /* Initialize in-place type conversion info. Start with it disabled. */ + new_piece_info->in_place_tconv = FALSE; + new_piece_info->buf_off = 0; + /* Add piece to global piece_count */ io_info->piece_count++; @@ -2268,6 +2300,10 @@ H5D__piece_file_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, H5MM_memcpy(piece_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims); piece_info->scaled[fm->f_ndims] = 0; + /* Initialize in-place type conversion info. Start with it disabled. */ + piece_info->in_place_tconv = FALSE; + piece_info->buf_off = 0; + /* Make connection to related dset info from this piece_info */ piece_info->dset_info = dinfo; @@ -2562,7 +2598,7 @@ H5D__chunk_may_use_select_io(H5D_io_info_t *io_info, const H5D_dset_io_info_t *d /* Don't use selection I/O if there are filters on the dataset (for now) */ if (dataset->shared->dcpl_cache.pline.nused > 0) { io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; - io_info->no_selection_io_cause |= H5D_DATASET_FILTER; + io_info->no_selection_io_cause |= H5D_SEL_IO_DATASET_FILTER; } else { hbool_t page_buf_enabled; @@ -2573,7 +2609,7 @@ H5D__chunk_may_use_select_io(H5D_io_info_t *io_info, const H5D_dset_io_info_t *d if (page_buf_enabled) { /* Note that page buffer is disabled in parallel */ io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; - io_info->no_selection_io_cause |= H5D_PAGE_BUFFER; + io_info->no_selection_io_cause |= H5D_SEL_IO_PAGE_BUFFER; } else { /* Check if chunks in this dataset may be cached, if so don't use @@ -2591,7 +2627,7 @@ H5D__chunk_may_use_select_io(H5D_io_info_t *io_info, const H5D_dset_io_info_t *d H5_CHECK_OVERFLOW(dataset->shared->layout.u.chunk.size, uint32_t, size_t); if ((size_t)dataset->shared->layout.u.chunk.size <= dataset->shared->cache.chunk.nbytes_max) { io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; - io_info->no_selection_io_cause |= H5D_CHUNK_CACHE; + io_info->no_selection_io_cause |= H5D_SEL_IO_CHUNK_CACHE; } #ifdef H5_HAVE_PARALLEL } /* end else */ diff --git a/src/H5Dcompact.c b/src/H5Dcompact.c index a454c72a4e9..5f45da45ee7 100644 --- a/src/H5Dcompact.c +++ b/src/H5Dcompact.c @@ -253,7 +253,7 @@ H5D__compact_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo) /* Disable selection I/O */ io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; - io_info->no_selection_io_cause |= H5D_NOT_CONTIGUOUS_OR_CHUNKED_DATASET; + io_info->no_selection_io_cause |= H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET; FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5D__compact_io_init() */ diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c index b320191d8bc..01db1e4f259 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -665,6 +665,14 @@ H5D__contig_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo) /* get dset file address for piece */ new_piece_info->faddr = dinfo->dset->shared->layout.storage.u.contig.addr; + /* Initialize in-place type conversion info. Start with it disabled. */ + new_piece_info->in_place_tconv = FALSE; + new_piece_info->buf_off = 0; + + /* Calculate type conversion buffer size and check for in-place conversion if necessary */ + if (!(dinfo->type_info.is_xform_noop && dinfo->type_info.is_conv_noop)) + H5D_INIT_PIECE_TCONV(io_info, dinfo, new_piece_info) + /* Save piece to dataset info struct so it is freed at the end of the * operation */ dinfo->layout_io_info.contig_piece_info = new_piece_info; @@ -760,11 +768,14 @@ H5D__contig_may_use_select_io(H5D_io_info_t *io_info, const H5D_dset_io_info_t * /* Don't use selection I/O if it's globally disabled, if it's not a contiguous dataset, or if the sieve * buffer exists (write) or is dirty (read) */ - if (dset_info->layout_ops.readvv != H5D__contig_readvv || - (op_type == H5D_IO_OP_READ && dataset->shared->cache.contig.sieve_dirty) || - (op_type == H5D_IO_OP_WRITE && dataset->shared->cache.contig.sieve_buf)) { + if (dset_info->layout_ops.readvv != H5D__contig_readvv) { + io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; + io_info->no_selection_io_cause |= H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET; + } + else if ((op_type == H5D_IO_OP_READ && dataset->shared->cache.contig.sieve_dirty) || + (op_type == H5D_IO_OP_WRITE && dataset->shared->cache.contig.sieve_buf)) { io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; - io_info->no_selection_io_cause |= H5D_CONTIGUOUS_SIEVE_BUFFER; + io_info->no_selection_io_cause |= H5D_SEL_IO_CONTIGUOUS_SIEVE_BUFFER; } else { hbool_t page_buf_enabled; @@ -776,7 +787,7 @@ H5D__contig_may_use_select_io(H5D_io_info_t *io_info, const H5D_dset_io_info_t * HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if page buffer is enabled") if (page_buf_enabled) { io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; - io_info->no_selection_io_cause |= H5D_PAGE_BUFFER; + io_info->no_selection_io_cause |= H5D_SEL_IO_PAGE_BUFFER; } } /* end else */ diff --git a/src/H5Defl.c b/src/H5Defl.c index 9ba03a94760..7509df74a56 100644 --- a/src/H5Defl.c +++ b/src/H5Defl.c @@ -214,7 +214,7 @@ H5D__efl_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo) /* Disable selection I/O */ io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; - io_info->no_selection_io_cause |= H5D_NOT_CONTIGUOUS_OR_CHUNKED_DATASET; + io_info->no_selection_io_cause |= H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET; FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5D__efl_io_init() */ diff --git a/src/H5Dio.c b/src/H5Dio.c index f176742726d..7792fc84e5e 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -43,7 +43,8 @@ /********************/ /* Setup/teardown routines */ -static herr_t H5D__ioinfo_init(size_t count, H5D_dset_io_info_t *dset_info, H5D_io_info_t *io_info); +static herr_t H5D__ioinfo_init(size_t count, H5D_io_op_type_t op_type, H5D_dset_io_info_t *dset_info, + H5D_io_info_t *io_info); static herr_t H5D__dset_ioinfo_init(H5D_t *dset, H5D_dset_io_info_t *dset_info, H5D_storage_t *store); static herr_t H5D__typeinfo_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, hid_t mem_type_id); #ifdef H5_HAVE_PARALLEL @@ -107,9 +108,8 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info) FUNC_ENTER_NOAPI(FAIL) /* Init io_info */ - if (H5D__ioinfo_init(count, dset_info, &io_info) < 0) + if (H5D__ioinfo_init(count, H5D_IO_OP_READ, dset_info, &io_info) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize I/O info") - io_info.op_type = H5D_IO_OP_READ; /* Allocate store buffer if necessary */ if (count > 1) @@ -360,7 +360,7 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info) if (NULL == (io_info.rbufs = H5MM_malloc(io_info.piece_count * sizeof(void *)))) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for read buffer list") - if (io_info.tconv_buf) + if (io_info.max_tconv_type_size > 0) if (NULL == (io_info.sel_pieces = H5MM_malloc(io_info.piece_count * sizeof(io_info.sel_pieces[0])))) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, @@ -388,7 +388,7 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info) * (if using selection I/O and either multi dataset or type conversion) */ if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info)) { /* Check for type conversion */ - if (io_info.tconv_buf) { + if (io_info.max_tconv_type_size > 0) { /* Type conversion pathway */ if (H5D__scatgath_read_select(&io_info) < 0) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "type conversion selection read failed") @@ -505,9 +505,8 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info) FUNC_ENTER_NOAPI(FAIL) /* Init io_info */ - if (H5D__ioinfo_init(count, dset_info, &io_info) < 0) + if (H5D__ioinfo_init(count, H5D_IO_OP_WRITE, dset_info, &io_info) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize I/O info") - io_info.op_type = H5D_IO_OP_WRITE; /* Allocate store buffer if necessary */ if (count > 1) @@ -765,7 +764,7 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info) if (NULL == (io_info.wbufs = H5MM_malloc(io_info.piece_count * sizeof(const void *)))) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for write buffer list") - if (io_info.tconv_buf) + if (io_info.max_tconv_type_size > 0) if (NULL == (io_info.sel_pieces = H5MM_malloc(io_info.piece_count * sizeof(io_info.sel_pieces[0])))) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, @@ -791,7 +790,7 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info) * (if using selection I/O and either multi dataset or type conversion) */ if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info)) { /* Check for type conversion */ - if (io_info.tconv_buf) { + if (io_info.max_tconv_type_size > 0) { /* Type conversion pathway */ if (H5D__scatgath_write_select(&io_info) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "type conversion selection write failed") @@ -894,7 +893,8 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info) *------------------------------------------------------------------------- */ static herr_t -H5D__ioinfo_init(size_t count, H5D_dset_io_info_t *dset_info, H5D_io_info_t *io_info) +H5D__ioinfo_init(size_t count, H5D_io_op_type_t op_type, H5D_dset_io_info_t *dset_info, + H5D_io_info_t *io_info) { H5D_selection_io_mode_t selection_io_mode; @@ -910,8 +910,9 @@ H5D__ioinfo_init(size_t count, H5D_dset_io_info_t *dset_info, H5D_io_info_t *io_ HDmemset(io_info, 0, sizeof(*io_info)); /* Set up simple fields */ - io_info->f_sh = count > 0 ? H5F_SHARED(dset_info[0].dset->oloc.file) : NULL; - io_info->count = count; + io_info->op_type = op_type; + io_info->f_sh = count > 0 ? H5F_SHARED(dset_info[0].dset->oloc.file) : NULL; + io_info->count = count; /* Start without multi-dataset I/O ops. If we're not using the collective * I/O path then we will call the single dataset callbacks in a loop. */ @@ -927,7 +928,7 @@ H5D__ioinfo_init(size_t count, H5D_dset_io_info_t *dset_info, H5D_io_info_t *io_ /* Record no selection I/O cause if it was disabled by the API */ if (selection_io_mode == H5D_SELECTION_IO_MODE_OFF) - io_info->no_selection_io_cause = H5D_DISABLE_BY_API; + io_info->no_selection_io_cause = H5D_SEL_IO_DISABLE_BY_API; #ifdef H5_HAVE_PARALLEL @@ -936,6 +937,9 @@ H5D__ioinfo_init(size_t count, H5D_dset_io_info_t *dset_info, H5D_io_info_t *io_ io_info->using_mpi_vfd = H5F_HAS_FEATURE(dset_info[0].dset->oloc.file, H5FD_FEAT_HAS_MPI); #endif /* H5_HAVE_PARALLEL */ + /* Check if we could potentially use in-place type conversion. For now just check if it's a read op */ + io_info->may_use_in_place_tconv = (op_type == H5D_IO_OP_READ); + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5D__ioinfo_init() */ @@ -1144,30 +1148,22 @@ H5D__typeinfo_init_phase2(H5D_io_info_t *io_info) size_t max_temp_buf; /* Maximum temporary buffer size */ size_t i; /* Local index variable */ - /* Collective I/O, conversion buffer must be large enough for entire I/O (for now). - * Stick with individual background buffers */ + /* Collective I/O, conversion buffer must be large enough for entire I/O (for now) */ - /* Calculate size of buffers */ + /* Calculate size of background buffer (tconv buf size was calculated in layout io_init callbacks) + */ for (i = 0; i < io_info->count; i++) { H5D_type_info_t *type_info = &io_info->dsets_info[i].type_info; - /* Check if type conversion buffer is needed for this dataset */ - if (!type_info->is_conv_noop || !type_info->is_xform_noop) { - /* Add size of this dataset's type conversion buffer to the global type conversion buffer - * size */ - io_info->tconv_buf_size += io_info->dsets_info[i].nelmts * - MAX(type_info->src_type_size, type_info->dst_type_size); - - /* Check for background buffer */ - if (type_info->need_bkg) { - /* Add size of this dataset's background buffer to the global background buffer size - */ - io_info->bkg_buf_size += io_info->dsets_info[i].nelmts * type_info->dst_type_size; - - /* Check if we need to fill the background buffer with the destination contents */ - if (type_info->need_bkg == H5T_BKG_YES) - io_info->must_fill_bkg = TRUE; - } + /* Check for background buffer */ + if (type_info->need_bkg) { + /* Add size of this dataset's background buffer to the global background buffer size + */ + io_info->bkg_buf_size += io_info->dsets_info[i].nelmts * type_info->dst_type_size; + + /* Check if we need to fill the background buffer with the destination contents */ + if (type_info->need_bkg == H5T_BKG_YES) + io_info->must_fill_bkg = TRUE; } } @@ -1175,11 +1171,17 @@ H5D__typeinfo_init_phase2(H5D_io_info_t *io_info) if (H5CX_get_max_temp_buf(&max_temp_buf) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve max. temp. buf size") - /* Check if the needed type conversion size is too big */ - HDassert(io_info->bkg_buf_size <= io_info->tconv_buf_size); + /* Check if the needed type conversion or background buffer size is too big */ if (io_info->tconv_buf_size > max_temp_buf) { io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; - io_info->no_selection_io_cause |= H5D_TCONV_BUF_TOO_SMALL; + io_info->no_selection_io_cause |= H5D_SEL_IO_TCONV_BUF_TOO_SMALL; + io_info->tconv_buf_size = 0; + io_info->bkg_buf_size = 0; + io_info->must_fill_bkg = FALSE; + } + if (io_info->bkg_buf_size > max_temp_buf) { + io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; + io_info->no_selection_io_cause |= H5D_SEL_IO_BKG_BUF_TOO_SMALL; io_info->tconv_buf_size = 0; io_info->bkg_buf_size = 0; io_info->must_fill_bkg = FALSE; @@ -1334,7 +1336,7 @@ H5D__ioinfo_adjust(H5D_io_info_t *io_info) io_info->use_select_io = H5D_SELECTION_IO_MODE_ON; else { io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; - io_info->no_selection_io_cause |= H5D_NO_VECTOR_OR_SELECTION_IO_CB; + io_info->no_selection_io_cause |= H5D_SEL_IO_DEFAULT_OFF; } } @@ -1423,7 +1425,7 @@ H5D__typeinfo_init_phase3(H5D_io_info_t *io_info) * assumes the tconv buf is large enough to hold all data in the I/O, and we don't want * to impose this when there's no benefit */ io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; - io_info->no_selection_io_cause |= H5D_DATATYPE_CONVERSION; + io_info->no_selection_io_cause |= H5D_SEL_IO_DATATYPE_CONVERSION; /* Get max buffer size from API context */ if (H5CX_get_max_temp_buf(&max_temp_buf) < 0) diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c index 7ddba7c3e6b..96bbcf77850 100644 --- a/src/H5Dmpio.c +++ b/src/H5Dmpio.c @@ -739,10 +739,8 @@ H5D__mpio_opt_possible(H5D_io_info_t *io_info) if (io_info->use_select_io == H5D_SELECTION_IO_MODE_DEFAULT) { /* If the only reason(s) we've disabled collective are type conversions and/or transforms, enable * selection I/O and re-enable collective I/O since it's supported by selection I/O */ - if (global_cause[0] && - !(global_cause[0] & - ~((unsigned)H5D_MPIO_DATATYPE_CONVERSION | (unsigned)H5D_MPIO_DATA_TRANSFORMS)) && - (io_info->use_select_io == H5D_SELECTION_IO_MODE_DEFAULT)) { + if (global_cause[0] && !(global_cause[0] & ~((unsigned)H5D_MPIO_DATATYPE_CONVERSION | + (unsigned)H5D_MPIO_DATA_TRANSFORMS))) { HDassert(!(local_cause[0] & ~((unsigned)H5D_MPIO_DATATYPE_CONVERSION | (unsigned)H5D_MPIO_DATA_TRANSFORMS))); local_cause[0] = 0; @@ -752,7 +750,7 @@ H5D__mpio_opt_possible(H5D_io_info_t *io_info) else { /* Otherwise, there's currently no benefit to selection I/O, so leave it off */ io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; - io_info->no_selection_io_cause |= H5D_NO_BENEFIT_BY_MPIO; + io_info->no_selection_io_cause |= H5D_SEL_IO_DEFAULT_OFF; } } diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index 97a4e3479d2..fb5d8e86258 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -72,7 +72,47 @@ /* Macro to determine if the layout I/O callback should perform I/O */ #define H5D_LAYOUT_CB_PERFORM_IO(IO_INFO) \ (((IO_INFO)->use_select_io == H5D_SELECTION_IO_MODE_OFF) || \ - ((IO_INFO)->count == 1 && !(IO_INFO)->tconv_buf)) + ((IO_INFO)->count == 1 && (IO_INFO)->max_tconv_type_size == 0)) + +/* Macro to check if in-place type conversion will be used for a piece and add it to the global type + * conversion size if it won't be used */ +#define H5D_INIT_PIECE_TCONV(IO_INFO, DINFO, PIECE_INFO) \ + { \ + /* Check for potential in-place conversion */ \ + if ((IO_INFO)->may_use_in_place_tconv) { \ + size_t mem_type_size = ((IO_INFO)->op_type == H5D_IO_OP_READ) \ + ? (DINFO)->type_info.dst_type_size \ + : (DINFO)->type_info.src_type_size; \ + size_t file_type_size = ((IO_INFO)->op_type == H5D_IO_OP_READ) \ + ? (DINFO)->type_info.src_type_size \ + : (DINFO)->type_info.dst_type_size; \ + \ + /* Make sure the memory type is not smaller than the file type, otherwise the memory buffer \ + * won't be big enough tp serve as the type conversion buffer */ \ + if (mem_type_size >= file_type_size) { \ + hbool_t is_contig; \ + hsize_t sel_off; \ + \ + /* Check if the space is contiguous */ \ + if (H5S_select_contig_block((PIECE_INFO)->mspace, &is_contig, &sel_off, NULL) < 0) \ + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't check if dataspace is contiguous") \ + \ + /* If the first sequence includes all the elements selected in this piece, it it contiguous \ + */ \ + if (is_contig) { \ + H5_CHECK_OVERFLOW(sel_off, hsize_t, size_t); \ + (PIECE_INFO)->in_place_tconv = TRUE; \ + (PIECE_INFO)->buf_off = (size_t)sel_off * mem_type_size; \ + } \ + } \ + } \ + \ + /* If we're not using in-place type conversion, add this piece to global type conversion buffer \ + * size. This will only be used if we must allocate a type conversion buffer for the entire I/O. */ \ + if (!(PIECE_INFO)->in_place_tconv) \ + (IO_INFO)->tconv_buf_size += (PIECE_INFO)->piece_points * MAX((DINFO)->type_info.src_type_size, \ + (DINFO)->type_info.dst_type_size); \ + } /****************************/ /* Package Private Typedefs */ @@ -212,9 +252,11 @@ typedef struct H5D_piece_info_t { hsize_t piece_points; /* Number of elements selected in piece */ hsize_t scaled[H5O_LAYOUT_NDIMS]; /* Scaled coordinates of chunk (in file dataset's dataspace) */ H5S_t *fspace; /* Dataspace describing chunk & selection in it */ - unsigned fspace_shared; /* Indicate that the file space for a chunk is shared and shouldn't be freed */ - H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */ - unsigned mspace_shared; /* Indicate that the memory space for a chunk is shared and shouldn't be freed */ + unsigned fspace_shared; /* Indicate that the file space for a chunk is shared and shouldn't be freed */ + H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */ + unsigned mspace_shared; /* Indicate that the memory space for a chunk is shared and shouldn't be freed */ + hbool_t in_place_tconv; /* Whether to perform type conversion in-place */ + size_t buf_off; /* Buffer offset for in-place type conversion */ struct H5D_dset_io_info_t *dset_info; /* Pointer to dset_info */ } H5D_piece_info_t; @@ -277,6 +319,8 @@ typedef struct H5D_io_info_t { conversion */ hbool_t must_fill_bkg; /* Whether any datasets need a background buffer filled with destination contents */ + hbool_t may_use_in_place_tconv; /* Whether datasets in this I/O could potentially use in-place type + conversion if the type sizes are compatible with it */ #ifdef H5_HAVE_PARALLEL H5D_mpio_actual_io_mode_t actual_io_mode; /* Actual type of collective or independent I/O */ #endif /* H5_HAVE_PARALLEL */ diff --git a/src/H5Dscatgath.c b/src/H5Dscatgath.c index 54d99952077..6a7ce758a2b 100644 --- a/src/H5Dscatgath.c +++ b/src/H5Dscatgath.c @@ -31,6 +31,11 @@ /* Local Macros */ /****************/ +/* Macro to determine if we're using H5D__compound_opt_read() */ +#define H5D__SCATGATH_USE_CMPD_OPT_READ(DSET_INFO, PIECE_INFO) \ + ((DSET_INFO)->type_info.cmpd_subset && H5T_SUBSET_FALSE != (DSET_INFO)->type_info.cmpd_subset->subset && \ + !(PIECE_INFO)->in_place_tconv) + /******************/ /* Local Typedefs */ /******************/ @@ -737,13 +742,15 @@ H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset herr_t H5D__scatgath_read_select(H5D_io_info_t *io_info) { - H5S_t **tmp_mem_spaces = NULL; /* Memory spaces to use for read from disk */ - H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info */ - hbool_t mem_iter_init = FALSE; /* Memory selection iteration info has been initialized */ - void **tmp_bufs = NULL; /* Buffers to use for read from disk */ - size_t buf_bytes_used = 0; /* Number of bytes used so far in conversion/background buffer */ - size_t i; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ + H5S_t **tmp_mem_spaces = NULL; /* Memory spaces to use for read from disk */ + H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info */ + hbool_t mem_iter_init = FALSE; /* Memory selection iteration info has been initialized */ + void **tmp_bufs = NULL; /* Buffers to use for read from disk */ + void *tmp_bkg_buf = NULL; /* Temporary background buffer pointer */ + size_t tconv_bytes_used = 0; /* Number of bytes used so far in conversion buffer */ + size_t bkg_bytes_used = 0; /* Number of bytes used so far in background buffer */ + size_t i; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -791,11 +798,56 @@ H5D__scatgath_read_select(H5D_io_info_t *io_info) HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "unable to create simple memory dataspace") } - /* Set buffer to point into type conversion buffer */ - tmp_bufs[i] = io_info->tconv_buf + buf_bytes_used; - buf_bytes_used += io_info->sel_pieces[i]->piece_points * - MAX(dset_info->type_info.src_type_size, dset_info->type_info.dst_type_size); - HDassert(buf_bytes_used <= io_info->tconv_buf_size); + /* Check for in-place type conversion */ + if (io_info->sel_pieces[i]->in_place_tconv) + /* Set buffer to point to read buffer + offset */ + tmp_bufs[i] = (uint8_t *)(io_info->rbufs[i]) + io_info->sel_pieces[i]->buf_off; + else { + /* Set buffer to point into type conversion buffer */ + tmp_bufs[i] = io_info->tconv_buf + tconv_bytes_used; + tconv_bytes_used += + io_info->sel_pieces[i]->piece_points * + MAX(dset_info->type_info.src_type_size, dset_info->type_info.dst_type_size); + HDassert(tconv_bytes_used <= io_info->tconv_buf_size); + } + + /* Fill background buffer here unless we will use H5D__compound_opt_read(). Must do this before + * the read so the read buffer doesn't get wiped out if we're using in-place type conversion */ + if (!H5D__SCATGATH_USE_CMPD_OPT_READ(dset_info, io_info->sel_pieces[i])) { + /* Check for background buffer */ + if (dset_info->type_info.need_bkg) { + HDassert(io_info->bkg_buf); + + /* Calculate background buffer position */ + tmp_bkg_buf = io_info->bkg_buf + bkg_bytes_used; + bkg_bytes_used += + io_info->sel_pieces[i]->piece_points * dset_info->type_info.dst_type_size; + HDassert(bkg_bytes_used <= io_info->bkg_buf_size); + + /* Gather data from read buffer to background buffer if necessary */ + if (H5T_BKG_YES == dset_info->type_info.need_bkg) { + /* Initialize memory iterator */ + HDassert(!mem_iter_init); + if (H5S_select_iter_init(mem_iter, io_info->mem_spaces[i], + dset_info->type_info.dst_type_size, 0) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to initialize memory selection information") + mem_iter_init = TRUE; /* Memory selection iteration info has been initialized */ + + if ((size_t)io_info->sel_pieces[i]->piece_points != + H5D__gather_mem(io_info->rbufs[i], mem_iter, + (size_t)io_info->sel_pieces[i]->piece_points, + tmp_bkg_buf /*out*/)) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "mem gather failed") + + /* Reset selection iterator */ + HDassert(mem_iter_init); + if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator") + mem_iter_init = FALSE; + } + } + } } } @@ -805,8 +857,8 @@ H5D__scatgath_read_select(H5D_io_info_t *io_info) io_info->file_spaces, io_info->addrs, io_info->element_sizes, tmp_bufs) < 0) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "selection read failed") - /* Reset buf_bytes_used so we can use it for the background buffer */ - buf_bytes_used = 0; + /* Reset bkg_bytes_used */ + bkg_bytes_used = 0; /* Perform type conversion and scatter data to memory buffers for datasets that need this */ for (i = 0; i < io_info->pieces_added; i++) { @@ -830,45 +882,21 @@ H5D__scatgath_read_select(H5D_io_info_t *io_info) * and no conversion is needed, copy the data directly into user's buffer and * bypass the rest of steps. */ - if (dset_info->type_info.cmpd_subset && - H5T_SUBSET_FALSE != dset_info->type_info.cmpd_subset->subset) { + if (H5D__SCATGATH_USE_CMPD_OPT_READ(dset_info, io_info->sel_pieces[i])) { if (H5D__compound_opt_read((size_t)io_info->sel_pieces[i]->piece_points, mem_iter, &dset_info->type_info, tmp_bufs[i], io_info->rbufs[i] /*out*/) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed") } else { - void *tmp_bkg_buf = NULL; - /* Check for background buffer */ if (dset_info->type_info.need_bkg) { HDassert(io_info->bkg_buf); /* Calculate background buffer position */ - tmp_bkg_buf = io_info->bkg_buf + buf_bytes_used; - buf_bytes_used += + tmp_bkg_buf = io_info->bkg_buf + bkg_bytes_used; + bkg_bytes_used += io_info->sel_pieces[i]->piece_points * dset_info->type_info.dst_type_size; - HDassert(buf_bytes_used <= io_info->bkg_buf_size); - - /* Gather data from read buffer to background buffer if necessary */ - if (H5T_BKG_YES == dset_info->type_info.need_bkg) { - if ((size_t)io_info->sel_pieces[i]->piece_points != - H5D__gather_mem(io_info->rbufs[i], mem_iter, - (size_t)io_info->sel_pieces[i]->piece_points, - tmp_bkg_buf /*out*/)) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "mem gather failed") - - /* Reset selection iterator */ - HDassert(mem_iter_init); - if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator") - mem_iter_init = FALSE; - - if (H5S_select_iter_init(mem_iter, io_info->mem_spaces[i], - dset_info->type_info.dst_type_size, 0) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to initialize memory selection information") - mem_iter_init = TRUE; /* Memory selection iteration info has been initialized */ - } + HDassert(bkg_bytes_used <= io_info->bkg_buf_size); } /* @@ -894,10 +922,11 @@ H5D__scatgath_read_select(H5D_io_info_t *io_info) HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "Error performing data transform") } - /* Scatter the data into memory */ - if (H5D__scatter_mem(tmp_bufs[i], mem_iter, (size_t)io_info->sel_pieces[i]->piece_points, - io_info->rbufs[i] /*out*/) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed") + /* Scatter the data into memory if this was not an in-place conversion */ + if (!io_info->sel_pieces[i]->in_place_tconv) + if (H5D__scatter_mem(tmp_bufs[i], mem_iter, (size_t)io_info->sel_pieces[i]->piece_points, + io_info->rbufs[i] /*out*/) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed") } /* Release selection iterator */ @@ -1019,18 +1048,33 @@ H5D__scatgath_write_select(H5D_io_info_t *io_info) HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "unable to create simple memory dataspace") spaces_added++; - /* Set buffer to point into type conversion buffer */ - tmp_write_buf = io_info->tconv_buf + tconv_bytes_used; - write_bufs[i] = (const void *)tmp_write_buf; - tconv_bytes_used += io_info->sel_pieces[i]->piece_points * - MAX(dset_info->type_info.src_type_size, dset_info->type_info.dst_type_size); - HDassert(tconv_bytes_used <= io_info->tconv_buf_size); + /* Check for in-place type conversion */ + if (io_info->sel_pieces[i]->in_place_tconv) { + H5_flexible_const_ptr_t flex_buf; + + /* Set buffer to point to write buffer + offset */ + /* Use cast to union to twiddle away const. OK because if we're doing this it means the user + * explicitly allowed us to modify this buffer via H5Pset_modfy_write_buf(). */ + flex_buf.cvp = io_info->wbufs[i]; + tmp_write_buf = (uint8_t *)flex_buf.vp + io_info->sel_pieces[i]->buf_off; + } + else { + /* Set buffer to point into type conversion buffer */ + tmp_write_buf = io_info->tconv_buf + tconv_bytes_used; + tconv_bytes_used += + io_info->sel_pieces[i]->piece_points * + MAX(dset_info->type_info.src_type_size, dset_info->type_info.dst_type_size); + HDassert(tconv_bytes_used <= io_info->tconv_buf_size); + + /* Gather data from application buffer into the datatype conversion buffer */ + if ((size_t)io_info->sel_pieces[i]->piece_points != + H5D__gather_mem(io_info->wbufs[i], mem_iter, (size_t)io_info->sel_pieces[i]->piece_points, + tmp_write_buf /*out*/)) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed") + } - /* Gather data from application buffer into the datatype conversion buffer */ - if ((size_t)io_info->sel_pieces[i]->piece_points != - H5D__gather_mem(io_info->wbufs[i], mem_iter, (size_t)io_info->sel_pieces[i]->piece_points, - tmp_write_buf /*out*/)) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed") + /* Set buffer for writing to disk (from type conversion buffer) */ + write_bufs[i] = (const void *)tmp_write_buf; /* If the source and destination are compound types and the destination is a subset of * the source and no conversion is needed, copy the data directly into the type @@ -1040,7 +1084,8 @@ H5D__scatgath_write_select(H5D_io_info_t *io_info) */ if (dset_info->type_info.cmpd_subset && H5T_SUBSET_DST == dset_info->type_info.cmpd_subset->subset && - dset_info->type_info.dst_type_size == dset_info->type_info.cmpd_subset->copy_size) { + dset_info->type_info.dst_type_size == dset_info->type_info.cmpd_subset->copy_size && + !io_info->sel_pieces[i]->in_place_tconv) { if (H5D__compound_opt_write((size_t)io_info->sel_pieces[i]->piece_points, &dset_info->type_info, tmp_write_buf) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed") diff --git a/src/H5Dvirtual.c b/src/H5Dvirtual.c index d09d543de1e..6695c02b669 100644 --- a/src/H5Dvirtual.c +++ b/src/H5Dvirtual.c @@ -2385,7 +2385,7 @@ H5D__virtual_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t H5_ATTR_UNUSED * /* Disable selection I/O */ io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; - io_info->no_selection_io_cause |= H5D_NOT_CONTIGUOUS_OR_CHUNKED_DATASET; + io_info->no_selection_io_cause |= H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET; FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5D__virtual_io_init() */ diff --git a/src/H5FDint.c b/src/H5FDint.c index e1cb5ff94da..c20b89d4994 100644 --- a/src/H5FDint.c +++ b/src/H5FDint.c @@ -471,6 +471,7 @@ H5FD_read_vector(H5FD_t *file, uint32_t count, H5FD_mem_t types[], haddr_t addrs */ extend_sizes = FALSE; extend_types = FALSE; + uint32_t no_selection_io_cause; for (i = 0; i < count; i++) { @@ -507,6 +508,11 @@ H5FD_read_vector(H5FD_t *file, uint32_t count, H5FD_mem_t types[], haddr_t addrs if ((file->cls->read)(file, type, dxpl_id, addrs[i], size, bufs[i]) < 0) HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed") } + + /* Add H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB to no selection I/O cause */ + H5CX_get_no_selection_io_cause(&no_selection_io_cause); + no_selection_io_cause |= H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB; + H5CX_set_no_selection_io_cause(no_selection_io_cause); } done: @@ -673,6 +679,7 @@ H5FD_write_vector(H5FD_t *file, uint32_t count, H5FD_mem_t types[], haddr_t addr */ extend_sizes = FALSE; extend_types = FALSE; + uint32_t no_selection_io_cause; for (i = 0; i < count; i++) { @@ -709,6 +716,11 @@ H5FD_write_vector(H5FD_t *file, uint32_t count, H5FD_mem_t types[], haddr_t addr if ((file->cls->write)(file, type, dxpl_id, addrs[i], size, bufs[i]) < 0) HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver write request failed") } + + /* Add H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB to no selection I/O cause */ + H5CX_get_no_selection_io_cause(&no_selection_io_cause); + no_selection_io_cause |= H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB; + H5CX_set_no_selection_io_cause(no_selection_io_cause); } done: @@ -997,6 +1009,14 @@ H5FD__read_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uin 0) HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read vector request failed") } + else { + uint32_t no_selection_io_cause; + + /* Add H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB to no selection I/O cause */ + H5CX_get_no_selection_io_cause(&no_selection_io_cause); + no_selection_io_cause |= H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB; + H5CX_set_no_selection_io_cause(no_selection_io_cause); + } done: /* Terminate and free iterators */ @@ -1642,6 +1662,14 @@ H5FD__write_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, ui 0) HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write vector request failed") } + else { + uint32_t no_selection_io_cause; + + /* Add H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB to no selection I/O cause */ + H5CX_get_no_selection_io_cause(&no_selection_io_cause); + no_selection_io_cause |= H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB; + H5CX_set_no_selection_io_cause(no_selection_io_cause); + } done: /* Terminate and free iterators */ diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 4d07bb90c4f..55df1529d20 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -368,41 +368,45 @@ typedef enum H5D_mpio_no_collective_cause_t { /** * Causes for H5Pget_no_selection_io_cause() property */ -#define H5D_DISABLE_BY_API \ +#define H5D_SEL_IO_DISABLE_BY_API \ (0x0001u) /**< Selection I/O was not performed because \ the feature was disabled by the API */ -#define H5D_DATATYPE_CONVERSION \ +#define H5D_SEL_IO_DATATYPE_CONVERSION \ (0x0002u) /**< Selection I/O was not performed because of \ datatype conversion */ -#define H5D_NOT_CONTIGUOUS_OR_CHUNKED_DATASET \ +#define H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET \ (0x0004u) /**< Selection I/O was not performed because the \ dataset was neither contiguous nor chunked */ -#define H5D_CONTIGUOUS_SIEVE_BUFFER \ +#define H5D_SEL_IO_CONTIGUOUS_SIEVE_BUFFER \ (0x0008u) /**< Selection I/O was not performed because of \ sieve buffer for contiguous dataset */ -#define H5D_NO_VECTOR_OR_SELECTION_IO_CB \ +#define H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB \ (0x0010u) /**< Selection I/O was not performed because the VFD \ does not have vector or selection I/O callback */ -#define H5D_PAGE_BUFFER \ +#define H5D_SEL_IO_PAGE_BUFFER \ (0x0020u) /**< Selection I/O was not performed because of \ page buffer */ -#define H5D_DATASET_FILTER \ +#define H5D_SEL_IO_DATASET_FILTER \ (0x0040u) /**< Selection I/O was not performed because of \ dataset filters */ -#define H5D_CHUNK_CACHE \ +#define H5D_SEL_IO_CHUNK_CACHE \ (0x0080u) /**< Selection I/O was not performed because of \ chunk cache */ -#define H5D_TCONV_BUF_TOO_SMALL \ +#define H5D_SEL_IO_TCONV_BUF_TOO_SMALL \ (0x0100u) /**< Selection I/O was not performed because the \ - type conversion buffer is too small \ - (for collective I/O) */ -#define H5D_NO_BENEFIT_BY_MPIO \ - (0x0200u) /**< Selection I/O was not performed because there \ - is no benefit (for MPIO) */ + type conversion buffer is too small */ +#define H5D_SEL_IO_BKG_BUF_TOO_SMALL \ + (0x0100u) /**< Selection I/O was not performed because the \ + type conversion background buffer is too small */ +#define H5D_SEL_IO_DEFAULT_OFF \ + (0x0200u) /**< Selection I/O was not performed because the \ + selection I/O mode is DEFAULT and the library \ + chose it to be off for this case */ /* Causes for H5D_MPIO_NO_SELECTION_IO */ #define H5D_MPIO_NO_SELECTION_IO_CAUSES \ - (H5D_DISABLE_BY_API | H5D_TCONV_BUF_TOO_SMALL | H5D_DATASET_FILTER | H5D_CHUNK_CACHE) + (H5D_SEL_IO_DISABLE_BY_API | H5D_SEL_IO_TCONV_BUF_TOO_SMALL | H5D_SEL_IO_BKG_BUF_TOO_SMALL | \ + H5D_SEL_IO_DATASET_FILTER | H5D_SEL_IO_CHUNK_CACHE) //! /** diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 19127b36f80..4303eee3995 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -260,6 +260,7 @@ H5_DLL herr_t H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, H5_DLL herr_t H5S_select_project_intersection(H5S_t *src_space, H5S_t *dst_space, H5S_t *src_intersect_space, H5S_t **new_space_ptr, hbool_t share_space); H5_DLL herr_t H5S_select_subtract(H5S_t *space, H5S_t *subtract_space); +H5_DLL herr_t H5S_select_contig_block(H5S_t *space, hbool_t *is_contig, hsize_t *off, size_t *len); /* Operations on all selections */ H5_DLL herr_t H5S_select_all(H5S_t *space, hbool_t rel_prev); diff --git a/src/H5Spublic.h b/src/H5Spublic.h index f8fed47aef3..7d0fe14e699 100644 --- a/src/H5Spublic.h +++ b/src/H5Spublic.h @@ -864,9 +864,9 @@ H5_DLL hid_t H5Ssel_iter_create(hid_t spaceid, size_t elmt_size, unsigned flags) * * \space_id{sel_iter_id} * \param[in] maxseq Maximum number of sequences to retrieve - * \param[in] maxbytes Maximum number of bytes to retrieve in sequences + * \param[in] maxelmts Maximum number of elements to retrieve in sequences * \param[out] nseq Number of sequences retrieved - * \param[out] nbytes Number of bytes retrieved, in all sequences + * \param[out] nelmts Number of elements retrieved, in all sequences * \param[out] off Array of sequence offsets * \param[out] len Array of sequence lengths * @@ -883,9 +883,9 @@ H5_DLL hid_t H5Ssel_iter_create(hid_t spaceid, size_t elmt_size, unsigned flags) * #H5S_SEL_ITER_GET_SEQ_LIST_SORTED flag is passed to * H5Ssel_iter_create() for a point selection. * - * \p maxseq and \p maxbytes specify the most sequences or bytes + * \p maxseq and \p maxelmts specify the most sequences or elements * possible to place into the \p off and \p len arrays. \p nseq and - * \p nbytes return the actual number of sequences and bytes put + * \p nelmts return the actual number of sequences and elements put * into the arrays. * * Each call to H5Ssel_iter_get_seq_list() will retrieve the next @@ -897,13 +897,13 @@ H5_DLL hid_t H5Ssel_iter_create(hid_t spaceid, size_t elmt_size, unsigned flags) * the iterator was created from (which can be retrieved with * H5Sget_select_npoints(). When there are no further sequences of * elements to retrieve, calls to this routine will set \p nseq - * and \p nbytes to zero. + * and \p nelmts to zero. * * \since 1.12.0 * */ -H5_DLL herr_t H5Ssel_iter_get_seq_list(hid_t sel_iter_id, size_t maxseq, size_t maxbytes, size_t *nseq, - size_t *nbytes, hsize_t *off, size_t *len); +H5_DLL herr_t H5Ssel_iter_get_seq_list(hid_t sel_iter_id, size_t maxseq, size_t maxelmts, size_t *nseq, + size_t *nelmts, hsize_t *off, size_t *len); /** * \ingroup H5S * diff --git a/src/H5Sselect.c b/src/H5Sselect.c index c2fb7fab8a3..f0a29d810f6 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -2997,9 +2997,9 @@ H5Ssel_iter_create(hid_t space_id, size_t elmt_size, unsigned flags) herr_t H5Ssel_iter_get_seq_list(sel_iter_id, maxseq, maxbytes, nseq, nbytes, off, len) hid_t sel_iter_id; IN: ID of the dataspace selection iterator to retrieve sequence from size_t maxseq; IN: Max. # of sequences to retrieve - size_t maxbytes; IN: Max. # of bytes to retrieve in sequences + size_t maxelmts; IN: Max. # of elements to retrieve in sequences size_t *nseq; OUT: # of sequences retrieved - size_t *nbytes; OUT: # of bytes retrieved, in all sequences + size_t *nelmts; OUT: # of elements retrieved, in all sequences hsize_t *off; OUT: Array of sequence offsets size_t *len; OUT: Array of sequence lengths RETURNS @@ -3014,8 +3014,8 @@ H5Ssel_iter_create(hid_t space_id, size_t elmt_size, unsigned flags) selections is "in order selected", unless the H5S_SEL_ITER_GET_SEQ_LIST_SORTED flag is passed to H5Sset_iter_create for a point selection. - MAXSEQ and MAXBYTES specify the most sequences or bytes possible to - place into the OFF and LEN arrays. *NSEQ and *NBYTES return the actual + MAXSEQ and MAXELMTS specify the most sequences or bytes possible to + place into the OFF and LEN arrays. *NSEQ and *NELMTS return the actual number of sequences and bytes put into the arrays. Each call to H5Ssel_iter_get_seq_list() will retrieve the next set @@ -3026,7 +3026,7 @@ H5Ssel_iter_create(hid_t space_id, size_t elmt_size, unsigned flags) of elements selected in the dataspace the iterator was created from (which can be retrieved with H5Sget_select_npoints). When there are no further sequences of elements to retrieve, calls to this routine will - set *NSEQ and *NBYTES to zero. + set *NSEQ and *NELMTS to zero. PROGRAMMER Quincey Koziol - February 11, 2019 GLOBAL VARIABLES @@ -3035,21 +3035,21 @@ H5Ssel_iter_create(hid_t space_id, size_t elmt_size, unsigned flags) REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5Ssel_iter_get_seq_list(hid_t sel_iter_id, size_t maxseq, size_t maxbytes, size_t *nseq /*out*/, - size_t *nbytes /*out*/, hsize_t *off /*out*/, size_t *len /*out*/) +H5Ssel_iter_get_seq_list(hid_t sel_iter_id, size_t maxseq, size_t maxelmts, size_t *nseq /*out*/, + size_t *nelmts /*out*/, hsize_t *off /*out*/, size_t *len /*out*/) { H5S_sel_iter_t *sel_iter; /* Dataspace selection iterator to operate on */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) - H5TRACE7("e", "izzxxxx", sel_iter_id, maxseq, maxbytes, nseq, nbytes, off, len); + H5TRACE7("e", "izzxxxx", sel_iter_id, maxseq, maxelmts, nseq, nelmts, off, len); /* Check args */ if (NULL == (sel_iter = (H5S_sel_iter_t *)H5I_object_verify(sel_iter_id, H5I_SPACE_SEL_ITER))) HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace selection iterator") if (NULL == nseq) HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "'nseq' pointer is NULL") - if (NULL == nbytes) + if (NULL == nelmts) HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "'nbytes' pointer is NULL") if (NULL == off) HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "offset array pointer is NULL") @@ -3057,17 +3057,94 @@ H5Ssel_iter_get_seq_list(hid_t sel_iter_id, size_t maxseq, size_t maxbytes, size HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "length array pointer is NULL") /* Get the sequences of bytes */ - if (maxseq > 0 && maxbytes > 0 && sel_iter->elmt_left > 0) { - if (H5S_SELECT_ITER_GET_SEQ_LIST(sel_iter, maxseq, maxbytes, nseq, nbytes, off, len) < 0) + if (maxseq > 0 && maxelmts > 0 && sel_iter->elmt_left > 0) { + if (H5S_SELECT_ITER_GET_SEQ_LIST(sel_iter, maxseq, maxelmts, nseq, nelmts, off, len) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "sequence length generation failed") } /* end if */ else - *nseq = *nbytes = 0; + *nseq = *nelmts = 0; done: FUNC_LEAVE_API(ret_value) } /* end H5Ssel_iter_get_seq_list() */ +/*-------------------------------------------------------------------------- + NAME + H5S_select_contig_block + + PURPOSE + Determines if a selection is a single contiguous block, and returns the + offset and length (in elements) if it is + + USAGE + herr_t H5S_select_contig_block(space, is_contig, off, len) + H5S_t *space; IN: Selection to check + hbool_t *is_contig; OUT: Whether the selection is contiguous + hsize_t *off; OUT: Offset of selection + size_t *len; OUT: Length of selection + + RETURNS + Non-negative on success/Negative on failure. + + DESCRIPTION + Determines if a selection is a single contiguous block, and returns the + offset and length (in elements) if it is. + + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_select_contig_block(H5S_t *space, hbool_t *is_contig, hsize_t *off, size_t *len) +{ + H5S_sel_iter_t *iter = NULL; /* Selection iterator */ + hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */ + size_t nseq_tmp; + size_t nelem_tmp; + hsize_t sel_off; + size_t sel_len; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(space); + + /* Allocate and initialize the iterator */ + if (NULL == (iter = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate iterator") + if (H5S_select_iter_init(iter, space, 1, 0) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize memory selection information") + iter_init = TRUE; + + /* Get list of sequences for selection, to check if it is contiguous */ + if (H5S_SELECT_ITER_GET_SEQ_LIST(iter, (size_t)1, (size_t)-1, &nseq_tmp, &nelem_tmp, &sel_off, &sel_len) < + 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "sequence length generation failed") + + /* If the first sequence includes all the elements selected in this piece, it it contiguous */ + H5_CHECK_OVERFLOW(space->select.num_elem, hsize_t, size_t); + if (sel_len == (size_t)space->select.num_elem) { + if (is_contig) + *is_contig = TRUE; + if (off) + *off = sel_off; + if (len) + *len = sel_len; + } + else if (is_contig) + *is_contig = FALSE; + +done: + if (iter_init && H5S_SELECT_ITER_RELEASE(iter) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator") + if (iter) + iter = H5FL_FREE(H5S_sel_iter_t, iter); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_select_contig_block() */ + /*-------------------------------------------------------------------------- NAME H5Ssel_iter_reset diff --git a/test/select_io_dset.c b/test/select_io_dset.c index 630d944ed24..ba0642e7bde 100644 --- a/test/select_io_dset.c +++ b/test/select_io_dset.c @@ -2569,7 +2569,7 @@ test_set_get_select_io_mode(hid_t fid) /* * To test with various test_mode that no selelction I/O is performed * - * Note: It's the responsiblity of the tester to feed proper combination + * Note: It's the responsibility of the tester to feed proper combination * of test_mode as needed. */ static herr_t @@ -2618,44 +2618,44 @@ test_no_selection_io_cause_mode(uint32_t test_mode) /* If on mode, will trigger nothing because the on mode path is different */ /* Need 2 writes */ if (test_mode & TEST_CONTIGUOUS_SIEVE_BUFFER) - no_selection_io_cause_expected |= H5D_CONTIGUOUS_SIEVE_BUFFER; + no_selection_io_cause_expected |= H5D_SEL_IO_CONTIGUOUS_SIEVE_BUFFER; if (test_mode & TEST_NOT_CONTIGUOUS_OR_CHUNKED_DATASET) { if (H5Pset_layout(dcpl, H5D_COMPACT) < 0) FAIL_STACK_ERROR; - no_selection_io_cause_expected |= H5D_NOT_CONTIGUOUS_OR_CHUNKED_DATASET; + no_selection_io_cause_expected |= H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET; } if (test_mode == TEST_DATASET_FILTER) { if (H5Pset_deflate(dcpl, 9) < 0) FAIL_STACK_ERROR; is_chunked = TRUE; - no_selection_io_cause_expected |= H5D_DATASET_FILTER; + no_selection_io_cause_expected |= H5D_SEL_IO_DATASET_FILTER; } if (test_mode == TEST_CHUNK_CACHE) { is_chunked = TRUE; - no_selection_io_cause_expected |= H5D_CHUNK_CACHE; + no_selection_io_cause_expected |= H5D_SEL_IO_CHUNK_CACHE; } if (test_mode == TEST_DISABLE_BY_API) { if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_OFF) < 0) FAIL_STACK_ERROR; - no_selection_io_cause_expected |= H5D_DISABLE_BY_API; + no_selection_io_cause_expected |= H5D_SEL_IO_DISABLE_BY_API; } if (test_mode & TEST_NO_VECTOR_OR_SELECTION_IO_CB) - no_selection_io_cause_expected |= H5D_NO_VECTOR_OR_SELECTION_IO_CB; + no_selection_io_cause_expected |= H5D_SEL_IO_DEFAULT_OFF; if (test_mode & TEST_DATATYPE_CONVERSION) { if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_ON) < 0) FAIL_STACK_ERROR; tid = H5T_NATIVE_UINT; - no_selection_io_cause_expected |= H5D_DATATYPE_CONVERSION; + no_selection_io_cause_expected |= H5D_SEL_IO_DATATYPE_CONVERSION; } if (test_mode & TEST_PAGE_BUFFER) - no_selection_io_cause_expected |= H5D_PAGE_BUFFER; + no_selection_io_cause_expected |= H5D_SEL_IO_PAGE_BUFFER; /* Create 1d data space */ dims[0] = DSET_SELECT_DIM; diff --git a/testpar/t_2Gio.c b/testpar/t_2Gio.c index 632db729c5b..173b2212fb0 100644 --- a/testpar/t_2Gio.c +++ b/testpar/t_2Gio.c @@ -3979,7 +3979,7 @@ test_no_collective_cause_mode(int selection_mode) test_name = "Broken Collective I/O - Datatype Conversion"; no_collective_cause_local_expected |= H5D_MPIO_DATATYPE_CONVERSION | H5D_MPIO_NO_SELECTION_IO; no_collective_cause_global_expected |= H5D_MPIO_DATATYPE_CONVERSION | H5D_MPIO_NO_SELECTION_IO; - no_selection_io_cause_expected |= H5D_DATATYPE_CONVERSION; + no_selection_io_cause_expected |= H5D_SEL_IO_DATATYPE_CONVERSION; /* set different sign to trigger type conversion */ data_type = H5T_NATIVE_UINT; } @@ -3988,7 +3988,7 @@ test_no_collective_cause_mode(int selection_mode) test_name = "Broken Collective I/O - DATA Transforms"; no_collective_cause_local_expected |= H5D_MPIO_DATA_TRANSFORMS | H5D_MPIO_NO_SELECTION_IO; no_collective_cause_global_expected |= H5D_MPIO_DATA_TRANSFORMS | H5D_MPIO_NO_SELECTION_IO; - no_selection_io_cause_expected |= H5D_DATATYPE_CONVERSION; + no_selection_io_cause_expected |= H5D_SEL_IO_DATATYPE_CONVERSION; } if (selection_mode & TEST_NOT_SIMPLE_OR_SCALAR_DATASPACES) { @@ -4070,7 +4070,7 @@ test_no_collective_cause_mode(int selection_mode) /* Disable selection I/O */ ret = H5Pset_selection_io(dxpl_write, H5D_SELECTION_IO_MODE_OFF); VRFY((ret >= 0), "H5Pset_selection_io succeeded"); - no_selection_io_cause_expected |= H5D_DISABLE_BY_API; + no_selection_io_cause_expected |= H5D_SEL_IO_DISABLE_BY_API; } if (selection_mode & TEST_DATA_TRANSFORMS) { diff --git a/testpar/t_dset.c b/testpar/t_dset.c index e6259370e7f..01355908b44 100644 --- a/testpar/t_dset.c +++ b/testpar/t_dset.c @@ -3565,7 +3565,7 @@ test_no_collective_cause_mode(int selection_mode) test_name = "Broken Collective I/O - Datatype Conversion"; no_collective_cause_local_expected |= H5D_MPIO_DATATYPE_CONVERSION | H5D_MPIO_NO_SELECTION_IO; no_collective_cause_global_expected |= H5D_MPIO_DATATYPE_CONVERSION | H5D_MPIO_NO_SELECTION_IO; - no_selection_io_cause_expected |= H5D_DATATYPE_CONVERSION; + no_selection_io_cause_expected |= H5D_SEL_IO_DATATYPE_CONVERSION; /* set different sign to trigger type conversion */ data_type = H5T_NATIVE_UINT; } @@ -3574,7 +3574,7 @@ test_no_collective_cause_mode(int selection_mode) test_name = "Broken Collective I/O - DATA Transforms"; no_collective_cause_local_expected |= H5D_MPIO_DATA_TRANSFORMS | H5D_MPIO_NO_SELECTION_IO; no_collective_cause_global_expected |= H5D_MPIO_DATA_TRANSFORMS | H5D_MPIO_NO_SELECTION_IO; - no_selection_io_cause_expected |= H5D_DATATYPE_CONVERSION; + no_selection_io_cause_expected |= H5D_SEL_IO_DATATYPE_CONVERSION; } if (selection_mode & TEST_NOT_SIMPLE_OR_SCALAR_DATASPACES) { @@ -3656,7 +3656,7 @@ test_no_collective_cause_mode(int selection_mode) /* Disable selection I/O */ ret = H5Pset_selection_io(dxpl_write, H5D_SELECTION_IO_MODE_OFF); VRFY((ret >= 0), "H5Pset_selection_io succeeded"); - no_selection_io_cause_expected |= H5D_DISABLE_BY_API; + no_selection_io_cause_expected |= H5D_SEL_IO_DISABLE_BY_API; } if (selection_mode & TEST_DATA_TRANSFORMS) { diff --git a/testpar/t_select_io_dset.c b/testpar/t_select_io_dset.c index a6df7d0b0a1..c920df77ade 100644 --- a/testpar/t_select_io_dset.c +++ b/testpar/t_select_io_dset.c @@ -887,6 +887,7 @@ test_cmpd_with_bkg(hid_t fid, unsigned chunked) check_io_mode(dxpl, chunked); /* Read all the data from the dataset */ + HDmemset(s1_rbuf, 0, sizeof(s1_t) * DSET_SELECT_DIM); if (H5Dread(did, s1_tid, mspace_id, fspace_id, dxpl, s1_rbuf) < 0) P_TEST_ERROR; @@ -926,7 +927,8 @@ test_cmpd_with_bkg(hid_t fid, unsigned chunked) P_TEST_ERROR; /* Read the whole compound back */ - if (H5Dread(did, ss_ac_tid, mspace_id, fspace_id, dxpl, s1_rbuf) < 0) + HDmemset(s1_rbuf, 0, sizeof(s1_t) * DSET_SELECT_DIM); + if (H5Dread(did, s1_tid, mspace_id, fspace_id, dxpl, s1_rbuf) < 0) P_TEST_ERROR; /* Verify the compound fields have the correct (old or new) values */ @@ -1007,6 +1009,7 @@ test_cmpd_with_bkg(hid_t fid, unsigned chunked) P_TEST_ERROR; /* Read it back */ + HDmemset(s2_rbuf, 0, sizeof(s2_t) * DSET_SELECT_DIM); if (H5Dread(did, s2_tid, mspace_id, fspace_id, dxpl, s2_rbuf) < 0) P_TEST_ERROR; @@ -3220,20 +3223,20 @@ test_no_selection_io_cause_mode(uint32_t test_mode) if (test_mode & TEST_NOT_CONTIGUOUS_OR_CHUNKED_DATASET) { if (H5Pset_layout(dcpl, H5D_COMPACT) < 0) P_TEST_ERROR; - no_selection_io_cause_expected |= H5D_NOT_CONTIGUOUS_OR_CHUNKED_DATASET; + no_selection_io_cause_expected |= H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET; } if (test_mode == TEST_DISABLE_BY_API) { if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_OFF) < 0) P_TEST_ERROR; - no_selection_io_cause_expected |= H5D_DISABLE_BY_API; + no_selection_io_cause_expected |= H5D_SEL_IO_DISABLE_BY_API; } if (test_mode & TEST_DATATYPE_CONVERSION) { if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_ON) < 0) P_TEST_ERROR; tid = H5T_NATIVE_UINT; - no_selection_io_cause_expected |= H5D_DATATYPE_CONVERSION; + no_selection_io_cause_expected |= H5D_SEL_IO_DATATYPE_CONVERSION; } /* Create 1d data space */