Implement selection I/O with type conversion (#2823)

Initial implementation of selection I/O with type conversion.  Allows
Parallel collective I/O with type conversion, as long as selection I/O
is enabled.
This commit is contained in:
Neil Fortner 2023-04-28 18:58:25 -05:00 committed by GitHub
parent 4497feb575
commit 3236fb79ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 9465 additions and 377 deletions

View File

@ -37,6 +37,7 @@ $Source = "";
"H5D_alloc_time_t" => "Da",
"H5D_append_cb_t" => "DA",
"H5FD_mpio_collective_opt_t" => "Dc",
"H5D_selection_io_mode_t" => "DC",
"H5D_fill_time_t" => "Df",
"H5D_fill_value_t" => "DF",
"H5D_gather_func_t" => "Dg",

View File

@ -694,6 +694,18 @@ of the library for reading or writing the actual data.</td>
<td>Gets local and global causes that broke collective I/O on the last parallel I/O call.</td>
</tr>
<tr>
<td>#H5Pset_selection_io/#H5Pget_selection_io</td>
<td>Sets/gets the selection I/O mode.</td>
</tr>
<tr>
<td>#H5Pget_no_selection_io_cause</td>
<td>Gets the cause for not performing selection or vector I/O on the last parallel I/O call.</td>
</tr>
<tr>
<td>#H5Pset_modify_write_buf/#H5Pget_modify_write_buf</td>
<td>Sets/gets a flag allowing the library to modify the contents of the write buffer.</td>
</tr>
<tr>
<td>H5Pset_preserve/H5Pget_preserve</td>
<td>No longer available, deprecated as it no longer has any effect.</td>
</tr>
@ -952,4 +964,3 @@ encoding for object names.</td>
//! [acpl_table]
*
*/

View File

@ -105,6 +105,16 @@ New Features
machine's node-local storage while placing the subfiling configuration
file on a file system readable by all machine nodes.
- Added H5Pset_selection_io(), H5Pget_selection_io(), and
H5Pget_no_selection_io_cause() API functions to manage the selection I/O
feature. This can be used to enable collective I/O with type conversion,
or it can be used with custom VFDs that support vector or selection I/O.
- Added H5Pset_modify_write_buf() and H5Pget_modify_write_buf() API
functions to allow the library to modify the contents of write buffers, in
order to avoid malloc/memcpy. Currently only used for type conversion
with selection I/O.
Parallel Library:
-----------------

View File

@ -82,8 +82,6 @@ hbool_t H5_libinit_g = FALSE; /* Library hasn't been initialized */
hbool_t H5_libterm_g = FALSE; /* Library isn't being shutdown */
#endif
hbool_t H5_use_selection_io_g = FALSE;
char H5_lib_vers_info_g[] = H5_VERS_INFO;
static hbool_t H5_dont_atexit_g = FALSE;
H5_debug_t H5_debug_g; /* debugging info */
@ -141,8 +139,7 @@ herr_t
H5_init_library(void)
{
size_t i;
char *env_use_select_io = NULL;
herr_t ret_value = SUCCEED;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
@ -274,14 +271,6 @@ H5_init_library(void)
}
/* clang-format on */
/* Check for HDF5_USE_SELECTION_IO env variable */
env_use_select_io = HDgetenv("HDF5_USE_SELECTION_IO");
if (NULL != env_use_select_io && HDstrcmp(env_use_select_io, "") && HDstrcmp(env_use_select_io, "0") &&
HDstrcmp(env_use_select_io, "no") && HDstrcmp(env_use_select_io, "No") &&
HDstrcmp(env_use_select_io, "NO") && HDstrcmp(env_use_select_io, "false") &&
HDstrcmp(env_use_select_io, "False") && HDstrcmp(env_use_select_io, "FALSE"))
H5_use_selection_io_g = TRUE;
/* Debugging? */
H5__debug_mask("-all");
H5__debug_mask(HDgetenv("HDF5_DEBUG"));

View File

@ -94,14 +94,12 @@
H5CX_RETRIEVE_PROP_COMMON(PL, DEF_PL, PROP_NAME, PROP_FIELD) \
} /* end if */
#ifdef H5_HAVE_PARALLEL
/* Macro for the duplicated code to retrieve possibly set properties from a property list */
#define H5CX_RETRIEVE_PROP_VALID_SET(PL, DEF_PL, PROP_NAME, PROP_FIELD) \
/* Check if the value has been retrieved already */ \
if (!((*head)->ctx.H5_GLUE(PROP_FIELD, _valid) || (*head)->ctx.H5_GLUE(PROP_FIELD, _set))) { \
H5CX_RETRIEVE_PROP_COMMON(PL, DEF_PL, PROP_NAME, PROP_FIELD) \
} /* end if */
#endif /* H5_HAVE_PARALLEL */
} /* end if */
#if defined(H5_HAVE_PARALLEL) && defined(H5_HAVE_INSTRUMENTED_LIBRARY)
/* Macro for the duplicated code to test and set properties for a property list */
@ -127,7 +125,6 @@
}
#endif /* defined(H5_HAVE_PARALLEL) && defined(H5_HAVE_INSTRUMENTED_LIBRARY) */
#ifdef H5_HAVE_PARALLEL
/* Macro for the duplicated code to test and set properties for a property list */
#define H5CX_SET_PROP(PROP_NAME, PROP_FIELD) \
if ((*head)->ctx.H5_GLUE(PROP_FIELD, _set)) { \
@ -137,8 +134,7 @@
/* Set the property */ \
if (H5P_set((*head)->ctx.dxpl, PROP_NAME, &(*head)->ctx.PROP_FIELD) < 0) \
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTSET, NULL, "error setting data xfer property") \
} /* end if */
#endif /* H5_HAVE_PARALLEL */
} /* end if */
/******************/
/* Local Typedefs */
@ -242,16 +238,20 @@ typedef struct H5CX_t {
unsigned mpio_chunk_opt_ratio; /* Collective chunk ratio (H5D_XFER_MPIO_CHUNK_OPT_RATIO_NAME) */
hbool_t mpio_chunk_opt_ratio_valid; /* Whether collective chunk ratio is valid */
#endif /* H5_HAVE_PARALLEL */
H5Z_EDC_t err_detect; /* Error detection info (H5D_XFER_EDC_NAME) */
hbool_t err_detect_valid; /* Whether error detection info is valid */
H5Z_cb_t filter_cb; /* Filter callback function (H5D_XFER_FILTER_CB_NAME) */
hbool_t filter_cb_valid; /* Whether filter callback function is valid */
H5Z_data_xform_t *data_transform; /* Data transform info (H5D_XFER_XFORM_NAME) */
hbool_t data_transform_valid; /* Whether data transform info is valid */
H5T_vlen_alloc_info_t vl_alloc_info; /* VL datatype alloc info (H5D_XFER_VLEN_*_NAME) */
hbool_t vl_alloc_info_valid; /* Whether VL datatype alloc info is valid */
H5T_conv_cb_t dt_conv_cb; /* Datatype conversion struct (H5D_XFER_CONV_CB_NAME) */
hbool_t dt_conv_cb_valid; /* Whether datatype conversion struct is valid */
H5Z_EDC_t err_detect; /* Error detection info (H5D_XFER_EDC_NAME) */
hbool_t err_detect_valid; /* Whether error detection info is valid */
H5Z_cb_t filter_cb; /* Filter callback function (H5D_XFER_FILTER_CB_NAME) */
hbool_t filter_cb_valid; /* Whether filter callback function is valid */
H5Z_data_xform_t *data_transform; /* Data transform info (H5D_XFER_XFORM_NAME) */
hbool_t data_transform_valid; /* Whether data transform info is valid */
H5T_vlen_alloc_info_t vl_alloc_info; /* VL datatype alloc info (H5D_XFER_VLEN_*_NAME) */
hbool_t vl_alloc_info_valid; /* Whether VL datatype alloc info is valid */
H5T_conv_cb_t dt_conv_cb; /* Datatype conversion struct (H5D_XFER_CONV_CB_NAME) */
hbool_t dt_conv_cb_valid; /* Whether datatype conversion struct is valid */
H5D_selection_io_mode_t selection_io_mode; /* Selection I/O mode (H5D_XFER_SELECTION_IO_MODE_NAME) */
hbool_t selection_io_mode_valid; /* Whether selection I/O mode is valid */
hbool_t modify_write_buf; /* Whether the library can modify write buffers */
hbool_t modify_write_buf_valid; /* Whether the modify_write_buf field is valid */
/* Return-only DXPL properties to return to application */
#ifdef H5_HAVE_PARALLEL
@ -297,9 +297,13 @@ typedef struct H5CX_t {
hbool_t mpio_coll_rank0_bcast; /* Instrumented "collective chunk multi ratio ind" value
(H5D_XFER_COLL_CHUNK_MULTI_RATIO_IND_NAME) */
hbool_t
mpio_coll_rank0_bcast_set; /* Whether instrumented "collective chunk multi ratio ind" value is set */
#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
#endif /* H5_HAVE_PARALLEL */
mpio_coll_rank0_bcast_set; /* Whether instrumented "collective chunk multi ratio ind" value is set */
#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
#endif /* H5_HAVE_PARALLEL */
uint32_t no_selection_io_cause; /* Reason for not performing selection I/O
(H5D_XFER_NO_SELECTION_IO_CAUSE_NAME) */
hbool_t no_selection_io_cause_set; /* Whether reason for not performing selection I/O is set */
hbool_t no_selection_io_cause_valid; /* Whether reason for not performing selection I/O is valid */
/* Cached LCPL properties */
H5T_cset_t encoding; /* Link name character encoding */
@ -370,15 +374,19 @@ typedef struct H5CX_dxpl_cache_t {
uint32_t mpio_global_no_coll_cause; /* Global reason for breaking collective I/O
(H5D_MPIO_GLOBAL_NO_COLLECTIVE_CAUSE_NAME) */
H5FD_mpio_chunk_opt_t
mpio_chunk_opt_mode; /* Collective chunk option (H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME) */
unsigned mpio_chunk_opt_num; /* Collective chunk threshold (H5D_XFER_MPIO_CHUNK_OPT_NUM_NAME) */
unsigned mpio_chunk_opt_ratio; /* Collective chunk ratio (H5D_XFER_MPIO_CHUNK_OPT_RATIO_NAME) */
#endif /* H5_HAVE_PARALLEL */
H5Z_EDC_t err_detect; /* Error detection info (H5D_XFER_EDC_NAME) */
H5Z_cb_t filter_cb; /* Filter callback function (H5D_XFER_FILTER_CB_NAME) */
H5Z_data_xform_t *data_transform; /* Data transform info (H5D_XFER_XFORM_NAME) */
H5T_vlen_alloc_info_t vl_alloc_info; /* VL datatype alloc info (H5D_XFER_VLEN_*_NAME) */
H5T_conv_cb_t dt_conv_cb; /* Datatype conversion struct (H5D_XFER_CONV_CB_NAME) */
mpio_chunk_opt_mode; /* Collective chunk option (H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME) */
unsigned mpio_chunk_opt_num; /* Collective chunk threshold (H5D_XFER_MPIO_CHUNK_OPT_NUM_NAME) */
unsigned mpio_chunk_opt_ratio; /* Collective chunk ratio (H5D_XFER_MPIO_CHUNK_OPT_RATIO_NAME) */
#endif /* H5_HAVE_PARALLEL */
H5Z_EDC_t err_detect; /* Error detection info (H5D_XFER_EDC_NAME) */
H5Z_cb_t filter_cb; /* Filter callback function (H5D_XFER_FILTER_CB_NAME) */
H5Z_data_xform_t *data_transform; /* Data transform info (H5D_XFER_XFORM_NAME) */
H5T_vlen_alloc_info_t vl_alloc_info; /* VL datatype alloc info (H5D_XFER_VLEN_*_NAME) */
H5T_conv_cb_t dt_conv_cb; /* Datatype conversion struct (H5D_XFER_CONV_CB_NAME) */
H5D_selection_io_mode_t selection_io_mode; /* Selection I/O mode (H5D_XFER_SELECTION_IO_MODE_NAME) */
uint32_t no_selection_io_cause; /* Reasons for not performing selection I/O
(H5D_XFER_NO_SELECTION_IO_CAUSE_NAME) */
hbool_t modify_write_buf; /* Whether the library can modify write buffers */
} H5CX_dxpl_cache_t;
/* Typedef for cached default link creation property list information */
@ -566,6 +574,19 @@ H5CX_init(void)
if (H5P_get(dx_plist, H5D_XFER_CONV_CB_NAME, &H5CX_def_dxpl_cache.dt_conv_cb) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "Can't retrieve datatype conversion exception callback")
/* Get the selection I/O mode */
if (H5P_get(dx_plist, H5D_XFER_SELECTION_IO_MODE_NAME, &H5CX_def_dxpl_cache.selection_io_mode) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "Can't retrieve parallel transfer method")
/* Get the local & global reasons for breaking selection I/O values */
if (H5P_get(dx_plist, H5D_XFER_NO_SELECTION_IO_CAUSE_NAME, &H5CX_def_dxpl_cache.no_selection_io_cause) <
0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "Can't retrieve cause for no selection I/O")
/* Get the modify write buffer property */
if (H5P_get(dx_plist, H5D_XFER_MODIFY_WRITE_BUF_NAME, &H5CX_def_dxpl_cache.modify_write_buf) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "Can't retrieve modify write buffer property")
/* Reset the "default LCPL cache" information */
HDmemset(&H5CX_def_lcpl_cache, 0, sizeof(H5CX_lcpl_cache_t));
@ -2563,6 +2584,111 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5CX_get_dt_conv_cb() */
/*-------------------------------------------------------------------------
* Function: H5CX_get_selection_io_mode
*
* Purpose: Retrieves the selection I/O mode for the current API call context.
*
* Return: Non-negative on success / Negative on failure
*
* Programmer: Vailin Choi
* March 5, 2023
*
*-------------------------------------------------------------------------
*/
herr_t
H5CX_get_selection_io_mode(H5D_selection_io_mode_t *selection_io_mode)
{
H5CX_node_t **head = NULL; /* Pointer to head of API context list */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity check */
HDassert(selection_io_mode);
head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
HDassert(head && *head);
HDassert(H5P_DEFAULT != (*head)->ctx.dxpl_id);
H5CX_RETRIEVE_PROP_VALID(dxpl, H5P_DATASET_XFER_DEFAULT, H5D_XFER_SELECTION_IO_MODE_NAME,
selection_io_mode)
/* Get the value */
*selection_io_mode = (*head)->ctx.selection_io_mode;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5CX_get_selection_io_mode() */
/*-------------------------------------------------------------------------
* Function: H5CX_get_no_selection_io_cause
*
* Purpose: Retrieves the cause for not performing selection I/O
* for the current API call context.
*
* Return: Non-negative on success / Negative on failure
*
* Programmer: Vailin Choi
* April 15, 2023
*
*-------------------------------------------------------------------------
*/
herr_t
H5CX_get_no_selection_io_cause(uint32_t *no_selection_io_cause)
{
H5CX_node_t **head = NULL; /* Pointer to head of API context list */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity check */
HDassert(no_selection_io_cause);
head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
HDassert(head && *head);
HDassert(H5P_DEFAULT != (*head)->ctx.dxpl_id);
H5CX_RETRIEVE_PROP_VALID_SET(dxpl, H5P_DATASET_XFER_DEFAULT, H5D_XFER_NO_SELECTION_IO_CAUSE_NAME,
no_selection_io_cause)
/* Get the value */
*no_selection_io_cause = (*head)->ctx.no_selection_io_cause;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5CX_get_no_selection_io_cause() */
/*-------------------------------------------------------------------------
* Function: H5CX_get_modify_write_buf
*
* Purpose: Retrieves the modify write buffer property for the current API call context.
*
* Return: Non-negative on success / Negative on failure
*
*-------------------------------------------------------------------------
*/
herr_t
H5CX_get_modify_write_buf(hbool_t *modify_write_buf)
{
H5CX_node_t **head = NULL; /* Pointer to head of API context list */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity check */
HDassert(modify_write_buf);
head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
HDassert(head && *head);
HDassert(H5P_DEFAULT != (*head)->ctx.dxpl_id);
H5CX_RETRIEVE_PROP_VALID(dxpl, H5P_DATASET_XFER_DEFAULT, H5D_XFER_MODIFY_WRITE_BUF_NAME, modify_write_buf)
/* Get the value */
*modify_write_buf = (*head)->ctx.modify_write_buf;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5CX_get_selection_io_mode() */
/*-------------------------------------------------------------------------
* Function: H5CX_get_encoding
*
@ -3543,6 +3669,41 @@ done:
#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
#endif /* H5_HAVE_PARALLEL */
/*-------------------------------------------------------------------------
* Function: H5CX_set_no_selecction_io_cause
*
* Purpose: Sets the reason for not performing selection I/O for
* the current API call context.
*
* Return: <none>
*
* Programmer: Vailin Choi
* April 15, 2023
*
*-------------------------------------------------------------------------
*/
void
H5CX_set_no_selection_io_cause(uint32_t no_selection_io_cause)
{
H5CX_node_t **head = NULL; /* Pointer to head of API context list */
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Sanity checks */
head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
HDassert(head && *head);
HDassert((*head)->ctx.dxpl_id != H5P_DEFAULT);
/* If we're using the default DXPL, don't modify it */
if ((*head)->ctx.dxpl_id != H5P_DATASET_XFER_DEFAULT) {
/* Cache the value for later, marking it to set in DXPL when context popped */
(*head)->ctx.no_selection_io_cause = no_selection_io_cause;
(*head)->ctx.no_selection_io_cause_set = TRUE;
} /* end if */
FUNC_LEAVE_NOAPI_VOID
} /* end H5CX_set_no_selectiion_io_cause() */
/*-------------------------------------------------------------------------
* Function: H5CX_get_ohdr_flags
*
@ -3596,11 +3757,7 @@ H5CX__pop_common(hbool_t update_dxpl_props)
H5CX_node_t **head = NULL; /* Pointer to head of API context list */
H5CX_node_t *ret_value = NULL; /* Return value */
#ifdef H5_HAVE_PARALLEL
FUNC_ENTER_PACKAGE
#else
FUNC_ENTER_PACKAGE_NOERR
#endif
/* Sanity check */
head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
@ -3608,6 +3765,7 @@ H5CX__pop_common(hbool_t update_dxpl_props)
/* Check for cached DXPL properties to return to application */
if (update_dxpl_props) {
H5CX_SET_PROP(H5D_XFER_NO_SELECTION_IO_CAUSE_NAME, no_selection_io_cause)
#ifdef H5_HAVE_PARALLEL
H5CX_SET_PROP(H5D_MPIO_ACTUAL_CHUNK_OPT_MODE_NAME, mpio_actual_chunk_opt)
H5CX_SET_PROP(H5D_MPIO_ACTUAL_IO_MODE_NAME, mpio_actual_io_mode)
@ -3629,9 +3787,7 @@ H5CX__pop_common(hbool_t update_dxpl_props)
ret_value = (*head);
(*head) = (*head)->next;
#ifdef H5_HAVE_PARALLEL
done:
#endif /* H5_HAVE_PARALLEL */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5CX__pop_common() */

View File

@ -115,6 +115,9 @@ H5_DLL herr_t H5CX_get_filter_cb(H5Z_cb_t *filter_cb);
H5_DLL herr_t H5CX_get_data_transform(H5Z_data_xform_t **data_transform);
H5_DLL herr_t H5CX_get_vlen_alloc_info(H5T_vlen_alloc_info_t *vl_alloc_info);
H5_DLL herr_t H5CX_get_dt_conv_cb(H5T_conv_cb_t *cb_struct);
H5_DLL herr_t H5CX_get_selection_io_mode(H5D_selection_io_mode_t *selection_io_mode);
H5_DLL herr_t H5CX_get_no_selection_io_cause(uint32_t *no_selection_io_cause);
H5_DLL herr_t H5CX_get_modify_write_buf(hbool_t *modify_write_buf);
/* "Getter" routines for LCPL properties cached in API context */
H5_DLL herr_t H5CX_get_encoding(H5T_cset_t *encoding);
@ -158,6 +161,9 @@ H5_DLL herr_t H5CX_set_nlinks(size_t nlinks);
H5_DLL herr_t H5CX_init(void);
/* "Setter" routines for cached DXPL properties that must be returned to application */
H5_DLL void H5CX_set_no_selection_io_cause(uint32_t no_selection_io_cause);
#ifdef H5_HAVE_PARALLEL
H5_DLL void H5CX_set_mpio_actual_chunk_opt(H5D_mpio_actual_chunk_opt_mode_t chunk_opt);
H5_DLL void H5CX_set_mpio_actual_io_mode(H5D_mpio_actual_io_mode_t actual_io_mode);

View File

@ -289,21 +289,21 @@ static ssize_t H5D__nonexistent_readvv(const H5D_io_info_t *io_info, const H5D_d
static int H5D__chunk_format_convert_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata);
/* Helper routines */
static herr_t H5D__chunk_set_info_real(H5O_layout_chunk_t *layout, unsigned ndims, const hsize_t *curr_dims,
const hsize_t *max_dims);
static herr_t H5D__chunk_cinfo_cache_reset(H5D_chunk_cached_t *last);
static herr_t H5D__chunk_cinfo_cache_update(H5D_chunk_cached_t *last, const H5D_chunk_ud_t *udata);
static hbool_t H5D__chunk_cinfo_cache_found(const H5D_chunk_cached_t *last, H5D_chunk_ud_t *udata);
static herr_t H5D__create_piece_map_single(H5D_dset_io_info_t *di, H5D_io_info_t *io_info);
static herr_t H5D__create_piece_file_map_all(H5D_dset_io_info_t *di, H5D_io_info_t *io_info);
static herr_t H5D__create_piece_file_map_hyper(H5D_dset_io_info_t *di, H5D_io_info_t *io_info);
static herr_t H5D__create_piece_mem_map_1d(const H5D_dset_io_info_t *di);
static herr_t H5D__create_piece_mem_map_hyper(const H5D_dset_io_info_t *di);
static herr_t H5D__piece_file_cb(void *elem, const H5T_t *type, unsigned ndims, const hsize_t *coords,
static herr_t H5D__chunk_set_info_real(H5O_layout_chunk_t *layout, unsigned ndims, const hsize_t *curr_dims,
const hsize_t *max_dims);
static herr_t H5D__chunk_cinfo_cache_reset(H5D_chunk_cached_t *last);
static herr_t H5D__chunk_cinfo_cache_update(H5D_chunk_cached_t *last, const H5D_chunk_ud_t *udata);
static hbool_t H5D__chunk_cinfo_cache_found(const H5D_chunk_cached_t *last, H5D_chunk_ud_t *udata);
static herr_t H5D__create_piece_map_single(H5D_dset_io_info_t *di, H5D_io_info_t *io_info);
static herr_t H5D__create_piece_file_map_all(H5D_dset_io_info_t *di, H5D_io_info_t *io_info);
static herr_t H5D__create_piece_file_map_hyper(H5D_dset_io_info_t *di, H5D_io_info_t *io_info);
static herr_t H5D__create_piece_mem_map_1d(const H5D_dset_io_info_t *di);
static herr_t H5D__create_piece_mem_map_hyper(const H5D_dset_io_info_t *di);
static herr_t H5D__piece_file_cb(void *elem, const H5T_t *type, unsigned ndims, const hsize_t *coords,
void *_opdata);
static herr_t H5D__piece_mem_cb(void *elem, const H5T_t *type, unsigned ndims, const hsize_t *coords,
void *_opdata);
static herr_t H5D__piece_mem_cb(void *elem, const H5T_t *type, unsigned ndims, const hsize_t *coords,
void *_opdata);
static htri_t H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info);
static herr_t H5D__chunk_may_use_select_io(H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info);
static unsigned H5D__chunk_hash_val(const H5D_shared_t *shared, const hsize_t *scaled);
static herr_t H5D__chunk_flush_entry(const H5D_t *dset, H5D_rdcc_ent_t *ent, hbool_t reset);
static herr_t H5D__chunk_cache_evict(const H5D_t *dset, H5D_rdcc_ent_t *ent, hbool_t flush);
@ -1062,9 +1062,8 @@ H5D__chunk_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
htri_t file_space_normalized = FALSE; /* File dataspace was normalized */
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) */
htri_t use_selection_io = FALSE; /* Whether to use selection I/O */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@ -1114,10 +1113,29 @@ H5D__chunk_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
/* Check if we're performing selection I/O and save the result if it hasn't
* been disabled already */
if (io_info->use_select_io) {
if ((use_selection_io = H5D__chunk_may_use_select_io(io_info, dinfo)) < 0)
if (io_info->use_select_io != H5D_SELECTION_IO_MODE_OFF)
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")
io_info->use_select_io = (hbool_t)use_selection_io;
/* Calculate type conversion buffer size if necessary. Currently only implemented for selection I/O. */
if (io_info->use_select_io != H5D_SELECTION_IO_MODE_OFF &&
!(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:
@ -1571,6 +1589,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;
@ -1700,6 +1722,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);
@ -1896,6 +1922,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++;
@ -2271,6 +2301,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;
@ -2547,11 +2581,11 @@ done:
*
*-------------------------------------------------------------------------
*/
static htri_t
H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info)
static herr_t
H5D__chunk_may_use_select_io(H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info)
{
const H5D_t *dataset = NULL; /* Local pointer to dataset info */
htri_t ret_value = FAIL; /* Return value */
const H5D_t *dataset = NULL; /* Local pointer to dataset info */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@ -2562,20 +2596,22 @@ H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_inf
dataset = dset_info->dset;
HDassert(dataset);
/* Don't use selection I/O if it's globally disabled, there is a type
* conversion, or if there are filters on the dataset (for now) */
if (dset_info->io_ops.single_read != H5D__select_read || dataset->shared->dcpl_cache.pline.nused > 0)
ret_value = FALSE;
/* 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_SEL_IO_DATASET_FILTER;
}
else {
hbool_t page_buf_enabled;
HDassert(dset_info->io_ops.single_write == H5D__select_write);
/* Check if the page buffer is enabled */
if (H5PB_enabled(io_info->f_sh, H5FD_MEM_DRAW, &page_buf_enabled) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if page buffer is enabled")
if (page_buf_enabled)
ret_value = FALSE;
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_SEL_IO_PAGE_BUFFER;
}
else {
/* Check if chunks in this dataset may be cached, if so don't use
* selection I/O (for now). Note that chunks temporarily cached for
@ -2586,16 +2622,14 @@ H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_inf
* must bypass the chunk-cache scheme because other MPI processes
* could be writing to other elements in the same chunk.
*/
if (io_info->using_mpi_vfd && (H5F_ACC_RDWR & H5F_INTENT(dataset->oloc.file)))
ret_value = TRUE;
else {
if (!(io_info->using_mpi_vfd && (H5F_ACC_RDWR & H5F_INTENT(dataset->oloc.file)))) {
#endif /* H5_HAVE_PARALLEL */
/* Check if the chunk is too large to keep in the cache */
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)
ret_value = TRUE;
else
ret_value = FALSE;
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_SEL_IO_CHUNK_CACHE;
}
#ifdef H5_HAVE_PARALLEL
} /* end else */
#endif /* H5_HAVE_PARALLEL */
@ -2668,7 +2702,7 @@ H5D__chunk_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
}
/* Different blocks depending on whether we're using selection I/O */
if (io_info->use_select_io) {
if (io_info->use_select_io == H5D_SELECTION_IO_MODE_ON) {
size_t num_chunks;
size_t element_sizes[2] = {dset_info->type_info.src_type_size, 0};
void *bufs[2] = {dset_info->buf.vp, NULL};
@ -2749,6 +2783,8 @@ H5D__chunk_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
io_info->addrs[io_info->pieces_added] = udata.chunk_block.offset;
io_info->element_sizes[io_info->pieces_added] = element_sizes[0];
io_info->rbufs[io_info->pieces_added] = bufs[0];
if (io_info->sel_pieces)
io_info->sel_pieces[io_info->pieces_added] = chunk_info;
io_info->pieces_added++;
}
} /* end if */
@ -2766,7 +2802,7 @@ H5D__chunk_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
chunk_node = H5D_CHUNK_GET_NEXT_NODE(dset_info, chunk_node);
} /* end while */
/* Only perform I/O if not performing multi dataset I/O, otherwise the
/* Only perform I/O if not performing multi dataset I/O or type conversion, otherwise the
* higher level will handle it after all datasets have been processed */
if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) {
/* Issue selection I/O call (we can skip the page buffer because we've
@ -2787,7 +2823,13 @@ H5D__chunk_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
chunk_addrs = H5MM_xfree(chunk_addrs);
} /* end if */
} /* end if */
} /* end if */
#ifdef H5_HAVE_PARALLEL
/* Report that collective chunk I/O was used (will only be set on the DXPL if collective I/O was
* requested) */
io_info->actual_io_mode |= H5D_MPIO_CHUNK_COLLECTIVE;
#endif /* H5_HAVE_PARALLEL */
} /* end if */
else {
H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
@ -2981,7 +3023,7 @@ H5D__chunk_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
cpt_store.compact.dirty = &cpt_dirty;
/* Different blocks depending on whether we're using selection I/O */
if (io_info->use_select_io) {
if (io_info->use_select_io == H5D_SELECTION_IO_MODE_ON) {
size_t num_chunks;
size_t element_sizes[2] = {dset_info->type_info.dst_type_size, 0};
const void *bufs[2] = {dset_info->buf.cvp, NULL};
@ -3139,6 +3181,8 @@ H5D__chunk_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
io_info->addrs[io_info->pieces_added] = udata.chunk_block.offset;
io_info->element_sizes[io_info->pieces_added] = element_sizes[0];
io_info->wbufs[io_info->pieces_added] = bufs[0];
if (io_info->sel_pieces)
io_info->sel_pieces[io_info->pieces_added] = chunk_info;
io_info->pieces_added++;
}
} /* end else */
@ -3147,7 +3191,7 @@ H5D__chunk_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
chunk_node = H5D_CHUNK_GET_NEXT_NODE(dset_info, chunk_node);
} /* end while */
/* Only perform I/O if not performing multi dataset I/O, otherwise the
/* Only perform I/O if not performing multi dataset I/O or type conversion, otherwise the
* higher level will handle it after all datasets have been processed */
if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) {
/* Issue selection I/O call (we can skip the page buffer because we've
@ -3168,7 +3212,13 @@ H5D__chunk_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
chunk_addrs = H5MM_xfree(chunk_addrs);
} /* end if */
} /* end if */
} /* end if */
#ifdef H5_HAVE_PARALLEL
/* Report that collective chunk I/O was used (will only be set on the DXPL if collective I/O was
* requested) */
io_info->actual_io_mode |= H5D_MPIO_CHUNK_COLLECTIVE;
#endif /* H5_HAVE_PARALLEL */
} /* end if */
else {
/* Iterate through nodes in chunk skip list */
chunk_node = H5D_CHUNK_GET_FIRST_NODE(dset_info);

View File

@ -252,7 +252,8 @@ H5D__compact_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
dinfo->store->compact.dirty = &dinfo->dset->shared->layout.storage.u.compact.dirty;
/* Disable selection I/O */
io_info->use_select_io = FALSE;
io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF;
io_info->no_selection_io_cause |= H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__compact_io_init() */

View File

@ -106,7 +106,7 @@ static herr_t H5D__contig_io_term(H5D_io_info_t *io_info, H5D_dset_io_info_t *d
/* Helper routines */
static herr_t H5D__contig_write_one(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, hsize_t offset,
size_t size);
static htri_t H5D__contig_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
static herr_t H5D__contig_may_use_select_io(H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
H5D_io_op_type_t op_type);
/*********************/
@ -586,8 +586,7 @@ H5D__contig_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
int sf_ndims; /* The number of dimensions of the file dataspace (signed) */
htri_t use_selection_io = FALSE; /* Whether to use selection I/O */
herr_t ret_value = SUCCEED; /* Return value */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@ -666,6 +665,16 @@ 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. Currently
* only implemented for selection I/O. */
if (io_info->use_select_io != H5D_SELECTION_IO_MODE_OFF &&
!(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;
@ -676,11 +685,9 @@ H5D__contig_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
/* Check if we're performing selection I/O if it hasn't been disabled
* already */
if (io_info->use_select_io) {
if ((use_selection_io = H5D__contig_may_use_select_io(io_info, dinfo, H5D_IO_OP_READ)) < 0)
if (io_info->use_select_io != H5D_SELECTION_IO_MODE_OFF)
if (H5D__contig_may_use_select_io(io_info, dinfo, io_info->op_type) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if selection I/O is possible")
io_info->use_select_io = (hbool_t)use_selection_io;
}
done:
if (ret_value < 0) {
@ -740,12 +747,12 @@ H5D__contig_mdio_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
*
*-------------------------------------------------------------------------
*/
static htri_t
H5D__contig_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
static herr_t
H5D__contig_may_use_select_io(H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
H5D_io_op_type_t op_type)
{
const H5D_t *dataset = NULL; /* Local pointer to dataset info */
htri_t ret_value = FAIL; /* Return value */
const H5D_t *dataset = NULL; /* Local pointer to dataset info */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@ -757,27 +764,33 @@ H5D__contig_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_in
dataset = dset_info->dset;
/* Don't use selection I/O if it's globally disabled, if there is a type
* conversion, or if it's not a contiguous dataset, or if the sieve buffer
* exists (write) or is dirty (read) */
if (dset_info->io_ops.single_read != H5D__select_read ||
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))
ret_value = FALSE;
/* None of the reasons this function might disable selection I/O are relevant to parallel, so no need to
* update no_selection_io_cause since we're only keeping track of the reason for no selection I/O in
* parallel (for now) */
/* 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) {
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_SEL_IO_CONTIGUOUS_SIEVE_BUFFER;
}
else {
hbool_t page_buf_enabled;
HDassert(dset_info->io_ops.single_write == H5D__select_write);
HDassert(dset_info->layout_ops.writevv == H5D__contig_writevv);
/* Check if the page buffer is enabled */
if (H5PB_enabled(io_info->f_sh, H5FD_MEM_DRAW, &page_buf_enabled) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if page buffer is enabled")
if (page_buf_enabled)
ret_value = FALSE;
else
ret_value = TRUE;
if (page_buf_enabled) {
io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF;
io_info->no_selection_io_cause |= H5D_SEL_IO_PAGE_BUFFER;
}
} /* end else */
done:
@ -810,9 +823,9 @@ H5D__contig_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
HDassert(dinfo->mem_space);
HDassert(dinfo->file_space);
if (io_info->use_select_io) {
/* Only perform I/O if not performing multi dataset I/O with selection
* I/O, otherwise the higher level will handle it after all datasets
if (io_info->use_select_io == H5D_SELECTION_IO_MODE_ON) {
/* Only perform I/O if not performing multi dataset I/O or type conversion,
* otherwise the higher level will handle it after all datasets
* have been processed */
if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) {
size_t dst_type_size = dinfo->type_info.dst_type_size;
@ -841,10 +854,17 @@ H5D__contig_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
io_info->addrs[io_info->pieces_added] = dinfo->store->contig.dset_addr;
io_info->element_sizes[io_info->pieces_added] = dinfo->type_info.src_type_size;
io_info->rbufs[io_info->pieces_added] = dinfo->buf.vp;
if (io_info->sel_pieces)
io_info->sel_pieces[io_info->pieces_added] = dinfo->layout_io_info.contig_piece_info;
io_info->pieces_added++;
}
}
} /* end if */
#ifdef H5_HAVE_PARALLEL
/* Report that collective contiguous I/O was used */
io_info->actual_io_mode |= H5D_MPIO_CONTIGUOUS_COLLECTIVE;
#endif /* H5_HAVE_PARALLEL */
} /* end if */
else
/* Read data through legacy (non-selection I/O) pathway */
if ((dinfo->io_ops.single_read)(io_info, dinfo) < 0)
@ -880,9 +900,9 @@ H5D__contig_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
HDassert(dinfo->mem_space);
HDassert(dinfo->file_space);
if (io_info->use_select_io) {
/* Only perform I/O if not performing multi dataset I/O with selection
* I/O, otherwise the higher level will handle it after all datasets
if (io_info->use_select_io == H5D_SELECTION_IO_MODE_ON) {
/* Only perform I/O if not performing multi dataset I/O or type conversion,
* otherwise the higher level will handle it after all datasets
* have been processed */
if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) {
size_t dst_type_size = dinfo->type_info.dst_type_size;
@ -911,10 +931,17 @@ H5D__contig_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
io_info->addrs[io_info->pieces_added] = dinfo->store->contig.dset_addr;
io_info->element_sizes[io_info->pieces_added] = dinfo->type_info.dst_type_size;
io_info->wbufs[io_info->pieces_added] = dinfo->buf.cvp;
if (io_info->sel_pieces)
io_info->sel_pieces[io_info->pieces_added] = dinfo->layout_io_info.contig_piece_info;
io_info->pieces_added++;
}
}
} /* end if */
#ifdef H5_HAVE_PARALLEL
/* Report that collective contiguous I/O was used */
io_info->actual_io_mode |= H5D_MPIO_CONTIGUOUS_COLLECTIVE;
#endif /* H5_HAVE_PARALLEL */
} /* end if */
else
/* Write data through legacy (non-selection I/O) pathway */
if ((dinfo->io_ops.single_write)(io_info, dinfo) < 0)

