mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-01-30 15:32:37 +08:00
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:
parent
4497feb575
commit
3236fb79ce
@ -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",
|
||||
|
@ -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]
|
||||
*
|
||||
*/
|
||||
|
@ -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:
|
||||
-----------------
|
||||
|
13
src/H5.c
13
src/H5.c
@ -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"));
|
||||
|
224
src/H5CX.c
224
src/H5CX.c
@ -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() */
|
||||
|
||||
|
@ -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);
|
||||
|
140
src/H5Dchunk.c
140
src/H5Dchunk.c
@ -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);
|
||||
|
@ -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() */
|
||||
|
@ -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)
|
||||
|
@ -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() */
|
||||
|
477
src/H5Dio.c
477
src/H5Dio.c
@ -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() */
|
||||
|
@ -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")
|
||||
}
|
||||
|
89
src/H5Dpkg.h
89
src/H5Dpkg.h
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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() */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
355
src/H5Pdxpl.c
355
src/H5Pdxpl.c
@ -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() */
|
||||
|
252
src/H5Ppublic.h
252
src/H5Ppublic.h
@ -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
|
||||
*
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
*
|
||||
|
101
src/H5Sselect.c
101
src/H5Sselect.c
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -337,6 +337,7 @@ set (H5_TESTS
|
||||
page_buffer
|
||||
dtypes
|
||||
dsets
|
||||
select_io_dset
|
||||
chunk_info # compression lib link
|
||||
cmpd_dset
|
||||
mdset
|
||||
|
@ -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 \
|
||||
|
@ -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");
|
||||
|
@ -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
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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
3786
testpar/t_select_io_dset.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user