View File

@ -213,7 +213,8 @@ H5D__efl_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
H5MM_memcpy(&dinfo->store->efl, &(dinfo->dset->shared->dcpl_cache.efl), sizeof(H5O_efl_t));
/* Disable selection I/O */
io_info->use_select_io = FALSE;
io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF;
io_info->no_selection_io_cause |= H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__efl_io_init() */

View File

@ -43,14 +43,16 @@
/********************/
/* 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);
static herr_t H5D__typeinfo_init_phase2(H5D_io_info_t *io_info);
static herr_t H5D__typeinfo_init_phase3(H5D_io_info_t *io_info);
#ifdef H5_HAVE_PARALLEL
static herr_t H5D__ioinfo_adjust(H5D_io_info_t *io_info);
#endif /* H5_HAVE_PARALLEL */
static herr_t H5D__typeinfo_term(H5D_io_info_t *io_info, size_t type_info_init);
static herr_t H5D__typeinfo_term(H5D_io_info_t *io_info);
/*********************/
/* Package Variables */
@ -77,7 +79,6 @@ herr_t
H5D__read(size_t count, H5D_dset_io_info_t *dset_info)
{
H5D_io_info_t io_info; /* Dataset I/O info for multi dsets */
size_t type_info_init = 0; /* Number of datatype info structs that have been initialized */
H5S_t *orig_mem_space_local; /* Local buffer for orig_mem_space */
H5S_t **orig_mem_space = NULL; /* If not NULL, ptr to an array of dataspaces */
/* containing the original memory spaces contained */
@ -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)
@ -148,7 +148,6 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info)
/* Set up datatype info for operation */
if (H5D__typeinfo_init(&io_info, &(dset_info[i]), dset_info[i].mem_type_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info")
type_info_init++;
/* Make certain that the number of elements in each selection is the same, and cache nelmts in
* dset_info */
@ -285,7 +284,6 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info)
}
} /* end of for loop */
HDassert(type_info_init == count);
HDassert(io_op_init + io_skipped == count);
/* If no datasets have I/O, we're done */
@ -297,10 +295,17 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info (second phase)")
#ifdef H5_HAVE_PARALLEL
/* Adjust I/O info for any parallel I/O */
/* Adjust I/O info for any parallel or selection I/O */
if (H5D__ioinfo_adjust(&io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to adjust I/O info for parallel I/O")
#endif /*H5_HAVE_PARALLEL*/
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
"unable to adjust I/O info for parallel or selection I/O")
#endif /* H5_HAVE_PARALLEL */
/* Perform third phase of type info initialization */
if (H5D__typeinfo_init_phase3(&io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info (third phase)")
H5CX_set_no_selection_io_cause(io_info.no_selection_io_cause);
/* If multi dataset I/O callback is not provided, perform read IO via
* single-dset path with looping */
@ -339,6 +344,7 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info)
else {
haddr_t prev_tag = HADDR_UNDEF;
/* Allocate selection I/O parameter arrays if necessary */
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info) && io_info.piece_count > 0) {
if (NULL == (io_info.mem_spaces = H5MM_malloc(io_info.piece_count * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
@ -354,6 +360,11 @@ 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.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,
"unable to allocate array of selected pieces")
}
/* Loop with serial & single-dset read IO path */
@ -373,15 +384,39 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info)
H5AC_tag(prev_tag, NULL);
}
/* Make final multi dataset selection I/O call if we are using both
* features - in this case the multi_read callbacks did not perform the
* actual I/O */
H5_CHECK_OVERFLOW(io_info.pieces_added, size_t, uint32_t)
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info))
if (H5F_shared_select_read(io_info.f_sh, H5FD_MEM_DRAW, (uint32_t)io_info.pieces_added,
io_info.mem_spaces, io_info.file_spaces, io_info.addrs,
io_info.element_sizes, io_info.rbufs) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "selection read failed")
/* Make final selection I/O call if the multi_read callbacks did not perform the actual I/O
* (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.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")
}
else {
/* Call selection I/O directly */
H5_CHECK_OVERFLOW(io_info.pieces_added, size_t, uint32_t)
if (H5F_shared_select_read(io_info.f_sh, H5FD_MEM_DRAW, (uint32_t)io_info.pieces_added,
io_info.mem_spaces, io_info.file_spaces, io_info.addrs,
io_info.element_sizes, io_info.rbufs) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "selection read failed")
}
}
#ifdef H5_HAVE_PARALLEL
/* Report the actual I/O mode to the application if appropriate */
if (io_info.using_mpi_vfd) {
H5FD_mpio_xfer_t xfer_mode; /* Parallel transfer for this request */
/* Get the parallel I/O transfer mode */
if (H5CX_get_io_xfer_mode(&xfer_mode) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get MPI-I/O transfer mode")
/* Only report the collective I/O mode if we're actually performing collective I/O */
if (xfer_mode == H5FD_MPIO_COLLECTIVE)
H5CX_set_mpio_actual_io_mode(io_info.actual_io_mode);
}
#endif /* H5_HAVE_PARALLEL */
}
done:
@ -392,7 +427,7 @@ done:
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down I/O op info")
/* Shut down datatype info for operation */
if (H5D__typeinfo_term(&io_info, type_info_init) < 0)
if (H5D__typeinfo_term(&io_info) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down type info")
/* Discard projected mem spaces and restore originals */
@ -443,7 +478,6 @@ herr_t
H5D__write(size_t count, H5D_dset_io_info_t *dset_info)
{
H5D_io_info_t io_info; /* Dataset I/O info for multi dsets */
size_t type_info_init = 0; /* Number of datatype info structs that have been initialized */
H5S_t *orig_mem_space_local; /* Local buffer for orig_mem_space */
H5S_t **orig_mem_space = NULL; /* If not NULL, ptr to an array of dataspaces */
/* containing the original memory spaces contained */
@ -471,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)
@ -509,9 +542,8 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info)
/* Set up datatype info for operation */
if (H5D__typeinfo_init(&io_info, &(dset_info[i]), dset_info[i].mem_type_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info")
type_info_init++;
/* Various MPI based checks */
/* Various MPI based checks */
#ifdef H5_HAVE_PARALLEL
if (H5F_HAS_FEATURE(dset_info[i].dset->oloc.file, H5FD_FEAT_HAS_MPI)) {
/* If MPI based VFD is used, no VL or region reference datatype support yet. */
@ -660,7 +692,6 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info)
H5AC_tag(prev_tag, NULL);
} /* end of for loop */
HDassert(type_info_init == count);
HDassert(io_op_init == count);
/* Perform second phase of type info initialization */
@ -668,10 +699,17 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info (second phase)")
#ifdef H5_HAVE_PARALLEL
/* Adjust I/O info for any parallel I/O */
/* Adjust I/O info for any parallel or selection I/O */
if (H5D__ioinfo_adjust(&io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to adjust I/O info for parallel I/O")
#endif /*H5_HAVE_PARALLEL*/
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
"unable to adjust I/O info for parallel or selection I/O")
#endif /* H5_HAVE_PARALLEL */
/* Perform third phase of type info initialization */
if (H5D__typeinfo_init_phase3(&io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info (third phase)")
H5CX_set_no_selection_io_cause(io_info.no_selection_io_cause);
/* If multi dataset I/O callback is not provided, perform write IO via
* single-dset path with looping */
@ -710,6 +748,7 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info)
else {
haddr_t prev_tag = HADDR_UNDEF;
/* Allocate selection I/O parameter arrays if necessary */
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info) && io_info.piece_count > 0) {
if (NULL == (io_info.mem_spaces = H5MM_malloc(io_info.piece_count * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
@ -724,7 +763,12 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info)
"memory allocation failed for element size list")
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 read buffer list")
"memory allocation failed for write buffer list")
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,
"unable to allocate array of selected pieces")
}
/* loop with serial & single-dset write IO path */
@ -742,15 +786,45 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info)
H5AC_tag(prev_tag, NULL);
}
/* Make final multi dataset selection I/O call if we are using both
* features - in this case the multi_write callbacks did not perform the
* actual I/O */
H5_CHECK_OVERFLOW(io_info.pieces_added, size_t, uint32_t)
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info))
if (H5F_shared_select_write(io_info.f_sh, H5FD_MEM_DRAW, (uint32_t)io_info.pieces_added,
io_info.mem_spaces, io_info.file_spaces, io_info.addrs,
io_info.element_sizes, io_info.wbufs) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "selection write failed")
/* Make final selection I/O call if the multi_write callbacks did not perform the actual I/O
* (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.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")
}
else {
/* Call selection I/O directly */
H5_CHECK_OVERFLOW(io_info.pieces_added, size_t, uint32_t)
if (H5F_shared_select_write(io_info.f_sh, H5FD_MEM_DRAW, (uint32_t)io_info.pieces_added,
io_info.mem_spaces, io_info.file_spaces, io_info.addrs,
io_info.element_sizes, io_info.wbufs) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "selection write failed")
}
}
#ifdef H5_HAVE_PARALLEL
/* Report the actual I/O mode to the application if appropriate */
if (io_info.using_mpi_vfd) {
H5FD_mpio_xfer_t xfer_mode; /* Parallel transfer for this request */
/* Get the parallel I/O transfer mode */
if (H5CX_get_io_xfer_mode(&xfer_mode) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get MPI-I/O transfer mode")
/* Only report the collective I/O mode if we're actually performing collective I/O */
if (xfer_mode == H5FD_MPIO_COLLECTIVE) {
H5CX_set_mpio_actual_io_mode(io_info.actual_io_mode);
/* If we did selection I/O, report that we used "link chunk" mode, since that's the most
* analogous to what selection I/O does */
if (io_info.use_select_io == H5D_SELECTION_IO_MODE_ON)
H5CX_set_mpio_actual_chunk_opt(H5D_MPIO_LINK_CHUNK);
}
}
#endif /* H5_HAVE_PARALLEL */
}
#ifdef OLD_WAY
@ -781,7 +855,7 @@ done:
}
/* Shut down datatype info for operation */
if (H5D__typeinfo_term(&io_info, type_info_init) < 0)
if (H5D__typeinfo_term(&io_info) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down type info")
/* Discard projected mem spaces and restore originals */
@ -819,8 +893,11 @@ done:
*-------------------------------------------------------------------------
*/
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;
FUNC_ENTER_PACKAGE_NOERR
/* check args */
@ -833,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. */
@ -842,16 +920,31 @@ H5D__ioinfo_init(size_t count, H5D_dset_io_info_t *dset_info, H5D_io_info_t *io_
/* Use provided dset_info */
io_info->dsets_info = dset_info;
/* Start with selection I/O on if the global is on, layout callback will
* turn it off if appropriate */
io_info->use_select_io = H5_use_selection_io_g;
/* Start with selection I/O mode from property list. If enabled, layout callback will turn it off if it
* is not supported by the layout. Handling of H5D_SELECTION_IO_MODE_AUTO occurs in H5D__ioinfo_adjust.
*/
H5CX_get_selection_io_mode(&selection_io_mode);
io_info->use_select_io = selection_io_mode;
/* 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_SEL_IO_DISABLE_BY_API;
#ifdef H5_HAVE_PARALLEL
/* Determine if the file was opened with an MPI VFD */
if (count > 0)
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 */
if (op_type == H5D_IO_OP_READ)
/* Always on for read (modulo other restrictions that are handled in layout callbacks) */
io_info->may_use_in_place_tconv = TRUE;
else
/* Only enable in-place type conversion if we're allowed to modify the write buffer */
H5CX_get_modify_write_buf(&io_info->may_use_in_place_tconv);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__ioinfo_init() */
@ -998,9 +1091,9 @@ H5D__typeinfo_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, hid_t
/* Check if the datatypes are compound subsets of one another */
type_info->cmpd_subset = H5T_path_compound_subset(type_info->tpath);
/* Update io_info->max_type_size */
io_info->max_type_size =
MAX3(io_info->max_type_size, type_info->src_type_size, type_info->dst_type_size);
/* Update io_info->max_tconv_type_size */
io_info->max_tconv_type_size =
MAX3(io_info->max_tconv_type_size, type_info->src_type_size, type_info->dst_type_size);
/* Check if we need a background buffer */
if ((io_info->op_type == H5D_IO_OP_WRITE) && H5T_detect_class(dset->shared->type, H5T_VLEN, FALSE))
@ -1025,8 +1118,12 @@ done:
/*-------------------------------------------------------------------------
* Function: H5D__typeinfo_init_phase2
*
* Purpose: Finish initializing type info for all datasets after
* calculating the max type size across all datasets.
* Purpose: Continue initializing type info for all datasets after
* calculating the max type size across all datasets, and
* before final determination of collective/independent in
* H5D__ioinfo_adjust(). Currently just checks to see if
* selection I/O can be used with type conversion, and sets
* no_collective_cause flags related to selection I/O.
*
* Return: Non-negative on success/Negative on failure
*
@ -1042,89 +1139,65 @@ H5D__typeinfo_init_phase2(H5D_io_info_t *io_info)
/* check args */
HDassert(io_info);
/* Check if we need to allocate a shared type conversion buffer */
if (io_info->max_type_size) {
void *tconv_buf; /* Temporary conversion buffer pointer */
void *bkgr_buf; /* Background conversion buffer pointer */
/* If selection I/O mode is default (auto), enable it here if the VFD supports it (it will be turned off
* later if something else conflicts), otherwise disable it. If we're using the MPIO VFD, the automatic
* selection will happen in H5D__mpio_opt_possible() inside H5D__ioinfo_adjust(). */
#ifdef H5_HAVE_PARALLEL
if (!io_info->using_mpi_vfd)
#endif /* H5_HAVE_PARALLEL */
if (io_info->use_select_io == H5D_SELECTION_IO_MODE_DEFAULT) {
if (H5F_has_vector_select_io(io_info->dsets_info[0].dset->oloc.file,
io_info->op_type == H5D_IO_OP_WRITE))
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_SEL_IO_DEFAULT_OFF;
}
}
/* If we're doing type conversion and we might be doing selection I/O, check if the buffers are large
* enough to handle the whole I/O */
if (io_info->max_tconv_type_size && io_info->use_select_io != H5D_SELECTION_IO_MODE_OFF) {
size_t max_temp_buf; /* Maximum temporary buffer size */
size_t target_size; /* Desired buffer size */
size_t i; /* Local index variable */
/* Get info from API context */
if (H5CX_get_max_temp_buf(&max_temp_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve max. temp. buf size")
if (H5CX_get_tconv_buf(&tconv_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve temp. conversion buffer pointer")
if (H5CX_get_bkgr_buf(&bkgr_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve background conversion buffer pointer")
/* Collective I/O, conversion buffer must be large enough for entire I/O (for now) */
/* Set up datatype conversion/background buffers */
target_size = max_temp_buf;
/* If the buffer is too small to hold even one element (in the dataset with the largest , try to make
* it bigger */
if (target_size < io_info->max_type_size) {
hbool_t default_buffer_info; /* Whether the buffer information are the defaults */
/* Detect if we have all default settings for buffers */
default_buffer_info =
(hbool_t)((H5D_TEMP_BUF_SIZE == max_temp_buf) && (NULL == tconv_buf) && (NULL == bkgr_buf));
/* Check if we are using the default buffer info */
if (default_buffer_info)
/* OK to get bigger for library default settings */
target_size = io_info->max_type_size;
else
/* Don't get bigger than the application has requested */
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
} /* end if */
/* Get a temporary buffer for type conversion unless the app has already
* supplied one through the xfer properties. Instead of allocating a
* buffer which is the exact size, we allocate the target size. This
* buffer is shared among all datasets in the operation, unlike for the
* background buffer, where each dataset gets its own. */
if (NULL == (io_info->tconv_buf = (uint8_t *)tconv_buf)) {
/* Allocate temporary buffer */
if (NULL == (io_info->tconv_buf = H5FL_BLK_MALLOC(type_conv, target_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
io_info->tconv_buf_allocated = TRUE;
} /* end if */
/* Don't use API provided background buffer if there's more than one dataset, since each
* dataset needs its own */
if (io_info->count > 1)
bkgr_buf = NULL;
/* Iterate over datasets */
/* 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;
/* Compute the number of elements that will fit into buffer */
type_info->request_nelmts = target_size / 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;
/* Sanity check elements in temporary buffer */
if (type_info->request_nelmts == 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
/* 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;
}
}
/* Allocate background buffer if necessary */
if (type_info->need_bkg && NULL == (type_info->bkg_buf = (uint8_t *)bkgr_buf)) {
size_t bkg_size; /* Desired background buffer size */
/* Get max temp buffer size from API context */
if (H5CX_get_max_temp_buf(&max_temp_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve max. temp. buf size")
/* Compute the background buffer size */
/* (don't try to use buffers smaller than the default size) */
bkg_size = type_info->request_nelmts * type_info->dst_type_size;
if (bkg_size < max_temp_buf)
bkg_size = max_temp_buf;
/* Allocate background buffer */
/* (Need calloc()-like call since memory needs to be initialized) */
if (NULL == (type_info->bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
"memory allocation failed for background conversion")
type_info->bkg_buf_allocated = TRUE;
} /* end if */
/* 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_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;
}
}
@ -1133,15 +1206,13 @@ done:
} /* end H5D__typeinfo_init_phase2() */
#ifdef H5_HAVE_PARALLEL
/*-------------------------------------------------------------------------
* Function: H5D__ioinfo_adjust
* Function: H5D__ioinfo_adjust
*
* Purpose: Adjust operation's I/O info for any parallel I/O
* Purpose: Adjust operation's I/O info for any parallel I/O, also
* handle decision on selection I/O even in serial case
*
* This was derived from H5D__ioinfo_adjust for multi-dset work.
*
* Return: Non-negative on success/Negative on failure
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@ -1193,7 +1264,7 @@ H5D__ioinfo_adjust(H5D_io_info_t *io_info)
* selection I/O is to be used - in this case the file driver will
* handle collective I/O */
/* Check for selection/vector support in file driver? -NAF */
if (!io_info->use_select_io) {
if (io_info->use_select_io == H5D_SELECTION_IO_MODE_OFF) {
io_info->md_io_ops.multi_read_md = H5D__collective_read;
io_info->md_io_ops.multi_write_md = H5D__collective_write;
io_info->md_io_ops.single_read_md = H5D__mpio_select_read;
@ -1269,6 +1340,137 @@ done:
} /* end H5D__ioinfo_adjust() */
#endif /* H5_HAVE_PARALLEL */
/*-------------------------------------------------------------------------
* Function: H5D__typeinfo_init_phase3
*
* Purpose: Finish initializing type info for all datasets after
* calculating the max type size across all datasets. And
* after final collective/independent determination in
* H5D__ioinfo_adjust().
*
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__typeinfo_init_phase3(H5D_io_info_t *io_info)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* check args */
HDassert(io_info);
/* Check if we need to allocate a shared type conversion buffer */
if (io_info->max_tconv_type_size) {
void *tconv_buf; /* Temporary conversion buffer pointer */
void *bkgr_buf; /* Background conversion buffer pointer */
/* Get provided buffers from API context */
if (H5CX_get_tconv_buf(&tconv_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve temp. conversion buffer pointer")
if (H5CX_get_bkgr_buf(&bkgr_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve background conversion buffer pointer")
/* Check if we're doing selection I/O */
if (io_info->use_select_io == H5D_SELECTION_IO_MODE_ON) {
/* Selection I/O, conversion buffers must be large enough for entire I/O (for now) */
/* Allocate global type conversion buffer (if any, could be none if datasets in this
* I/O have 0 elements selected) */
/* Allocating large buffers here will blow out all other type conversion buffers
* on the free list. Should we change this to a regular malloc? Would require
* keeping track of which version of free() to call. -NAF */
if (io_info->tconv_buf_size > 0) {
if (NULL == (io_info->tconv_buf = H5FL_BLK_MALLOC(type_conv, io_info->tconv_buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
"memory allocation failed for type conversion")
io_info->tconv_buf_allocated = TRUE;
}
/* Allocate global background buffer (if any) */
if (io_info->bkg_buf_size > 0) {
if (NULL == (io_info->bkg_buf = H5FL_BLK_MALLOC(type_conv, io_info->bkg_buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
"memory allocation failed for type conversion")
io_info->bkg_buf_allocated = TRUE;
}
}
else {
/* No selection I/O, only need to make sure it's big enough for one element */
size_t max_temp_buf; /* Maximum temporary buffer size */
size_t target_size; /* Desired buffer size */
size_t i;
/* Make sure selection I/O is disabled (DEFAULT should have been handled by now) */
HDassert(io_info->use_select_io == H5D_SELECTION_IO_MODE_OFF);
/* Get max buffer size from API context */
if (H5CX_get_max_temp_buf(&max_temp_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve max. temp. buf size")
/* Set up datatype conversion/background buffers */
target_size = max_temp_buf;
/* If the buffer is too small to hold even one element (in the dataset with the largest , try to
* make it bigger */
if (target_size < io_info->max_tconv_type_size) {
hbool_t default_buffer_info; /* Whether the buffer information are the defaults */
/* Detect if we have all default settings for buffers */
default_buffer_info = (hbool_t)((H5D_TEMP_BUF_SIZE == max_temp_buf) && (NULL == tconv_buf) &&
(NULL == bkgr_buf));
/* Check if we are using the default buffer info */
if (default_buffer_info)
/* OK to get bigger for library default settings */
target_size = io_info->max_tconv_type_size;
else
/* Don't get bigger than the application has requested */
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
} /* end if */
/* Get a temporary buffer for type conversion unless the app has already
* supplied one through the xfer properties. Instead of allocating a
* buffer which is the exact size, we allocate the target size. This
* buffer is shared among all datasets in the operation. */
if (NULL == (io_info->tconv_buf = (uint8_t *)tconv_buf)) {
/* Allocate temporary buffer */
if (NULL == (io_info->tconv_buf = H5FL_BLK_MALLOC(type_conv, target_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
"memory allocation failed for type conversion")
io_info->tconv_buf_allocated = TRUE;
} /* end if */
/* Iterate over datasets */
for (i = 0; i < io_info->count; i++) {
H5D_type_info_t *type_info = &io_info->dsets_info[i].type_info;
/* Compute the number of elements that will fit into buffer */
type_info->request_nelmts =
target_size / MAX(type_info->src_type_size, type_info->dst_type_size);
/* Check if we need a background buffer and one hasn't been allocated yet */
if (type_info->need_bkg && (NULL == io_info->bkg_buf) &&
(NULL == (io_info->bkg_buf = (uint8_t *)bkgr_buf))) {
/* Allocate background buffer with the same size as the type conversion buffer. We can do
* this since the number of elements that fit in the type conversion buffer will never be
* larger than the number that could fit in a background buffer of equal size, since the
* tconv element size is max(src, dst) and the bkg element size is dst */
if (NULL == (io_info->bkg_buf = H5FL_BLK_MALLOC(type_conv, target_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
"memory allocation failed for background conversion")
io_info->bkg_buf_allocated = TRUE;
}
}
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__typeinfo_init_phase3() */
/*-------------------------------------------------------------------------
* Function: H5D__typeinfo_term
*
@ -1282,10 +1484,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__typeinfo_term(H5D_io_info_t *io_info, size_t type_info_init)
H5D__typeinfo_term(H5D_io_info_t *io_info)
{
size_t i;
FUNC_ENTER_PACKAGE_NOERR
/* Check for releasing datatype conversion & background buffers */
@ -1293,11 +1493,10 @@ H5D__typeinfo_term(H5D_io_info_t *io_info, size_t type_info_init)
HDassert(io_info->tconv_buf);
(void)H5FL_BLK_FREE(type_conv, io_info->tconv_buf);
} /* end if */
for (i = 0; i < type_info_init; i++)
if (io_info->dsets_info[i].type_info.bkg_buf_allocated) {
HDassert(io_info->dsets_info[i].type_info.bkg_buf);
(void)H5FL_BLK_FREE(type_conv, io_info->dsets_info[i].type_info.bkg_buf);
} /* end if */
if (io_info->bkg_buf_allocated) {
HDassert(io_info->bkg_buf);
(void)H5FL_BLK_FREE(type_conv, io_info->bkg_buf);
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__typeinfo_term() */

View File

@ -626,13 +626,17 @@ H5D__mpio_opt_possible(H5D_io_info_t *io_info)
if (!H5FD_mpi_opt_types_g)
local_cause[0] |= H5D_MPIO_MPI_OPT_TYPES_ENV_VAR_DISABLED;
/* Don't allow collective operations if datatype conversions need to happen */
if (!type_info->is_conv_noop)
local_cause[0] |= H5D_MPIO_DATATYPE_CONVERSION;
/* Datatype conversions and transformations are allowed with selection I/O. If the selection I/O mode
* is auto (default), disable collective for now and re-enable later if we can */
if (io_info->use_select_io != H5D_SELECTION_IO_MODE_ON) {
/* Don't allow collective operations if datatype conversions need to happen */
if (!type_info->is_conv_noop)
local_cause[0] |= H5D_MPIO_DATATYPE_CONVERSION;
/* Don't allow collective operations if data transform operations should occur */
if (!type_info->is_xform_noop)
local_cause[0] |= H5D_MPIO_DATA_TRANSFORMS;
/* Don't allow collective operations if data transform operations should occur */
if (!type_info->is_xform_noop)
local_cause[0] |= H5D_MPIO_DATA_TRANSFORMS;
}
/* Check whether these are both simple or scalar dataspaces */
if (!((H5S_SIMPLE == H5S_GET_EXTENT_TYPE(mem_space) ||
@ -662,6 +666,15 @@ H5D__mpio_opt_possible(H5D_io_info_t *io_info)
local_cause[0] |= H5D_MPIO_PARALLEL_FILTERED_WRITES_DISABLED;
#endif
/* Check if we would be able to perform collective if we could use selection I/O. If so add reasons
* for not using selection I/O to local_cause[0] */
if ((io_info->use_select_io == H5D_SELECTION_IO_MODE_OFF) && local_cause[0] &&
!(local_cause[0] &
~((unsigned)H5D_MPIO_DATATYPE_CONVERSION | (unsigned)H5D_MPIO_DATA_TRANSFORMS))) {
HDassert(io_info->no_selection_io_cause & H5D_MPIO_NO_SELECTION_IO_CAUSES);
local_cause[0] |= H5D_MPIO_NO_SELECTION_IO;
}
/* Check if we are able to do a MPI_Bcast of the data from one rank
* instead of having all the processes involved in the collective I/O call.
*/
@ -722,6 +735,25 @@ H5D__mpio_opt_possible(H5D_io_info_t *io_info)
HMPI_GOTO_ERROR(FAIL, "MPI_Allreduce failed", mpi_code)
} /* end else */
/* If the selection I/O mode is default (auto), decide here whether it should be on or off */
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))) {
HDassert(!(local_cause[0] &
~((unsigned)H5D_MPIO_DATATYPE_CONVERSION | (unsigned)H5D_MPIO_DATA_TRANSFORMS)));
local_cause[0] = 0;
global_cause[0] = 0;
io_info->use_select_io = H5D_SELECTION_IO_MODE_ON;
}
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_SEL_IO_DEFAULT_OFF;
}
}
/* Set the local & global values of no-collective-cause in the API context */
H5CX_set_mpio_local_no_coll_cause(local_cause[0]);
H5CX_set_mpio_global_no_coll_cause(global_cause[0]);
@ -774,7 +806,7 @@ H5D__mpio_get_no_coll_cause_strings(char *local_cause, size_t local_cause_len, c
* Use compile-time assertion so this routine is updated
* when any new "no collective cause" values are added
*/
HDcompile_assert(H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE == (H5D_mpio_no_collective_cause_t)256);
HDcompile_assert(H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE == (H5D_mpio_no_collective_cause_t)0x200);
/* Initialize output buffers */
if (local_cause)
@ -827,6 +859,11 @@ H5D__mpio_get_no_coll_cause_strings(char *local_cause, size_t local_cause_len, c
case H5D_MPIO_ERROR_WHILE_CHECKING_COLLECTIVE_POSSIBLE:
cause_str = "an error occurred while checking if collective I/O was possible";
break;
case H5D_MPIO_NO_SELECTION_IO:
cause_str = "collective I/O may be supported by selection or vector I/O but that feature was "
"not possible (see causes via H5Pget_no_selection_io_cause())";
break;
case H5D_MPIO_COLLECTIVE:
case H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE:
default:
@ -1438,13 +1475,8 @@ H5D__link_piece_collective_io(H5D_io_info_t *io_info, int H5_ATTR_UNUSED mpi_ran
HDassert(io_info->dsets_info[i].dset->shared->dcpl_cache.pline.nused == 0);
if (io_info->dsets_info[i].layout->type == H5D_CHUNKED)
actual_io_mode |= H5D_MPIO_CHUNK_COLLECTIVE;
else if (io_info->dsets_info[i].layout->type == H5D_CONTIGUOUS) {
else if (io_info->dsets_info[i].layout->type == H5D_CONTIGUOUS)
actual_io_mode |= H5D_MPIO_CONTIGUOUS_COLLECTIVE;
/* if only single-dset */
if (1 == io_info->count)
actual_chunk_opt_mode = H5D_MPIO_NO_CHUNK_OPTIMIZATION;
}
else
HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout")
}

View File

@ -67,7 +67,49 @@
#define H5D_BT2_MERGE_PERC 40
/* 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 || (IO_INFO)->count == 1)
#define H5D_LAYOUT_CB_PERFORM_IO(IO_INFO) \
(((IO_INFO)->use_select_io == H5D_SELECTION_IO_MODE_OFF) || \
((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 to 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 */
@ -83,15 +125,13 @@ typedef struct H5D_type_info_t {
hid_t dst_type_id; /* Destination datatype ID */
/* Computed/derived values */
size_t src_type_size; /* Size of source type */
size_t dst_type_size; /* Size of destination type */
hbool_t is_conv_noop; /* Whether the type conversion is a NOOP */
hbool_t is_xform_noop; /* Whether the data transform is a NOOP */
const H5T_subset_info_t *cmpd_subset; /* Info related to the compound subset conversion functions */
H5T_bkg_t need_bkg; /* Type of background buf needed */
size_t request_nelmts; /* Requested strip mine */
uint8_t *bkg_buf; /* Background buffer */
hbool_t bkg_buf_allocated; /* Whether the background buffer was allocated */
size_t src_type_size; /* Size of source type */
size_t dst_type_size; /* Size of destination type */
hbool_t is_conv_noop; /* Whether the type conversion is a NOOP */
hbool_t is_xform_noop; /* Whether the data transform is a NOOP */
const H5T_subset_info_t *cmpd_subset; /* Info related to the compound subset conversion functions */
H5T_bkg_t need_bkg; /* Type of background buf needed */
size_t request_nelmts; /* Requested strip mine */
} H5D_type_info_t;
/* Forward declaration of structs used below */
@ -209,9 +249,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;
@ -263,10 +305,23 @@ typedef struct H5D_io_info_t {
const void **wbufs; /* Array of write buffers */
haddr_t store_faddr; /* lowest file addr for read/write */
H5_flexible_const_ptr_t base_maddr; /* starting mem address */
hbool_t use_select_io; /* Whether to use selection I/O */
H5D_selection_io_mode_t use_select_io; /* Whether to use selection I/O */
uint8_t *tconv_buf; /* Datatype conv buffer */
hbool_t tconv_buf_allocated; /* Whether the type conversion buffer was allocated */
size_t max_type_size; /* Largest of all source and destination type sizes */
size_t tconv_buf_size; /* Size of type conversion buffer */
uint8_t *bkg_buf; /* Background buffer */
hbool_t bkg_buf_allocated; /* Whether the background buffer was allocated */
size_t bkg_buf_size; /* Size of background buffer */
size_t max_tconv_type_size; /* Largest of all source and destination type sizes involved in type
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 */
unsigned no_selection_io_cause; /* "No selection I/O cause" flags */
} H5D_io_info_t;
/* Created to pass both at once for callback func */
@ -620,12 +675,14 @@ H5_DLL herr_t H5D__select_write(const H5D_io_info_t *io_info, const H5D_dset_io_
H5_DLL herr_t H5D_select_io_mem(void *dst_buf, H5S_t *dst_space, const void *src_buf, H5S_t *src_space,
size_t elmt_size, size_t nelmts);
/* Functions that perform scatter-gather serial I/O operations */
/* Functions that perform scatter-gather I/O operations */
H5_DLL herr_t H5D__scatter_mem(const void *_tscat_buf, H5S_sel_iter_t *iter, size_t nelmts, void *_buf);
H5_DLL size_t H5D__gather_mem(const void *_buf, H5S_sel_iter_t *iter, size_t nelmts,
void *_tgath_buf /*out*/);
H5_DLL herr_t H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info);
H5_DLL herr_t H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info);
H5_DLL herr_t H5D__scatgath_read_select(H5D_io_info_t *io_info);
H5_DLL herr_t H5D__scatgath_write_select(H5D_io_info_t *io_info);
/* Functions that operate on dataset's layout information */
H5_DLL herr_t H5D__layout_set_io_ops(const H5D_t *dataset);

View File

@ -78,12 +78,15 @@
#define H5D_MPIO_LOCAL_NO_COLLECTIVE_CAUSE_NAME \
"local_no_collective_cause" /* cause of broken collective I/O in each process */
#define H5D_MPIO_GLOBAL_NO_COLLECTIVE_CAUSE_NAME \
"global_no_collective_cause" /* cause of broken collective I/O in all processes */
#define H5D_XFER_EDC_NAME "err_detect" /* EDC */
#define H5D_XFER_FILTER_CB_NAME "filter_cb" /* Filter callback function */
#define H5D_XFER_CONV_CB_NAME "type_conv_cb" /* Type conversion callback function */
#define H5D_XFER_XFORM_NAME "data_transform" /* Data transform */
#define H5D_XFER_DSET_IO_SEL_NAME "dset_io_selection" /* Dataset I/O selection */
"global_no_collective_cause" /* cause of broken collective I/O in all processes */
#define H5D_XFER_EDC_NAME "err_detect" /* EDC */
#define H5D_XFER_FILTER_CB_NAME "filter_cb" /* Filter callback function */
#define H5D_XFER_CONV_CB_NAME "type_conv_cb" /* Type conversion callback function */
#define H5D_XFER_XFORM_NAME "data_transform" /* Data transform */
#define H5D_XFER_DSET_IO_SEL_NAME "dset_io_selection" /* Dataset I/O selection */
#define H5D_XFER_SELECTION_IO_MODE_NAME "selection_io_mode" /* Selection I/O mode */
#define H5D_XFER_NO_SELECTION_IO_CAUSE_NAME "no_selection_io_cause" /* Cause for no selection I/O */
#define H5D_XFER_MODIFY_WRITE_BUF_NAME "modify_write_buf" /* Modify write buffers */
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
/* Collective chunk instrumentation properties */
#define H5D_XFER_COLL_CHUNK_LINK_HARD_NAME "coll_chunk_link_hard"

View File

@ -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 */
/******************/
@ -529,7 +534,7 @@ H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_
} /* end if */
else {
if (H5T_BKG_YES == dset_info->type_info.need_bkg) {
n = H5D__gather_mem(buf, bkg_iter, smine_nelmts, dset_info->type_info.bkg_buf /*out*/);
n = H5D__gather_mem(buf, bkg_iter, smine_nelmts, io_info->bkg_buf /*out*/);
if (n != smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "mem gather failed")
} /* end if */
@ -539,7 +544,7 @@ H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_
*/
if (H5T_convert(dset_info->type_info.tpath, dset_info->type_info.src_type_id,
dset_info->type_info.dst_type_id, smine_nelmts, (size_t)0, (size_t)0,
io_info->tconv_buf, dset_info->type_info.bkg_buf) < 0)
io_info->tconv_buf, io_info->bkg_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
/* Do the data transform after the conversion (since we're using type mem_type) */
@ -672,8 +677,7 @@ H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset
} /* end if */
else {
if (H5T_BKG_YES == dset_info->type_info.need_bkg) {
n = H5D__gather_file(io_info, dset_info, bkg_iter, smine_nelmts,
dset_info->type_info.bkg_buf /*out*/);
n = H5D__gather_file(io_info, dset_info, bkg_iter, smine_nelmts, io_info->bkg_buf /*out*/);
if (n != smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
} /* end if */
@ -697,7 +701,7 @@ H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset
*/
if (H5T_convert(dset_info->type_info.tpath, dset_info->type_info.src_type_id,
dset_info->type_info.dst_type_id, smine_nelmts, (size_t)0, (size_t)0,
io_info->tconv_buf, dset_info->type_info.bkg_buf) < 0)
io_info->tconv_buf, io_info->bkg_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
} /* end else */
@ -726,6 +730,559 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__scatgath_write() */
/*-------------------------------------------------------------------------
* Function: H5D__scatgath_read_select
*
* Purpose: Perform scatter/gather read from a list of dataset pieces
*
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
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 */
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
/* Sanity check */
HDassert(io_info);
HDassert(io_info->count > 0);
HDassert(io_info->mem_spaces || io_info->pieces_added == 0);
HDassert(io_info->file_spaces || io_info->pieces_added == 0);
HDassert(io_info->addrs || io_info->pieces_added == 0);
HDassert(io_info->element_sizes || io_info->pieces_added == 0);
HDassert(io_info->rbufs || io_info->pieces_added == 0);
/* Allocate list of buffers (within the tconv buf) */
if (NULL == (tmp_bufs = H5MM_malloc(io_info->pieces_added * sizeof(void *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for temporary buffer list")
/* Allocate the iterator */
if (NULL == (mem_iter = H5FL_MALLOC(H5S_sel_iter_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate memory iterator")
/* Allocate list of block memory spaces */
/*!FIXME delay doing this until we find the first mem space that is non-contiguous or doesn't start at 0
*/
if (NULL == (tmp_mem_spaces = H5MM_malloc(io_info->pieces_added * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for temporary memory space list")
/* Build read operation to tconv buffer */
for (i = 0; i < io_info->pieces_added; i++) {
H5D_dset_io_info_t *dset_info = io_info->sel_pieces[i]->dset_info;
HDassert(io_info->sel_pieces[i]->piece_points > 0);
/* Check if this piece is involved in type conversion */
if (dset_info->type_info.is_xform_noop && dset_info->type_info.is_conv_noop) {
/* No type conversion, just copy the mem space and buffer */
tmp_mem_spaces[i] = io_info->mem_spaces[i];
tmp_bufs[i] = io_info->rbufs[i];
}
else {
/* Create block memory space */
if (NULL ==
(tmp_mem_spaces[i] = H5S_create_simple(1, &io_info->sel_pieces[i]->piece_points, NULL))) {
HDmemset(&tmp_mem_spaces[i], 0, (io_info->pieces_added - i) * sizeof(tmp_mem_spaces[0]));
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "unable to create simple memory dataspace")
}
/* 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;
}
}
}
}
}
/* Read data from all pieces */
H5_CHECK_OVERFLOW(io_info->pieces_added, size_t, uint32_t)
if (H5F_shared_select_read(io_info->f_sh, H5FD_MEM_DRAW, (uint32_t)io_info->pieces_added, tmp_mem_spaces,
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 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++) {
H5D_dset_io_info_t *dset_info = io_info->sel_pieces[i]->dset_info;
HDassert(tmp_mem_spaces[i]);
/* Check if this piece is involved in type conversion */
if (tmp_mem_spaces[i] != io_info->mem_spaces[i]) {
H5_CHECK_OVERFLOW(io_info->sel_pieces[i]->piece_points, hsize_t, size_t);
/* 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 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.
*/
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 {
/* 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);
}
/*
* Perform datatype conversion.
*/
if (H5T_convert(dset_info->type_info.tpath, dset_info->type_info.src_type_id,
dset_info->type_info.dst_type_id,
(size_t)io_info->sel_pieces[i]->piece_points, (size_t)0, (size_t)0,
tmp_bufs[i], tmp_bkg_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
/* Do the data transform after the conversion (since we're using type mem_type) */
if (!dset_info->type_info.is_xform_noop) {
H5Z_data_xform_t *data_transform; /* Data transform info */
/* Retrieve info from API context */
if (H5CX_get_data_transform(&data_transform) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data transform info")
if (H5Z_xform_eval(data_transform, tmp_bufs[i],
(size_t)io_info->sel_pieces[i]->piece_points,
dset_info->type_info.mem_type) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "Error performing data transform")
}
/* 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 */
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;
}
}
done:
/* Release and free selection iterator */
if (mem_iter_init && H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
if (mem_iter)
mem_iter = H5FL_FREE(H5S_sel_iter_t, mem_iter);
/* Free tmp_bufs */
H5MM_free(tmp_bufs);
tmp_bufs = NULL;
/* Clear and free tmp_mem_spaces */
if (tmp_mem_spaces) {
for (i = 0; i < io_info->pieces_added; i++)
if (tmp_mem_spaces[i] != io_info->mem_spaces[i] && tmp_mem_spaces[i] &&
H5S_close(tmp_mem_spaces[i]) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "Can't close dataspace")
H5MM_free(tmp_mem_spaces);
tmp_mem_spaces = NULL;
}
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__scatgath_read_select() */
/*-------------------------------------------------------------------------
* Function: H5D__scatgath_write_select
*
* Purpose: Perform scatter/gather write to a list of dataset pieces.
*
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
herr_t
H5D__scatgath_write_select(H5D_io_info_t *io_info)
{
H5S_t **write_mem_spaces = NULL; /* Memory spaces to use for write to disk */
size_t spaces_added = 0; /* Number of spaces added to write_mem_spaces */
H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info */
hbool_t mem_iter_init = FALSE; /* Memory selection iteration info has been initialized */
const void **write_bufs = NULL; /* Buffers to use for write to disk */
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 */
H5S_t **bkg_mem_spaces = NULL; /* Array of memory spaces for read to background buffer */
H5S_t **bkg_file_spaces = NULL; /* Array of file spaces for read to background buffer */
haddr_t *bkg_addrs = NULL; /* Array of file addresses for read to background buffer */
size_t *bkg_element_sizes = NULL; /* Array of element sizes for read to background buffer */
void **bkg_bufs = NULL; /* Array background buffers for read of existing file contents */
size_t bkg_pieces = 0; /* Number of pieces that need to read the background data from disk */
size_t i; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(io_info);
HDassert(io_info->count > 0);
HDassert(io_info->mem_spaces || io_info->pieces_added == 0);
HDassert(io_info->file_spaces || io_info->pieces_added == 0);
HDassert(io_info->addrs || io_info->pieces_added == 0);
HDassert(io_info->element_sizes || io_info->pieces_added == 0);
HDassert(io_info->wbufs || io_info->pieces_added == 0);
/* Allocate list of buffers (within the tconv buf) */
if (NULL == (write_bufs = (const void **)H5MM_malloc(io_info->pieces_added * sizeof(const void *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for temporary buffer list")
/* Allocate the iterator */
if (NULL == (mem_iter = H5FL_MALLOC(H5S_sel_iter_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate memory iterator")
/* Allocate list of block memory spaces */
/*!FIXME delay doing this until we find the first mem space that is non-contiguous or doesn't start at 0
*/
if (NULL == (write_mem_spaces = H5MM_malloc(io_info->pieces_added * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for temporary memory space list")
/* Build operations to read data to background buffer and to write data */
for (i = 0; i < io_info->pieces_added; i++) {
H5D_dset_io_info_t *dset_info = io_info->sel_pieces[i]->dset_info;
HDassert(io_info->sel_pieces[i]->piece_points > 0);
/* Check if this piece is involved in type conversion */
if (dset_info->type_info.is_xform_noop && dset_info->type_info.is_conv_noop) {
/* No type conversion, just copy the mem space and buffer */
write_mem_spaces[i] = io_info->mem_spaces[i];
spaces_added++;
write_bufs[i] = io_info->wbufs[i];
}
else {
void *tmp_write_buf; /* To sidestep const warnings */
void *tmp_bkg_buf = NULL;
H5_CHECK_OVERFLOW(io_info->sel_pieces[i]->piece_points, hsize_t, size_t);
/* Initialize memory iterator */
HDassert(!mem_iter_init);
if (H5S_select_iter_init(mem_iter, io_info->mem_spaces[i], dset_info->type_info.src_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 */
/* Create block memory space */
if (NULL ==
(write_mem_spaces[i] = H5S_create_simple(1, &io_info->sel_pieces[i]->piece_points, NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "unable to create simple memory dataspace")
spaces_added++;
/* 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_modify_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")
}
/* 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
* conversion 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.
*/
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 &&
!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")
/* No background buffer necessary, prevent this element from being considered in the second
* loop */
/* Add this to H5Tconv.c? -NAF */
dset_info->type_info.need_bkg = H5T_BKG_NO;
} /* end if */
else {
/* 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);
}
/* Set up background buffer read operation if necessary */
if (H5T_BKG_YES == dset_info->type_info.need_bkg) {
HDassert(io_info->must_fill_bkg);
/* Allocate arrays of parameters for selection read to background buffer if necessary */
if (!bkg_mem_spaces) {
HDassert(!bkg_file_spaces && !bkg_addrs && !bkg_element_sizes && !bkg_bufs);
if (NULL == (bkg_mem_spaces = H5MM_malloc(io_info->pieces_added * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for memory space list")
if (NULL == (bkg_file_spaces = H5MM_malloc(io_info->pieces_added * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for file space list")
if (NULL == (bkg_addrs = H5MM_malloc(io_info->pieces_added * sizeof(haddr_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for piece address list")
if (NULL == (bkg_element_sizes = H5MM_malloc(io_info->pieces_added * sizeof(size_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for element size list")
if (NULL == (bkg_bufs = H5MM_malloc(io_info->pieces_added * sizeof(const void *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for write buffer list")
}
/* Use same (block) memory space, file space, address, and element size as write operation
*/
HDassert(bkg_mem_spaces && bkg_file_spaces && bkg_addrs && bkg_element_sizes && bkg_bufs);
bkg_mem_spaces[bkg_pieces] = write_mem_spaces[i];
bkg_file_spaces[bkg_pieces] = io_info->file_spaces[i];
bkg_addrs[bkg_pieces] = io_info->addrs[i];
bkg_element_sizes[bkg_pieces] = io_info->element_sizes[i];
/* Use previously calculated background buffer position */
bkg_bufs[bkg_pieces] = tmp_bkg_buf;
/* Add piece */
bkg_pieces++;
}
else {
/* Perform type conversion here to avoid second loop if no dsets use the background buffer
*/
/* Do the data transform before the type conversion (since
* transforms must be done in the memory type). */
if (!dset_info->type_info.is_xform_noop) {
H5Z_data_xform_t *data_transform; /* Data transform info */
/* Retrieve info from API context */
if (H5CX_get_data_transform(&data_transform) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data transform info")
if (H5Z_xform_eval(data_transform, tmp_write_buf,
(size_t)io_info->sel_pieces[i]->piece_points,
dset_info->type_info.mem_type) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "Error performing data transform")
}
/*
* Perform datatype conversion.
*/
if (H5T_convert(dset_info->type_info.tpath, dset_info->type_info.src_type_id,
dset_info->type_info.dst_type_id,
(size_t)io_info->sel_pieces[i]->piece_points, (size_t)0, (size_t)0,
tmp_write_buf, tmp_bkg_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
}
}
/* Release 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;
}
}
HDassert(spaces_added == io_info->pieces_added);
/* Gather data to background buffer if necessary */
if (io_info->must_fill_bkg) {
size_t j = 0; /* Index into array of background buffers */
/* Read data */
H5_CHECK_OVERFLOW(bkg_pieces, size_t, uint32_t)
if (H5F_shared_select_read(io_info->f_sh, H5FD_MEM_DRAW, (uint32_t)bkg_pieces, bkg_mem_spaces,
bkg_file_spaces, bkg_addrs, bkg_element_sizes, bkg_bufs) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "selection read to background buffer failed")
/* Perform type conversion on pieces with background buffers that were just read */
for (i = 0; i < io_info->pieces_added; i++) {
H5D_dset_io_info_t *dset_info = io_info->sel_pieces[i]->dset_info;
if (H5T_BKG_YES == dset_info->type_info.need_bkg) {
/* Non-const write_buf[i]. Use pointer math here to avoid const warnings. When
* there's a background buffer write_buf[i] always points inside the non-const tconv
* buf so this is OK. */
void *tmp_write_buf =
(void *)((uint8_t *)io_info->tconv_buf +
((const uint8_t *)write_bufs[i] - (const uint8_t *)io_info->tconv_buf));
/* Do the data transform before the type conversion (since
* transforms must be done in the memory type). */
if (!dset_info->type_info.is_xform_noop) {
H5Z_data_xform_t *data_transform; /* Data transform info */
/* Retrieve info from API context */
if (H5CX_get_data_transform(&data_transform) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data transform info")
if (H5Z_xform_eval(data_transform, tmp_write_buf,
(size_t)io_info->sel_pieces[i]->piece_points,
dset_info->type_info.mem_type) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "Error performing data transform")
}
/*
* Perform datatype conversion.
*/
HDassert(j < bkg_pieces);
if (H5T_convert(dset_info->type_info.tpath, dset_info->type_info.src_type_id,
dset_info->type_info.dst_type_id,
(size_t)io_info->sel_pieces[i]->piece_points, (size_t)0, (size_t)0,
tmp_write_buf, bkg_bufs[j]) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
/* Advance to next background buffer */
j++;
}
}
HDassert(j == bkg_pieces);
}
/* Write data to disk */
H5_CHECK_OVERFLOW(io_info->pieces_added, size_t, uint32_t)
if (H5F_shared_select_write(io_info->f_sh, H5FD_MEM_DRAW, (uint32_t)io_info->pieces_added,
write_mem_spaces, io_info->file_spaces, io_info->addrs,
io_info->element_sizes, write_bufs) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "selection write failed")
done:
/* Release and free selection iterator */
if (mem_iter_init && H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
if (mem_iter)
mem_iter = H5FL_FREE(H5S_sel_iter_t, mem_iter);
/* Free write_bufs */
H5MM_free(write_bufs);
write_bufs = NULL;
/* Clear and free write_mem_spaces */
if (write_mem_spaces) {
for (i = 0; i < spaces_added; i++) {
HDassert(write_mem_spaces[i]);
if (write_mem_spaces[i] != io_info->mem_spaces[i] && H5S_close(write_mem_spaces[i]) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "Can't close dataspace")
}
H5MM_free(write_mem_spaces);
write_mem_spaces = NULL;
}
/* Free bakcground buffer parameter arrays */
H5MM_free(bkg_mem_spaces);
bkg_mem_spaces = NULL;
H5MM_free(bkg_file_spaces);
bkg_file_spaces = NULL;
H5MM_free(bkg_addrs);
bkg_addrs = NULL;
H5MM_free(bkg_element_sizes);
bkg_element_sizes = NULL;
H5MM_free(bkg_bufs);
bkg_bufs = NULL;
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__scatgath_write_select() */
/*-------------------------------------------------------------------------
* Function: H5D__compound_opt_read
*

View File

@ -2384,7 +2384,8 @@ H5D__virtual_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t H5_ATTR_UNUSED *
FUNC_ENTER_PACKAGE_NOERR
/* Disable selection I/O */
io_info->use_select_io = FALSE;
io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF;
io_info->no_selection_io_cause |= H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__virtual_io_init() */

View File

@ -469,6 +469,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++) {
@ -505,6 +506,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:
@ -669,6 +675,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++) {
@ -705,6 +712,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:
@ -991,6 +1003,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 */
@ -1630,6 +1650,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 */

View File

@ -906,6 +906,7 @@ H5_DLL haddr_t H5F_shared_get_eoa(const H5F_shared_t *f_sh, H5FD_mem_t type);
H5_DLL haddr_t H5F_get_eoa(const H5F_t *f, H5FD_mem_t type);
H5_DLL herr_t H5F_shared_get_file_driver(const H5F_shared_t *f_sh, H5FD_t **file_handle);
H5_DLL herr_t H5F_get_vfd_handle(const H5F_t *file, hid_t fapl, void **file_handle);
H5_DLL hbool_t H5F_has_vector_select_io(const H5F_t *f, hbool_t is_write);
/* File mounting routines */
H5_DLL herr_t H5F_mount(const struct H5G_loc_t *loc, const char *name, H5F_t *child, hid_t plist_id);

View File

@ -1372,3 +1372,30 @@ H5F_get_file_locking(const H5F_t *f)
FUNC_LEAVE_NOAPI(f->shared->use_file_locking)
} /* end H5F_get_file_locking */
/*-------------------------------------------------------------------------
* Function: H5F_has_vector_select_io
*
* Purpose: Determine if vector or selection I/O is supported by this file
*
* Return: TRUE/FALSE
*
*-------------------------------------------------------------------------
*/
hbool_t
H5F_has_vector_select_io(const H5F_t *f, hbool_t is_write)
{
hbool_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(f);
HDassert(f->shared);
if (is_write)
ret_value = (f->shared->lf->cls->write_vector != NULL || f->shared->lf->cls->write_selection != NULL);
else
ret_value = (f->shared->lf->cls->read_vector != NULL || f->shared->lf->cls->read_selection != NULL);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_has_vector_select_io */

View File

@ -168,6 +168,19 @@
#define H5D_XFER_DSET_IO_SEL_ENC H5P__dxfr_edc_enc
#define H5D_XFER_DSET_IO_SEL_DEC H5P__dxfr_edc_dec
#endif /* QAK */
/* Definition for selection I/O mode property */
#define H5D_XFER_SELECTION_IO_MODE_SIZE sizeof(H5D_selection_io_mode_t)
#define H5D_XFER_SELECTION_IO_MODE_DEF H5D_SELECTION_IO_MODE_DEFAULT
#define H5D_XFER_SELECTION_IO_MODE_ENC H5P__dxfr_selection_io_mode_enc
#define H5D_XFER_SELECTION_IO_MODE_DEC H5P__dxfr_selection_io_mode_dec
/* Definitions for cause of no selection I/O property */
#define H5D_XFER_NO_SELECTION_IO_CAUSE_SIZE sizeof(uint32_t)
#define H5D_XFER_NO_SELECTION_IO_CAUSE_DEF 0
/* Definitions for modify write buffer property */
#define H5D_XFER_MODIFY_WRITE_BUF_SIZE sizeof(hbool_t)
#define H5D_XFER_MODIFY_WRITE_BUF_DEF FALSE
#define H5D_XFER_MODIFY_WRITE_BUF_ENC H5P__dxfr_modify_write_buf_enc
#define H5D_XFER_MODIFY_WRITE_BUF_DEC H5P__dxfr_modify_write_buf_dec
/******************/
/* Local Typedefs */
@ -208,6 +221,10 @@ static herr_t H5P__dxfr_xform_close(const char *name, size_t size, void *value);
static herr_t H5P__dxfr_dset_io_hyp_sel_copy(const char *name, size_t size, void *value);
static int H5P__dxfr_dset_io_hyp_sel_cmp(const void *value1, const void *value2, size_t size);
static herr_t H5P__dxfr_dset_io_hyp_sel_close(const char *name, size_t size, void *value);
static herr_t H5P__dxfr_selection_io_mode_enc(const void *value, void **pp, size_t *size);
static herr_t H5P__dxfr_selection_io_mode_dec(const void **pp, void *value);
static herr_t H5P__dxfr_modify_write_buf_enc(const void *value, void **pp, size_t *size);
static herr_t H5P__dxfr_modify_write_buf_dec(const void **pp, void *value);
/*********************/
/* Package Variables */
@ -277,6 +294,9 @@ static const H5T_conv_cb_t H5D_def_conv_cb_g =
static const void *H5D_def_xfer_xform_g = H5D_XFER_XFORM_DEF; /* Default value for data transform */
static const H5S_t *H5D_def_dset_io_sel_g =
H5D_XFER_DSET_IO_SEL_DEF; /* Default value for dataset I/O selection */
static const H5D_selection_io_mode_t H5D_def_selection_io_mode_g = H5D_XFER_SELECTION_IO_MODE_DEF;
static const uint32_t H5D_def_no_selection_io_cause_g = H5D_XFER_NO_SELECTION_IO_CAUSE_DEF;
static const hbool_t H5D_def_modify_write_buf_g = H5D_XFER_MODIFY_WRITE_BUF_DEF;
/*-------------------------------------------------------------------------
* Function: H5P__dxfr_reg_prop
@ -441,6 +461,24 @@ H5P__dxfr_reg_prop(H5P_genclass_t *pclass)
H5D_XFER_DSET_IO_SEL_CLOSE) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
if (H5P__register_real(pclass, H5D_XFER_SELECTION_IO_MODE_NAME, H5D_XFER_SELECTION_IO_MODE_SIZE,
&H5D_def_selection_io_mode_g, NULL, NULL, NULL, H5D_XFER_SELECTION_IO_MODE_ENC,
H5D_XFER_SELECTION_IO_MODE_DEC, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
/* Register the cause of no selection I/O property */
/* (Note: this property should not have an encode/decode callback) */
if (H5P__register_real(pclass, H5D_XFER_NO_SELECTION_IO_CAUSE_NAME, H5D_XFER_NO_SELECTION_IO_CAUSE_SIZE,
&H5D_def_no_selection_io_cause_g, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
/* Register the modify write buffer property */
if (H5P__register_real(pclass, H5D_XFER_MODIFY_WRITE_BUF_NAME, H5D_XFER_MODIFY_WRITE_BUF_SIZE,
&H5D_def_modify_write_buf_g, NULL, NULL, NULL, H5D_XFER_MODIFY_WRITE_BUF_ENC,
H5D_XFER_MODIFY_WRITE_BUF_DEC, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P__dxfr_reg_prop() */
@ -2258,6 +2296,78 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P__dxfr_dset_io_hyp_sel_close() */
/*-------------------------------------------------------------------------
* Function: H5P__dxfr_selection_io_mode_enc
*
* Purpose: Callback routine which is called whenever the selection
* I/O mode property in the dataset transfer property list
* is encoded.
*
* Return: Success: Non-negative
* Failure: Negative
*
* Programmer: Vailin Choi
* Feb 2023
*
*-------------------------------------------------------------------------
*/
static herr_t
H5P__dxfr_selection_io_mode_enc(const void *value, void **_pp, size_t *size)
{
const H5D_selection_io_mode_t *select_io_mode =
(const H5D_selection_io_mode_t *)value; /* Create local alias for values */
uint8_t **pp = (uint8_t **)_pp;
FUNC_ENTER_PACKAGE_NOERR
/* Sanity check */
HDassert(select_io_mode);
HDassert(size);
if (NULL != *pp)
/* Encode selection I/O mode property */
*(*pp)++ = (uint8_t)*select_io_mode;
/* Size of selection I/O mode property */
(*size)++;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5P__dxfr_selection_io_mode_enc() */
/*-------------------------------------------------------------------------
* Function: H5P__dxfr_selection_io_mode_dec
*
* Purpose: Callback routine which is called whenever the selection
* I/O mode property in the dataset transfer property list
* is decoded.
*
* Return: Success: Non-negative
* Failure: Negative
*
* Programmer: Vailin Choi
* Feb 2023
*
*-------------------------------------------------------------------------
*/
static herr_t
H5P__dxfr_selection_io_mode_dec(const void **_pp, void *_value)
{
H5D_selection_io_mode_t *select_io_mode = (H5D_selection_io_mode_t *)_value; /* Selection I/O mode */
const uint8_t **pp = (const uint8_t **)_pp;
FUNC_ENTER_PACKAGE_NOERR
/* Sanity checks */
HDassert(pp);
HDassert(*pp);
HDassert(select_io_mode);
/* Decode selection I/O mode property */
*select_io_mode = (H5D_selection_io_mode_t) * (*pp)++;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5P__dxfr_selection_io_dec() */
/*-------------------------------------------------------------------------
* Function: H5Pset_dataset_io_hyperslab_selection
*
@ -2386,3 +2496,248 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pset_dataset_io_hyperslab_selection() */
/*-------------------------------------------------------------------------
* Function: H5Pset_selection_io
*
* Purpose: To set the selection I/O mode in the dataset
* transfer property list.
*
* Note: The library may not perform selection I/O as it asks for if
* the layout callback determines that it is not feasible to do so.
*
* Return: Success: Non-negative
* Failure: Negative
*
* Programmer: Vailin Choi
* March 5, 2023
*
*-------------------------------------------------------------------------
*/
herr_t
H5Pset_selection_io(hid_t plist_id, H5D_selection_io_mode_t selection_io_mode)
{
H5P_genplist_t *plist; /* Property list pointer */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "iDC", plist_id, selection_io_mode);
/* Check arguments */
if (plist_id == H5P_DEFAULT)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
if (NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
/* Set the selection I/O mode */
if (H5P_set(plist, H5D_XFER_SELECTION_IO_MODE_NAME, &selection_io_mode) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pset_selection_io() */
/*-------------------------------------------------------------------------
* Function: H5Pget_selection_io
*
* Purpose: To retrieve the selection I/O mode that is set in
* the dataset transfer property list.
*
* Note: The library may not perform selection I/O as it asks for if
* the layout callback determines that it is not feasible to do so.
*
* Return: Success: Non-negative
* Failure: Negative
*
* Programmer: Vailin Choi
* March 5, 2023
*
*-------------------------------------------------------------------------
*/
herr_t
H5Pget_selection_io(hid_t plist_id, H5D_selection_io_mode_t *selection_io_mode /*out*/)
{
H5P_genplist_t *plist; /* Property list pointer */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*DC", plist_id, selection_io_mode);
/* Check arguments */
if (NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
/* Get the selection I/O mode */
if (selection_io_mode)
if (H5P_get(plist, H5D_XFER_SELECTION_IO_MODE_NAME, selection_io_mode) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_selection_io() */
/*-------------------------------------------------------------------------
* Function: H5Pget_no_selection_io_cause
*
* Purpose: Retrieves causes for not performing selection I/O
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Vailin Choi
* April 17, 2023
*-------------------------------------------------------------------------
*/
herr_t
H5Pget_no_selection_io_cause(hid_t plist_id, uint32_t *no_selection_io_cause /*out*/)
{
H5P_genplist_t *plist;
herr_t ret_value = SUCCEED; /* return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "ix", plist_id, no_selection_io_cause);
/* Get the plist structure */
if (NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_ID, H5E_BADID, FAIL, "can't find object for ID")
/* Return values */
if (no_selection_io_cause)
if (H5P_get(plist, H5D_XFER_NO_SELECTION_IO_CAUSE_NAME, no_selection_io_cause) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get no_selection_io_cause value")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_no_selection_io_cause() */
/*-------------------------------------------------------------------------
* Function: H5P__dxfr_modify_write_buf_enc
*
* Purpose: Callback routine which is called whenever the modify write
* buffer property in the dataset transfer property list is
* encoded.
*
* Return: Success: Non-negative
* Failure: Negative
*
*-------------------------------------------------------------------------
*/
static herr_t
H5P__dxfr_modify_write_buf_enc(const void *value, void **_pp /*out*/, size_t *size /*out*/)
{
const hbool_t *modify_write_buf = (const hbool_t *)value; /* Create local alias for values */
uint8_t **pp = (uint8_t **)_pp;
FUNC_ENTER_PACKAGE_NOERR
/* Sanity check */
HDassert(modify_write_buf);
HDassert(size);
if (NULL != *pp)
/* Encode modify write buf property. Use "!!" so we always get 0 or 1 */
*(*pp)++ = (uint8_t)(!!(*modify_write_buf));
/* Size of modify write buf property */
(*size)++;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5P__dxfr_modify_write_buf_enc() */
/*-------------------------------------------------------------------------
* Function: H5P__dxfr_modify_write_buf_dec
*
* Purpose: Callback routine which is called whenever the modify write
* buffer property in the dataset transfer property list is
* decoded.
*
* Return: Success: Non-negative
* Failure: Negative
*
*-------------------------------------------------------------------------
*/
static herr_t
H5P__dxfr_modify_write_buf_dec(const void **_pp, void *_value /*out*/)
{
hbool_t *modify_write_buf = (hbool_t *)_value; /* Modify write buffer */
const uint8_t **pp = (const uint8_t **)_pp;
FUNC_ENTER_PACKAGE_NOERR
/* Sanity checks */
HDassert(pp);
HDassert(*pp);
HDassert(modify_write_buf);
/* Decode selection I/O mode property */
*modify_write_buf = (hbool_t) * (*pp)++;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5P__dxfr_modify_write_buf_dec() */
/*-------------------------------------------------------------------------
* Function: H5Pset_modify_write_buf
*
* Purpose: Allows the library to modify the contents of the write
* buffer
*
* Return: Success: Non-negative
* Failure: Negative
*
*-------------------------------------------------------------------------
*/
herr_t
H5Pset_modify_write_buf(hid_t plist_id, hbool_t modify_write_buf)
{
H5P_genplist_t *plist; /* Property list pointer */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "ib", plist_id, modify_write_buf);
/* Check arguments */
if (plist_id == H5P_DEFAULT)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
if (NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
/* Set the selection I/O mode */
if (H5P_set(plist, H5D_XFER_MODIFY_WRITE_BUF_NAME, &modify_write_buf) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pset_modify_write_buf() */
/*-------------------------------------------------------------------------
* Function: H5Pget_modify_write_buf
*
* Purpose: Retrieves the "modify write buffer" property
*
* Return: Success: Non-negative
* Failure: Negative
*
*-------------------------------------------------------------------------
*/
herr_t
H5Pget_modify_write_buf(hid_t plist_id, hbool_t *modify_write_buf /*out*/)
{
H5P_genplist_t *plist; /* Property list pointer */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*b", plist_id, modify_write_buf);
/* Check arguments */
if (NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
/* Get the selection I/O mode */
if (modify_write_buf)
if (H5P_get(plist, H5D_XFER_MODIFY_WRITE_BUF_NAME, modify_write_buf) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_modify_write_buf() */

View File

@ -328,7 +328,6 @@ typedef enum H5D_mpio_actual_io_mode_t {
H5D_MPIO_CHUNK_MIXED = 0x1 | 0x2,
/**< HDF5 performed one the chunk collective optimization schemes and some
chunks were accessed independently, some collectively. */
/** \internal The contiguous case is separate from the bit field. */
H5D_MPIO_CONTIGUOUS_COLLECTIVE = 0x4
/**< Collective I/O was performed on a contiguous dataset */
} H5D_mpio_actual_io_mode_t;
@ -344,7 +343,8 @@ typedef enum H5D_mpio_no_collective_cause_t {
H5D_MPIO_SET_INDEPENDENT = 0x01,
/**< Collective I/O was not performed because independent I/O was requested */
H5D_MPIO_DATATYPE_CONVERSION = 0x02,
/**< Collective I/O was not performed because datatype conversions were required */
/**< Collective I/O was not performed because datatype conversions were required and selection I/O was not
possible (see below) */
H5D_MPIO_DATA_TRANSFORMS = 0x04,
/**< Collective I/O was not performed because data transforms needed to be applied */
H5D_MPIO_MPI_OPT_TYPES_ENV_VAR_DISABLED = 0x08,
@ -357,11 +357,72 @@ typedef enum H5D_mpio_no_collective_cause_t {
/**< Collective I/O was not performed because parallel filtered writes are disabled */
H5D_MPIO_ERROR_WHILE_CHECKING_COLLECTIVE_POSSIBLE = 0x80,
/**< Error */
H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE = 0x100
H5D_MPIO_NO_SELECTION_IO = 0x100,
/**< Collective I/O would be supported by selection or vector I/O but that feature was disabled
(see causes via H5Pget_no_selection_io_cause()) */
H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE = 0x200
/**< Sentinel */
} H5D_mpio_no_collective_cause_t;
//! <!-- [H5D_mpio_no_collective_cause_t_snip] -->
/**
* Causes for H5Pget_no_selection_io_cause() property
*/
#define H5D_SEL_IO_DISABLE_BY_API \
(0x0001u) /**< Selection I/O was not performed because \
the feature was disabled by the API */
#define H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET \
(0x0002u) /**< Selection I/O was not performed because the \
dataset was neither contiguous nor chunked */
#define H5D_SEL_IO_CONTIGUOUS_SIEVE_BUFFER \
(0x0004u) /**< Selection I/O was not performed because of \
sieve buffer for contiguous dataset */
#define H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB \
(0x0008u) /**< Selection I/O was not performed because the VFD \
does not have vector or selection I/O callback */
#define H5D_SEL_IO_PAGE_BUFFER \
(0x0010u) /**< Selection I/O was not performed because of \
page buffer */
#define H5D_SEL_IO_DATASET_FILTER \
(0x0020u) /**< Selection I/O was not performed because of \
dataset filters */
#define H5D_SEL_IO_CHUNK_CACHE \
(0x0040u) /**< Selection I/O was not performed because of \
chunk cache */
#define H5D_SEL_IO_TCONV_BUF_TOO_SMALL \
(0x0080u) /**< Selection I/O was not performed because the \
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_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)
//! <!--[H5D_selection_io_mode_t_snip] -->
/**
* Selection I/O mode property
*
* \details The default value, #H5D_SELECTION_IO_MODE_DEFAULT,
* indicates selection I/O can be ON or OFF as
* determined by library internal.
*/
typedef enum H5D_selection_io_mode_t {
H5D_SELECTION_IO_MODE_DEFAULT = 0,
/**< Default selection I/O mode. */
H5D_SELECTION_IO_MODE_OFF,
/**< Selection I/O is off. */
H5D_SELECTION_IO_MODE_ON
/**< Selection I/O is on. */
} H5D_selection_io_mode_t;
//! <!--[H5D_selection_io_mode_t_snip] -->
/********************/
/* Public Variables */
/********************/
@ -8204,6 +8265,191 @@ H5_DLL herr_t H5Pset_dataset_io_hyperslab_selection(hid_t plist_id, unsigned ran
const hsize_t start[], const hsize_t stride[],
const hsize_t count[], const hsize_t block[]);
/**
*
* \ingroup DXPL
*
* \brief Sets the selection I/O mode
*
* \dxpl_id{plist_id}
* \param[in] selection_io_mode The selection I/O mode to be set
*
* \return \herr_t
*
* \details H5Pset_selection_io() sets the selection I/O mode
* \p selection_io_mode in the dataset transfer property
* list \p plist_id.
*
* This can be used to enable collective I/O with type conversion, or
* with custom VFDs that support vector or selection I/O.
*
* Values that can be set in \p selection_io_mode:
* \snippet this H5D_selection_io_mode_t_snip
* \click4more
*
* \note The library may not perform selection I/O as it asks for if the
* layout callback determines that it is not feasible to do so. Please
* refer to H5Pget_no_selection_io_cause() for details.
*
* When used with type conversion, selection I/O requires the type
* conversion buffer (and the background buffer if applicable) be large
* enough to hold the entirety of the data involved in the I/O. For
* read operations, the library will use the application's read buffer
* as the type conversion buffer if the memory type is not smaller than
* the file type, eliminating the need for a separate type conversion
* buffer (a background buffer may still be required). For write
* operations, the library will similarly use the write buffer as a
* type conversion buffer, but only if H5Pset_modify_write_buf() is
* used to allow the library to modify the contents of the write
* buffer.
*
* \since 1.14.1
*
*/
H5_DLL herr_t H5Pset_selection_io(hid_t plist_id, H5D_selection_io_mode_t selection_io_mode);
/**
*
* \ingroup DXPL
*
* \brief Retrieves the selection I/O mode
*
* \dxpl_id{plist_id}
* \param[out] selection_io_mode The selection I/O mode
*
* \return \herr_t
*
* \details H5Pget_selection_io() queries the selection I/O mode set in
* in the dataset transfer property list \p plist_id.
*
* Values returned in \p selection_io_mode:
* \snippet this H5D_selection_io_mode_t_snip
* \click4more
*
* \note The library may not perform selection I/O as it asks for if the
* layout callback determines that it is not feasible to do so. Please
* refer to H5Pget_no_selection_io_cause() for details.
*
* \since 1.14.1
*
*/
H5_DLL herr_t H5Pget_selection_io(hid_t plist_id, H5D_selection_io_mode_t *selection_io_mode);
/**
* \ingroup DXPL
*
* \brief Retrieves the cause for not performing selection or vector I/O on the
* last parallel I/O call
*
* \dxpl_id{plist_id}
* \param[out] no_selection_io_cause A bitwise set value indicating the relevant
* causes that prevented selection I/O from
* being performed
* \return \herr_t
*
* \par Motivation:
* A user can request selection I/O to be performed via a data transfer
* property list (DXPL). This can be used to enable collective I/O with
* type conversion, or with custom VFDs that support vector or selection
* I/O. However, there are conditions that can cause HDF5 to forgo
* selection or vector I/O and perform legacy (scalar) I/O instead.
*
* \details H5Pget_no_selection_io_cause() can be used to determine whether
* selection or vector I/O was applied for the last preceding I/O call.
* If selection or vector I/O was not used, this function retrieves the
* cause(s) that prevent selection or vector I/O to be performed on
* that I/O call. The properties retrieved by this function are set
* before I/O takes place and are retained even when I/O fails.
*
* If a selection I/O request falls back to vector I/O, that is not
* considered "breaking" selection I/O by this function, since vector
* I/O still passes all information to the file driver in a single
* callback.
*
* Valid values returned in \p no_selection_io_cause are listed
* as follows. If there are multiple causes, it is a bitwise OR of
* the relevant causes.
*
* - #H5D_SEL_IO_DISABLE_BY_API
* Selection I/O was not performed because the feature was disabled by the API
* - #H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET
* Selection I/O was not performed because the dataset was neither contiguous nor chunked
* - #H5D_SEL_IO_CONTIGUOUS_SIEVE_BUFFER
* Selection I/O was not performed because of sieve buffer for contiguous dataset
* - #H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB
* Selection I/O was not performed because the VFD does not have vector or selection I/O callback
* - #H5D_SEL_IO_PAGE_BUFFER
* Selection I/O was not performed because of page buffer
* - #H5D_SEL_IO_DATASET_FILTER
* Selection I/O was not performed because of dataset filters
* - #H5D_SEL_IO_CHUNK_CACHE
* Selection I/O was not performed because of chunk cache
* - #H5D_SEL_IO_TCONV_BUF_TOO_SMALL
* Selection I/O was not performed because the type conversion buffer is too small
* - #H5D_SEL_IO_BKG_BUF_TOO_SMALL
* Selection I/O was not performed because the type conversion background buffer is too small
* - #H5D_SEL_IO_DEFAULT_OFF
* 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
*
* \since 1.14.1
*
*/
H5_DLL herr_t H5Pget_no_selection_io_cause(hid_t plist_id, uint32_t *no_selection_io_cause);
/**
*
* \ingroup DXPL
*
* \brief Allows the library to modify the contents of the write buffer
*
* \dxpl_id{plist_id}
* \param[in] modify_write_buf Whether the library can modify the contents of the write buffer
*
* \return \herr_t
*
* \details H5Pset_modify_write_buf() sets whether the library is allowed to
* modify the contents of write buffers passed to HDF5 API routines
* that are passed the dataset transfer property list \p plist_id. The
* default value for modify_write_buf is FALSE.
*
* This function can be used to allow the library to perform in-place
* type conversion on write operations to save memory space. This is
* currently only used for selection I/O operations, which are used for
* collective I/O with type conversion. After making an API call with
* this parameter set to TRUE, the contents of the write buffer are
* undefined.
*
* \note When modify_write_buf is set to TRUE the library may violate the
* const qualifier on the API parameter for the write buffer.
*
* \since 1.14.1
*
*/
H5_DLL herr_t H5Pset_modify_write_buf(hid_t plist_id, hbool_t modify_write_buf);
/**
*
* \ingroup DXPL
*
* \brief Retrieves the "modify write buffer" property
*
* \dxpl_id{plist_id}
* \param[out] modify_write_buf Whether the library can modify the contents of the write buffer
*
* \return \herr_t
*
* \details H5Pget_modify_write_buf() gets the "modify write buffer" property
* from the dataset transfer property list \p plist_id. This property
* determines whether the library is allowed to modify the contents of
* write buffers passed to HDF5 API routines that are passed
* \p plist_id. The default value for modify_write_buf is FALSE.
*
* \since 1.14.1
*
*/
H5_DLL herr_t H5Pget_modify_write_buf(hid_t plist_id, hbool_t *modify_write_buf);
/**
* \ingroup LCPL
*

View File

@ -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);

View File

@ -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
*

View File

@ -2865,9 +2865,9 @@ done:
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
@ -2882,8 +2882,8 @@ done:
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
@ -2894,7 +2894,7 @@ done:
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
@ -2903,21 +2903,21 @@ done:
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")
@ -2925,17 +2925,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

View File

@ -1965,14 +1965,6 @@ extern hbool_t H5_libterm_g; /* Is the library being shutdown? */
#endif /* H5_HAVE_THREADSAFE */
/* Extern global to determine if we should use selection I/O if available (this
* variable should be removed once selection I/O performs as well as the
* previous scalar I/O implementation
*
* NOTE: Must be exposed via H5_DLLVAR so parallel tests pass on Windows.
*/
H5_DLLVAR hbool_t H5_use_selection_io_g;
#ifdef H5_HAVE_CODESTACK
/* Include required function stack header */

View File

@ -673,6 +673,31 @@ H5_trace_args(H5RS_str_t *rs, const char *type, va_list ap)
} /* end block */
break;
case 'C': /* H5D_selection_io_mode_t */
{
H5D_selection_io_mode_t selection_io_mode =
(H5D_selection_io_mode_t)HDva_arg(ap, int);
switch (selection_io_mode) {
case H5D_SELECTION_IO_MODE_DEFAULT:
H5RS_acat(rs, "H5D_SELECTION_IO_MODE_DEFAULT");
break;
case H5D_SELECTION_IO_MODE_OFF:
H5RS_acat(rs, "H5D_SELECTION_IO_MODE_OFF");
break;
case H5D_SELECTION_IO_MODE_ON:
H5RS_acat(rs, "H5D_SELECTION_IO_MODE_ON");
break;
default:
H5RS_asprintf_cat(rs, "%ld", (long)selection_io_mode);
break;
} /* end switch */
} /* end block */
break;
case 'f': /* H5D_fill_time_t */
{
H5D_fill_time_t fill_time = (H5D_fill_time_t)HDva_arg(ap, int);

View File

@ -337,6 +337,7 @@ set (H5_TESTS
page_buffer
dtypes
dsets
select_io_dset
chunk_info # compression lib link
cmpd_dset
mdset

View File

@ -65,7 +65,7 @@ TEST_PROG= testhdf5 \
accum hyperslab istore bittests dt_arith page_buffer \
dtypes dsets chunk_info cmpd_dset mdset cmpd_dtransform filter_fail extend direct_chunk \
external efc objcopy objcopy_ref links unlink twriteorder big mtime \
fillval mount \
fillval mount select_io_dset\
flush1 flush2 app_ref enum set_extent ttsafe enc_dec_plist \
enc_dec_plist_cross_platform getname vfd ros3 s3comms hdfs ntypes \
dangle dtransform reserved cross_read freespace mf vds file_image \

View File

@ -367,6 +367,12 @@ main(void)
if ((H5Pset_data_transform(dxpl, c_to_f)) < 0)
FAIL_STACK_ERROR;
if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_ON) < 0)
FAIL_STACK_ERROR;
if (H5Pset_modify_write_buf(dxpl, TRUE) < 0)
FAIL_STACK_ERROR;
/* Test encoding & decoding property list */
if (test_encode_decode(dxpl, low, high) < 0)
FAIL_PUTS_ERROR("DXPL encoding/decoding failed\n");

View File

@ -183,6 +183,11 @@ main(void)
assert(ret > 0);
if ((ret = H5Pset_data_transform(dxpl1, c_to_f)) < 0)
assert(ret > 0);
if ((ret = H5Pset_selection_io(dxpl1, H5D_SELECTION_IO_MODE_ON)) < 0)
assert(ret > 0);
if ((ret = H5Pset_modify_write_buf(dxpl1, TRUE)) < 0)
assert(ret > 0);
if ((ret = encode_plist(dxpl1, little_endian, word_length, "testfiles/plist_files/dxpl_")) < 0)
assert(ret > 0);

3269
test/select_io_dset.c Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -8,6 +8,7 @@ project (HDF5_TEST_PAR C)
set (testphdf5_SOURCES
${HDF5_TEST_PAR_SOURCE_DIR}/testphdf5.c
${HDF5_TEST_PAR_SOURCE_DIR}/t_dset.c
${HDF5_TEST_PAR_SOURCE_DIR}/t_select_io_dset.c
${HDF5_TEST_PAR_SOURCE_DIR}/t_file.c
${HDF5_TEST_PAR_SOURCE_DIR}/t_file_image.c
${HDF5_TEST_PAR_SOURCE_DIR}/t_mdset.c
@ -96,6 +97,7 @@ set (H5P_TESTS
t_prestart
t_init_term
t_pmulti_dset
t_select_io_dset
t_shapesame
t_filters_parallel
t_subfiling_vfd

View File

@ -33,7 +33,7 @@ check_SCRIPTS = $(TEST_SCRIPT_PARA)
# Test programs. These are our main targets.
#
TEST_PROG_PARA=t_mpi t_bigio testphdf5 t_cache t_cache_image t_pread t_pshutdown t_prestart t_init_term t_pmulti_dset t_shapesame t_filters_parallel t_2Gio t_vfd
TEST_PROG_PARA=t_mpi t_bigio testphdf5 t_cache t_cache_image t_pread t_pshutdown t_prestart t_init_term t_pmulti_dset t_select_io_dset t_shapesame t_filters_parallel t_2Gio t_vfd
if SUBFILING_VFD_CONDITIONAL
TEST_PROG_PARA += t_subfiling_vfd

View File

@ -3868,6 +3868,10 @@ test_no_collective_cause_mode(int selection_mode)
uint32_t no_collective_cause_global_expected = 0;
// hsize_t coord[NELM][MAX_RANK];
uint32_t no_selection_io_cause_write = 0;
uint32_t no_selection_io_cause_read = 0;
uint32_t no_selection_io_cause_expected = 0;
const char *filename;
const char *test_name;
hbool_t is_chunked = 1;
@ -3968,27 +3972,50 @@ test_no_collective_cause_mode(int selection_mode)
dataset = H5Dcreate2(fid, "nocolcause", data_type, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT);
VRFY((dataset >= 0), "H5Dcreate2() dataset succeeded");
/* Set up the dxpl for the write */
dxpl_write = H5Pcreate(H5P_DATASET_XFER);
VRFY((dxpl_write >= 0), "H5Pcreate(H5P_DATASET_XFER) succeeded");
/*
* Set expected causes and some tweaks based on the type of test
*/
if (selection_mode & TEST_DATATYPE_CONVERSION) {
test_name = "Broken Collective I/O - Datatype Conversion";
no_collective_cause_local_expected |= H5D_MPIO_DATATYPE_CONVERSION;
no_collective_cause_global_expected |= H5D_MPIO_DATATYPE_CONVERSION;
/* set different sign to trigger type conversion */
data_type = H5T_NATIVE_UINT;
/* Disable selection I/O since datatype conversion is supported in collective with selection I/O */
ret = H5Pset_selection_io(dxpl_write, H5D_SELECTION_IO_MODE_OFF);
VRFY((ret >= 0), "H5Pset_selection_io succeeded");
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_SEL_IO_DISABLE_BY_API;
}
if (selection_mode & TEST_DATA_TRANSFORMS) {
test_name = "Broken Collective I/O - DATA Transforms";
no_collective_cause_local_expected |= H5D_MPIO_DATA_TRANSFORMS;
no_collective_cause_global_expected |= H5D_MPIO_DATA_TRANSFORMS;
/* Set transform */
ret = H5Pset_data_transform(dxpl_write, "x+1");
VRFY((ret >= 0), "H5Pset_data_transform succeeded");
/* Disable selection I/O since data transforms are supported in collective with selection I/O */
ret = H5Pset_selection_io(dxpl_write, H5D_SELECTION_IO_MODE_OFF);
VRFY((ret >= 0), "H5Pset_selection_io succeeded");
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_SEL_IO_DISABLE_BY_API;
}
if (selection_mode & TEST_NOT_SIMPLE_OR_SCALAR_DATASPACES) {
test_name = "Broken Collective I/O - No Simple or Scalar DataSpace";
no_collective_cause_local_expected |= H5D_MPIO_NOT_SIMPLE_OR_SCALAR_DATASPACES;
no_collective_cause_global_expected |= H5D_MPIO_NOT_SIMPLE_OR_SCALAR_DATASPACES;
no_collective_cause_local_expected &= ~(unsigned)H5D_MPIO_NO_SELECTION_IO;
no_collective_cause_global_expected &= ~(unsigned)H5D_MPIO_NO_SELECTION_IO;
}
if (selection_mode & TEST_NOT_CONTIGUOUS_OR_CHUNKED_DATASET_COMPACT ||
@ -3996,6 +4023,8 @@ test_no_collective_cause_mode(int selection_mode)
test_name = "Broken Collective I/O - No CONTI or CHUNKED Dataset";
no_collective_cause_local_expected |= H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
no_collective_cause_global_expected |= H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
no_collective_cause_local_expected &= ~(unsigned)H5D_MPIO_NO_SELECTION_IO;
no_collective_cause_global_expected &= ~(unsigned)H5D_MPIO_NO_SELECTION_IO;
}
if (selection_mode & TEST_COLLECTIVE) {
@ -4008,6 +4037,8 @@ test_no_collective_cause_mode(int selection_mode)
test_name = "Broken Collective I/O - Independent";
no_collective_cause_local_expected = H5D_MPIO_SET_INDEPENDENT;
no_collective_cause_global_expected = H5D_MPIO_SET_INDEPENDENT;
no_collective_cause_local_expected &= ~(unsigned)H5D_MPIO_NO_SELECTION_IO;
no_collective_cause_global_expected &= ~(unsigned)H5D_MPIO_NO_SELECTION_IO;
/* switch to independent io */
is_independent = 1;
}
@ -4037,10 +4068,6 @@ test_no_collective_cause_mode(int selection_mode)
for (i = 0; i < length; i++)
buffer[i] = i;
/* Set up the dxpl for the write */
dxpl_write = H5Pcreate(H5P_DATASET_XFER);
VRFY((dxpl_write >= 0), "H5Pcreate(H5P_DATASET_XFER) succeeded");
if (is_independent) {
/* Set Independent I/O */
ret = H5Pset_dxpl_mpio(dxpl_write, H5FD_MPIO_INDEPENDENT);
@ -4052,11 +4079,6 @@ test_no_collective_cause_mode(int selection_mode)
VRFY((ret >= 0), "H5Pset_dxpl_mpio succeeded");
}
if (selection_mode & TEST_DATA_TRANSFORMS) {
ret = H5Pset_data_transform(dxpl_write, "x+1");
VRFY((ret >= 0), "H5Pset_data_transform succeeded");
}
/*---------------------
* Test Write access
*---------------------*/
@ -4072,6 +4094,20 @@ test_no_collective_cause_mode(int selection_mode)
&no_collective_cause_global_write);
VRFY((ret >= 0), "retrieving no collective cause succeeded");
ret = H5Pget_no_selection_io_cause(dxpl_write, &no_selection_io_cause_write);
VRFY((ret >= 0), "retrieving no selection io cause succeeded");
if (no_collective_cause_local_write & H5D_MPIO_NO_SELECTION_IO) {
VRFY((no_selection_io_cause_write == no_selection_io_cause_expected),
"H5D_MPIO_NO_SELECTION_IO for write is as expected");
}
if (no_collective_cause_global_write & H5D_MPIO_NO_SELECTION_IO) {
VRFY((no_selection_io_cause_write == no_selection_io_cause_expected),
"H5D_MPIO_NO_SELECTION_IO for write is as expected");
}
/*---------------------
* Test Read access
*---------------------*/
@ -4092,6 +4128,21 @@ test_no_collective_cause_mode(int selection_mode)
&no_collective_cause_global_read);
VRFY((ret >= 0), "retrieving no collective cause succeeded");
ret = H5Pget_no_selection_io_cause(dxpl_read, &no_selection_io_cause_read);
VRFY((ret >= 0), "retrieving no selection io cause succeeded");
if (no_collective_cause_local_read & H5D_MPIO_NO_SELECTION_IO) {
VRFY((no_selection_io_cause_read == no_selection_io_cause_expected),
"H5D_MPIO_NO_SELECTION_IO for read is as expected");
}
if (no_collective_cause_global_read & H5D_MPIO_NO_SELECTION_IO) {
VRFY((no_selection_io_cause_read == no_selection_io_cause_expected),
"H5D_MPIO_NO_SELECTION_IO for read is as expected");
}
/* Check write vs read */
VRFY((no_collective_cause_local_read == no_collective_cause_local_write),
"reading and writing are the same for local cause of Broken Collective I/O");

View File

@ -566,7 +566,8 @@ coll_chunktest(const char *filename, int chunk_factor, int select_factor, int ap
hsize_t start[RANK], count[RANK], stride[RANK], block[RANK];
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
unsigned prop_value;
unsigned prop_value;
H5D_selection_io_mode_t selection_io_mode;
#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
int mpi_size, mpi_rank;
@ -804,7 +805,11 @@ coll_chunktest(const char *filename, int chunk_factor, int select_factor, int ap
/* Only check chunk optimization mode if selection I/O is not being used -
* selection I/O bypasses this IO mode decision - it's effectively always
* multi chunk currently */
if (facc_type == FACC_MPIO && !H5_use_selection_io_g) {
status = H5Pget_selection_io(xfer_plist, &selection_io_mode);
VRFY((status >= 0), "testing property list get succeeded");
if (facc_type == FACC_MPIO && (selection_io_mode != H5D_SELECTION_IO_MODE_ON)) {
switch (api_option) {
case API_LINK_HARD:
status = H5Pget(xfer_plist, H5D_XFER_COLL_CHUNK_LINK_HARD_NAME, &prop_value);

View File

@ -3348,13 +3348,27 @@ test_actual_io_mode(int selection_mode)
void
actual_io_mode_tests(void)
{
int mpi_size = -1;
H5D_selection_io_mode_t selection_io_mode;
hid_t dxpl_id = H5I_INVALID_HID;
herr_t ret;
int mpi_size = -1;
int mpi_rank = -1;
MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
/* Only run these tests if selection I/O is not being used - selection I/O
* bypasses this IO mode decision - it's effectively always multi chunk
* currently */
if (!H5_use_selection_io_g) {
dxpl_id = H5Pcreate(H5P_DATASET_XFER);
VRFY((dxpl_id >= 0), "H5Pcreate(H5P_DATASET_XFER) succeeded");
ret = H5Pget_selection_io(dxpl_id, &selection_io_mode);
VRFY((ret >= 0), "retrieving selection io mode succeeded");
ret = H5Pclose(dxpl_id);
VRFY((ret >= 0), "H5Pclose succeeded");
if (selection_io_mode != H5D_SELECTION_IO_MODE_ON) {
test_actual_io_mode(TEST_ACTUAL_IO_NO_COLLECTIVE);
/*
@ -3438,6 +3452,10 @@ test_no_collective_cause_mode(int selection_mode)
uint32_t no_collective_cause_global_read = 0;
uint32_t no_collective_cause_global_expected = 0;
uint32_t no_selection_io_cause_write = 0;
uint32_t no_selection_io_cause_read = 0;
uint32_t no_selection_io_cause_expected = 0;
const char *filename;
const char *test_name;
hbool_t is_chunked = 1;
@ -3538,27 +3556,50 @@ test_no_collective_cause_mode(int selection_mode)
dataset = H5Dcreate2(fid, "nocolcause", data_type, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT);
VRFY((dataset >= 0), "H5Dcreate2() dataset succeeded");
/* Set up the dxpl for the write */
dxpl_write = H5Pcreate(H5P_DATASET_XFER);
VRFY((dxpl_write >= 0), "H5Pcreate(H5P_DATASET_XFER) succeeded");
/*
* Set expected causes and some tweaks based on the type of test
*/
if (selection_mode & TEST_DATATYPE_CONVERSION) {
test_name = "Broken Collective I/O - Datatype Conversion";
no_collective_cause_local_expected |= H5D_MPIO_DATATYPE_CONVERSION;
no_collective_cause_global_expected |= H5D_MPIO_DATATYPE_CONVERSION;
/* set different sign to trigger type conversion */
data_type = H5T_NATIVE_UINT;
/* Disable selection I/O since datatype conversion is supported in collective with selection I/O */
ret = H5Pset_selection_io(dxpl_write, H5D_SELECTION_IO_MODE_OFF);
VRFY((ret >= 0), "H5Pset_selection_io succeeded");
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_SEL_IO_DISABLE_BY_API;
}
if (selection_mode & TEST_DATA_TRANSFORMS) {
test_name = "Broken Collective I/O - DATA Transforms";
no_collective_cause_local_expected |= H5D_MPIO_DATA_TRANSFORMS;
no_collective_cause_global_expected |= H5D_MPIO_DATA_TRANSFORMS;
/* Set transform */
ret = H5Pset_data_transform(dxpl_write, "x+1");
VRFY((ret >= 0), "H5Pset_data_transform succeeded");
/* Disable selection I/O since data transforms are supported in collective with selection I/O */
ret = H5Pset_selection_io(dxpl_write, H5D_SELECTION_IO_MODE_OFF);
VRFY((ret >= 0), "H5Pset_selection_io succeeded");
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_SEL_IO_DISABLE_BY_API;
}
if (selection_mode & TEST_NOT_SIMPLE_OR_SCALAR_DATASPACES) {
test_name = "Broken Collective I/O - No Simple or Scalar DataSpace";
no_collective_cause_local_expected |= H5D_MPIO_NOT_SIMPLE_OR_SCALAR_DATASPACES;
no_collective_cause_global_expected |= H5D_MPIO_NOT_SIMPLE_OR_SCALAR_DATASPACES;
no_collective_cause_local_expected &= ~(unsigned)H5D_MPIO_NO_SELECTION_IO;
no_collective_cause_global_expected &= ~(unsigned)H5D_MPIO_NO_SELECTION_IO;
}
if (selection_mode & TEST_NOT_CONTIGUOUS_OR_CHUNKED_DATASET_COMPACT ||
@ -3566,6 +3607,8 @@ test_no_collective_cause_mode(int selection_mode)
test_name = "Broken Collective I/O - No CONTI or CHUNKED Dataset";
no_collective_cause_local_expected |= H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
no_collective_cause_global_expected |= H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
no_collective_cause_local_expected &= ~(unsigned)H5D_MPIO_NO_SELECTION_IO;
no_collective_cause_global_expected &= ~(unsigned)H5D_MPIO_NO_SELECTION_IO;
}
if (selection_mode & TEST_COLLECTIVE) {
@ -3578,6 +3621,8 @@ test_no_collective_cause_mode(int selection_mode)
test_name = "Broken Collective I/O - Independent";
no_collective_cause_local_expected = H5D_MPIO_SET_INDEPENDENT;
no_collective_cause_global_expected = H5D_MPIO_SET_INDEPENDENT;
no_collective_cause_local_expected &= ~(unsigned)H5D_MPIO_NO_SELECTION_IO;
no_collective_cause_global_expected &= ~(unsigned)H5D_MPIO_NO_SELECTION_IO;
/* switch to independent io */
is_independent = 1;
}
@ -3607,10 +3652,6 @@ test_no_collective_cause_mode(int selection_mode)
for (i = 0; i < length; i++)
buffer[i] = i;
/* Set up the dxpl for the write */
dxpl_write = H5Pcreate(H5P_DATASET_XFER);
VRFY((dxpl_write >= 0), "H5Pcreate(H5P_DATASET_XFER) succeeded");
if (is_independent) {
/* Set Independent I/O */
ret = H5Pset_dxpl_mpio(dxpl_write, H5FD_MPIO_INDEPENDENT);
@ -3642,6 +3683,20 @@ test_no_collective_cause_mode(int selection_mode)
&no_collective_cause_global_write);
VRFY((ret >= 0), "retrieving no collective cause succeeded");
ret = H5Pget_no_selection_io_cause(dxpl_write, &no_selection_io_cause_write);
VRFY((ret >= 0), "retrieving no selection io cause succeeded");
if (no_collective_cause_local_write & H5D_MPIO_NO_SELECTION_IO) {
VRFY((no_selection_io_cause_write == no_selection_io_cause_expected),
"H5D_MPIO_NO_SELECTION_IO for write is as expected");
}
if (no_collective_cause_global_write & H5D_MPIO_NO_SELECTION_IO) {
VRFY((no_selection_io_cause_write == no_selection_io_cause_expected),
"H5D_MPIO_NO_SELECTION_IO for write is as expected");
}
/*---------------------
* Test Read access
*---------------------*/
@ -3662,6 +3717,21 @@ test_no_collective_cause_mode(int selection_mode)
&no_collective_cause_global_read);
VRFY((ret >= 0), "retrieving no collective cause succeeded");
ret = H5Pget_no_selection_io_cause(dxpl_read, &no_selection_io_cause_read);
VRFY((ret >= 0), "retrieving no selection io cause succeeded");
if (no_collective_cause_local_read & H5D_MPIO_NO_SELECTION_IO) {
VRFY((no_selection_io_cause_read == no_selection_io_cause_expected),
"H5D_MPIO_NO_SELECTION_IO for read is as expected");
}
if (no_collective_cause_global_read & H5D_MPIO_NO_SELECTION_IO) {
VRFY((no_selection_io_cause_read == no_selection_io_cause_expected),
"H5D_MPIO_NO_SELECTION_IO for read is as expected");
}
/* Check write vs read */
VRFY((no_collective_cause_local_read == no_collective_cause_local_write),
"reading and writing are the same for local cause of Broken Collective I/O");

3786
testpar/t_select_io_dset.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -425,7 +425,10 @@ test_stripe_sizes(void)
VRFY(tmp_filename, "HDmalloc succeeded");
dxpl_id = H5Pcreate(H5P_DATASET_XFER);
VRFY((dxpl_id >= 0), "DCPL creation succeeded");
VRFY((dxpl_id >= 0), "DXPL creation succeeded");
/* Set selection I/O mode on DXPL */
VRFY((H5Pset_selection_io(dxpl_id, H5D_SELECTION_IO_MODE_ON) >= 0), "H5Pset_selection_io succeeded");
for (size_t i = 0; i < SUBF_NITER; i++) {
H5FD_subfiling_params_t cfg;
@ -1011,12 +1014,19 @@ test_read_different_stripe_size(void)
hid_t file_id = H5I_INVALID_HID;
hid_t fapl_id = H5I_INVALID_HID;
hid_t dset_id = H5I_INVALID_HID;
hid_t dxpl_id = H5I_INVALID_HID;
hid_t fspace_id = H5I_INVALID_HID;
char *tmp_filename = NULL;
void *buf = NULL;
curr_nerrors = nerrors;
dxpl_id = H5Pcreate(H5P_DATASET_XFER);
VRFY((dxpl_id >= 0), "DXPL creation succeeded");
/* Set selection I/O mode on DXPL */
VRFY((H5Pset_selection_io(dxpl_id, H5D_SELECTION_IO_MODE_ON) >= 0), "H5Pset_selection_io succeeded");
if (MAINPROCESS)
TESTING_2("file re-opening with different stripe size");
@ -1066,7 +1076,7 @@ test_read_different_stripe_size(void)
for (size_t i = 0; i < count[0]; i++)
((SUBF_C_TYPE *)buf)[i] = (SUBF_C_TYPE)((size_t)mpi_rank + i);
VRFY((H5Dwrite(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, H5P_DEFAULT, buf) >= 0),
VRFY((H5Dwrite(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, dxpl_id, buf) >= 0),
"Dataset write succeeded");
HDfree(buf);
@ -1133,7 +1143,7 @@ test_read_different_stripe_size(void)
buf = HDcalloc(1, count[0] * sizeof(SUBF_C_TYPE));
VRFY(buf, "HDcalloc succeeded");
VRFY((H5Dread(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, H5P_DEFAULT, buf) >= 0),
VRFY((H5Dread(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, dxpl_id, buf) >= 0),
"Dataset read succeeded");
for (size_t i = 0; i < count[0]; i++) {
@ -1185,6 +1195,7 @@ test_read_different_stripe_size(void)
}
H5E_END_TRY;
VRFY((H5Pclose(dxpl_id) >= 0), "DXPL close succeeded");
VRFY((H5Pclose(fapl_id) >= 0), "FAPL close succeeded");
HDfree(tmp_filename);
@ -1214,11 +1225,18 @@ test_subfiling_precreate_rank_0(void)
hid_t file_id = H5I_INVALID_HID;
hid_t fapl_id = H5I_INVALID_HID;
hid_t dset_id = H5I_INVALID_HID;
hid_t dxpl_id = H5I_INVALID_HID;
hid_t fspace_id = H5I_INVALID_HID;
void *buf = NULL;
curr_nerrors = nerrors;
dxpl_id = H5Pcreate(H5P_DATASET_XFER);
VRFY((dxpl_id >= 0), "DXPL creation succeeded");
/* Set selection I/O mode on DXPL */
VRFY((H5Pset_selection_io(dxpl_id, H5D_SELECTION_IO_MODE_ON) >= 0), "H5Pset_selection_io succeeded");
if (MAINPROCESS)
TESTING_2("file pre-creation on rank 0");
@ -1278,7 +1296,7 @@ test_subfiling_precreate_rank_0(void)
for (size_t i = 0; i < dset_dims[0]; i++)
((SUBF_C_TYPE *)buf)[i] = (SUBF_C_TYPE)((i / n_elements_per_rank) + (i % n_elements_per_rank));
VRFY((H5Dwrite(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, H5P_DEFAULT, buf) >= 0),
VRFY((H5Dwrite(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, dxpl_id, buf) >= 0),
"Dataset write succeeded");
HDfree(buf);
@ -1357,7 +1375,7 @@ test_subfiling_precreate_rank_0(void)
buf = HDcalloc(1, count[0] * sizeof(SUBF_C_TYPE));
VRFY(buf, "HDcalloc succeeded");
VRFY((H5Dread(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, H5P_DEFAULT, buf) >= 0),
VRFY((H5Dread(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, dxpl_id, buf) >= 0),
"Dataset read succeeded");
for (size_t i = 0; i < n_elements_per_rank; i++) {
@ -1380,6 +1398,7 @@ test_subfiling_precreate_rank_0(void)
H5E_END_TRY;
VRFY((H5Pclose(fapl_id) >= 0), "FAPL close succeeded");
VRFY((H5Pclose(dxpl_id) >= 0), "DXPL close succeeded");
CHECK_PASSED();
}
@ -1405,11 +1424,18 @@ test_subfiling_write_many_read_one(void)
hid_t file_id = H5I_INVALID_HID;
hid_t fapl_id = H5I_INVALID_HID;
hid_t dset_id = H5I_INVALID_HID;
hid_t dxpl_id = H5I_INVALID_HID;
hid_t fspace_id = H5I_INVALID_HID;
void *buf = NULL;
curr_nerrors = nerrors;
dxpl_id = H5Pcreate(H5P_DATASET_XFER);
VRFY((dxpl_id >= 0), "DXPL creation succeeded");
/* Set selection I/O mode on DXPL */
VRFY((H5Pset_selection_io(dxpl_id, H5D_SELECTION_IO_MODE_ON) >= 0), "H5Pset_selection_io succeeded");
if (MAINPROCESS)
TESTING_2("reading back file with single MPI rank");
@ -1461,7 +1487,7 @@ test_subfiling_write_many_read_one(void)
for (size_t i = 0; i < count[0]; i++)
((SUBF_C_TYPE *)buf)[i] = (SUBF_C_TYPE)((size_t)mpi_rank + i);
VRFY((H5Dwrite(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, H5P_DEFAULT, buf) >= 0),
VRFY((H5Dwrite(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, dxpl_id, buf) >= 0),
"Dataset write succeeded");
HDfree(buf);
@ -1486,7 +1512,7 @@ test_subfiling_write_many_read_one(void)
buf = HDcalloc(1, target_size);
VRFY(buf, "HDcalloc succeeded");
VRFY((H5Dread(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, H5S_ALL, H5P_DEFAULT, buf) >= 0),
VRFY((H5Dread(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, H5S_ALL, dxpl_id, buf) >= 0),
"Dataset read succeeded");
for (size_t i = 0; i < (size_t)mpi_size; i++) {
@ -1516,6 +1542,7 @@ test_subfiling_write_many_read_one(void)
VRFY((mpi_code_g == MPI_SUCCESS), "MPI_Barrier succeeded");
VRFY((H5Sclose(fspace_id) >= 0), "File dataspace close succeeded");
VRFY((H5Pclose(dxpl_id) >= 0), "DXPL close succeeded");
CHECK_PASSED();
}
@ -1543,11 +1570,18 @@ test_subfiling_write_many_read_few(void)
hid_t file_id = H5I_INVALID_HID;
hid_t fapl_id = H5I_INVALID_HID;
hid_t dset_id = H5I_INVALID_HID;
hid_t dxpl_id = H5I_INVALID_HID;
hid_t fspace_id = H5I_INVALID_HID;
void *buf = NULL;
curr_nerrors = nerrors;
dxpl_id = H5Pcreate(H5P_DATASET_XFER);
VRFY((dxpl_id >= 0), "DXPL creation succeeded");
/* Set selection I/O mode on DXPL */
VRFY((H5Pset_selection_io(dxpl_id, H5D_SELECTION_IO_MODE_ON) >= 0), "H5Pset_selection_io succeeded");
if (MAINPROCESS)
TESTING_2("reading back file with fewer MPI ranks than written with");
@ -1609,7 +1643,7 @@ test_subfiling_write_many_read_few(void)
for (size_t i = 0; i < count[0]; i++)
((SUBF_C_TYPE *)buf)[i] = (SUBF_C_TYPE)((size_t)mpi_rank + i);
VRFY((H5Dwrite(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, H5P_DEFAULT, buf) >= 0),
VRFY((H5Dwrite(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, dxpl_id, buf) >= 0),
"Dataset write succeeded");
HDfree(buf);
@ -1664,7 +1698,7 @@ test_subfiling_write_many_read_few(void)
buf = HDcalloc(1, target_size);
VRFY(buf, "HDcalloc succeeded");
VRFY((H5Dread(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, H5S_ALL, H5P_DEFAULT, buf) >= 0),
VRFY((H5Dread(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, H5S_ALL, dxpl_id, buf) >= 0),
"Dataset read succeeded");
for (size_t i = 0; i < (size_t)mpi_size; i++) {
@ -1699,6 +1733,7 @@ test_subfiling_write_many_read_few(void)
VRFY((mpi_code_g == MPI_SUCCESS), "MPI_Barrier succeeded");
VRFY((H5Sclose(fspace_id) >= 0), "File dataspace close succeeded");
VRFY((H5Pclose(dxpl_id) >= 0), "DXPL close succeeded");
CHECK_PASSED();
}
@ -1727,6 +1762,7 @@ test_subfiling_h5fuse(void)
hid_t file_id = H5I_INVALID_HID;
hid_t fapl_id = H5I_INVALID_HID;
hid_t dset_id = H5I_INVALID_HID;
hid_t dxpl_id = H5I_INVALID_HID;
hid_t fspace_id = H5I_INVALID_HID;
void *buf = NULL;
int skip_test = 0;
@ -1734,6 +1770,12 @@ test_subfiling_h5fuse(void)
curr_nerrors = nerrors;
dxpl_id = H5Pcreate(H5P_DATASET_XFER);
VRFY((dxpl_id >= 0), "DXPL creation succeeded");
/* Set selection I/O mode on DXPL */
VRFY((H5Pset_selection_io(dxpl_id, H5D_SELECTION_IO_MODE_ON) >= 0), "H5Pset_selection_io succeeded");
if (MAINPROCESS)
TESTING_2("h5fuse utility");
@ -1826,7 +1868,7 @@ test_subfiling_h5fuse(void)
for (size_t i = 0; i < count[0]; i++)
((SUBF_C_TYPE *)buf)[i] = (SUBF_C_TYPE)((size_t)mpi_rank + i);
VRFY((H5Dwrite(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, H5P_DEFAULT, buf) >= 0),
VRFY((H5Dwrite(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, fspace_id, dxpl_id, buf) >= 0),
"Dataset write succeeded");
HDfree(buf);
@ -1899,7 +1941,7 @@ test_subfiling_h5fuse(void)
buf = HDcalloc(1, target_size);
VRFY(buf, "HDcalloc succeeded");
VRFY((H5Dread(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, H5S_ALL, H5P_DEFAULT, buf) >= 0),
VRFY((H5Dread(dset_id, SUBF_HDF5_TYPE, H5S_BLOCK, H5S_ALL, dxpl_id, buf) >= 0),
"Dataset read succeeded");
for (size_t i = 0; i < (size_t)mpi_size; i++) {
@ -1969,6 +2011,7 @@ test_subfiling_h5fuse(void)
}
VRFY((H5Pclose(fapl_id) >= 0), "FAPL close succeeded");
VRFY((H5Pclose(dxpl_id) >= 0), "DXPL close succeeded");
mpi_code_g = MPI_Barrier(comm_g);
VRFY((mpi_code_g == MPI_SUCCESS), "MPI_Barrier succeeded");
@ -2132,9 +2175,6 @@ main(int argc, char **argv)
H5open();
/* Enable selection I/O using internal temporary workaround */
H5_use_selection_io_g = TRUE;
if (MAINPROCESS) {
HDprintf("Testing Subfiling VFD functionality\n");
}