diff options
author | Larry Knox <lrknox@hdfgroup.org> | 2023-08-08 16:06:05 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-08 16:06:05 (GMT) |
commit | f43d301f633b5e2cd9cde160ddb2c13578f9231f (patch) | |
tree | 3c05bb6a52a5cb19869721dab02e4931f6e48e39 /testpar | |
parent | 8ceb226bae916152510387da6f7f9710903882a8 (diff) | |
download | hdf5-f43d301f633b5e2cd9cde160ddb2c13578f9231f.zip hdf5-f43d301f633b5e2cd9cde160ddb2c13578f9231f.tar.gz hdf5-f43d301f633b5e2cd9cde160ddb2c13578f9231f.tar.bz2 |
Merge Implementation of the mpio driver with selection I/O. (#3360)
Diffstat (limited to 'testpar')
-rw-r--r-- | testpar/t_coll_chunk.c | 2 | ||||
-rw-r--r-- | testpar/t_dset.c | 2 | ||||
-rw-r--r-- | testpar/t_select_io_dset.c | 417 | ||||
-rw-r--r-- | testpar/t_vfd.c | 1805 |
4 files changed, 2139 insertions, 87 deletions
diff --git a/testpar/t_coll_chunk.c b/testpar/t_coll_chunk.c index fd77988..1ff7a8e 100644 --- a/testpar/t_coll_chunk.c +++ b/testpar/t_coll_chunk.c @@ -782,7 +782,7 @@ coll_chunktest(const char *filename, int chunk_factor, int select_factor, int ap 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)) { + if (facc_type == FACC_MPIO && (selection_io_mode == H5D_SELECTION_IO_MODE_OFF)) { switch (api_option) { case API_LINK_HARD: status = H5Pget(xfer_plist, H5D_XFER_COLL_CHUNK_LINK_HARD_NAME, &prop_value); diff --git a/testpar/t_dset.c b/testpar/t_dset.c index e401cd5..b75b6ae 100644 --- a/testpar/t_dset.c +++ b/testpar/t_dset.c @@ -3356,7 +3356,7 @@ actual_io_mode_tests(void) ret = H5Pclose(dxpl_id); VRFY((ret >= 0), "H5Pclose succeeded"); - if (selection_io_mode != H5D_SELECTION_IO_MODE_ON) { + if (selection_io_mode == H5D_SELECTION_IO_MODE_OFF) { test_actual_io_mode(TEST_ACTUAL_IO_NO_COLLECTIVE); /* diff --git a/testpar/t_select_io_dset.c b/testpar/t_select_io_dset.c index eb64bfe..daeacf0 100644 --- a/testpar/t_select_io_dset.c +++ b/testpar/t_select_io_dset.c @@ -128,6 +128,11 @@ typedef enum { #define TEST_TCONV_BUF_TOO_SMALL 0x008 #define TEST_IN_PLACE_TCONV 0x010 +/* Definitions used by test_bug_optimized_bufs() and test_bug_api_library() */ +#define DIMS 10000 +#define BIG_X_FACTOR 1048576 +#define BIG_Y_FACTOR 32 + /* * Helper routine to set dxpl * --selection I/O mode @@ -2960,6 +2965,8 @@ test_multi_dsets_all(int niter, hid_t fid, unsigned chunked, unsigned mwbuf) const void *wbufs[MULTI_NUM_DSETS]; void *rbufs[MULTI_NUM_DSETS]; + curr_nerrors = nerrors; + /* for n niter to ensure that all randomized dset_types with multi_dset_type_t will be covered */ for (n = 0; n < niter; n++) { @@ -3434,6 +3441,19 @@ test_no_selection_io_cause_mode(const char *filename, hid_t fapl, uint32_t test_ /* Datatype conversion */ if (test_mode & TEST_DATATYPE_CONVERSION) { + + /* With one exception, all will land at H5FD__mpio_read/write_selection(). + * As the xfer mode is H5FD_MPIO_INDEPENDENT, this will call + * H5FD__read/write_from_selection() triggering H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB. + */ + no_selection_io_cause_read_expected |= H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB; + + /* Exception case: This will turn off selection I/O landing at H5FD__mpio_write() */ + if ((test_mode & TEST_TCONV_BUF_TOO_SMALL) && !(test_mode & TEST_IN_PLACE_TCONV)) + no_selection_io_cause_write_expected |= H5D_SEL_IO_TCONV_BUF_TOO_SMALL; + else + no_selection_io_cause_write_expected |= H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB; + if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_ON) < 0) P_TEST_ERROR; tid = H5T_NATIVE_UINT; @@ -3443,18 +3463,12 @@ test_no_selection_io_cause_mode(const char *filename, hid_t fapl, uint32_t test_ if (H5Pset_buffer(dxpl, sizeof(int), NULL, NULL) < 0) P_TEST_ERROR; - /* If we're using in-place type conversion sel io will succeed */ if (test_mode & TEST_IN_PLACE_TCONV) { if (H5Pset_modify_write_buf(dxpl, TRUE) < 0) P_TEST_ERROR; } - else - no_selection_io_cause_write_expected |= H5D_SEL_IO_TCONV_BUF_TOO_SMALL; - /* In-place type conversion for read doesn't require modify_write_buf */ } - - /* If the tconv buf is largge enough sel io will succeed */ } /* Create 1d data space */ @@ -3521,6 +3535,31 @@ test_no_selection_io_cause_mode(const char *filename, hid_t fapl, uint32_t test_ static void test_get_no_selection_io_cause(const char *filename, hid_t fapl) { + hid_t dxpl = H5I_INVALID_HID; + H5D_selection_io_mode_t selection_io_mode; + + if (MAINPROCESS) { + printf("\n"); + TESTING("for H5Pget_no_selection_io_cause()"); + } + + curr_nerrors = nerrors; + + if ((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0) + P_TEST_ERROR; + if (H5Pget_selection_io(dxpl, &selection_io_mode) < 0) + P_TEST_ERROR; + if (H5Pclose(dxpl) < 0) + P_TEST_ERROR; + + /* The following tests are based on H5D_SELECTION_IO_MODE_DEFAULT as the + * default setting in the library; skip the tests if that is not true */ + if (selection_io_mode != H5D_SELECTION_IO_MODE_DEFAULT) { + if (MAINPROCESS) + SKIPPED(); + return; + } + test_no_selection_io_cause_mode(filename, fapl, TEST_DISABLE_BY_API); test_no_selection_io_cause_mode(filename, fapl, TEST_NOT_CONTIGUOUS_OR_CHUNKED_DATASET); test_no_selection_io_cause_mode(filename, fapl, TEST_DATATYPE_CONVERSION); @@ -3533,6 +3572,366 @@ test_get_no_selection_io_cause(const char *filename, hid_t fapl) return; } /* test_get_no_selection_io_cause() */ +/* + * This bug is exposed when running testpar/t_coll_md.c via testphdf5. + * + * Optimized bufs (bufs[1] is NULL) is used when passing as a parameter to the mpio driver + * for selection I/O. When computing mpi_bufs_base in that routine, it is not accounted + * for and therefore causing segmentation fault when running the test. + * + * Fix: + * Check for optimized bufs when computing mpi_bufs_base. + */ +static void +test_bug_optimized_bufs(const char *filename, hid_t fapl) +{ + hid_t dxpl = H5I_INVALID_HID; + hid_t dcpl = H5I_INVALID_HID; + hid_t fid = H5I_INVALID_HID; + hid_t did = H5I_INVALID_HID; + hid_t fspace_id = H5I_INVALID_HID; + hid_t mspace_id = H5I_INVALID_HID; + hsize_t dims[1]; + hsize_t cdims[1]; + hsize_t start[1]; + hsize_t stride[1]; + hsize_t count[1]; + hsize_t block[1]; + int *wbuf; + + if ((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + P_TEST_ERROR; + + if ((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) + P_TEST_ERROR; + + dims[0] = (hsize_t)mpi_size * (hsize_t)DIMS; + + fspace_id = H5Screate_simple(1, dims, NULL); + + cdims[0] = (hsize_t)mpi_size; + + if (H5Pset_chunk(dcpl, 1, cdims) < 0) + P_TEST_ERROR; + + if ((did = H5Dcreate2(fid, "bug_optimized_bufs", H5T_NATIVE_INT, fspace_id, H5P_DEFAULT, dcpl, + H5P_DEFAULT)) < 0) + P_TEST_ERROR; + + start[0] = (hsize_t)mpi_rank; + stride[0] = (hsize_t)mpi_size; + count[0] = DIMS; + block[0] = 1; + + if (H5Sselect_hyperslab(fspace_id, H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + if ((mspace_id = H5Screate_simple(1, count, NULL)) < 0) + P_TEST_ERROR; + + if ((wbuf = calloc(1, count[0] * sizeof(int))) == NULL) + P_TEST_ERROR; + + if ((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0) + P_TEST_ERROR; + + /* Enable collection transfer mode */ + if (H5Pset_dxpl_mpio(dxpl, H5FD_MPIO_COLLECTIVE) < 0) + P_TEST_ERROR; + + /* Enable selection I/O */ + if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_ON) < 0) + P_TEST_ERROR; + + if (H5Dwrite(did, H5T_NATIVE_INT, mspace_id, fspace_id, dxpl, wbuf) < 0) + P_TEST_ERROR; + + if (H5Dclose(did) < 0) + P_TEST_ERROR; + + if (H5Pclose(dcpl) < 0) + P_TEST_ERROR; + + if (H5Pclose(dxpl) < 0) + P_TEST_ERROR; + + if (H5Sclose(fspace_id) < 0) + P_TEST_ERROR; + + if (H5Sclose(mspace_id) < 0) + P_TEST_ERROR; + + if (H5Fclose(fid) < 0) + P_TEST_ERROR; + + return; + +} /* test_bug_optimized_bufs() */ + +/* + * The bug is exposed when running testpar/t_pread.c. + * + * The file is created with userblock. Before passing down to the mpio driver for + * selection I/O, the parameter offsets[] is added by base_addr (size of the uesrblock). + * For the independent case in the mpio driver for selection I/O, + * the intermediate routine for the API H5FDread/write_vector_from_selection() is called. + * The parameter offsets[] is passed as is to the intermediate routine which will + * be added again by base_addr causing incorrect data retrieval. + * + * Fix: + * The parameter offsets[] needs to be adjusted by the base_addr addition before calling + * the intermediate routine. + */ +static void +test_bug_base_addr(const char *filename, hid_t fapl) +{ + hid_t dxpl = H5I_INVALID_HID; + hid_t dxpl_read = H5I_INVALID_HID; + hid_t fid = H5I_INVALID_HID; + hid_t did = H5I_INVALID_HID; + hid_t sid = H5I_INVALID_HID; + hid_t fcpl = H5I_INVALID_HID; + hsize_t dims[1]; + hid_t tid = H5T_NATIVE_INT; + int wbuf[DSET_SELECT_DIM]; + int rbuf[DSET_SELECT_DIM]; + int i; + + /* Create user block */ + if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + P_TEST_ERROR; + + if (H5Pset_userblock(fcpl, 512) < 0) + P_TEST_ERROR; + + if ((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0) + P_TEST_ERROR; + + /* Create the file with userblock */ + if ((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0) + P_TEST_ERROR; + + /* Create 1d data space */ + dims[0] = DSET_SELECT_DIM; + + if ((sid = H5Screate_simple(1, dims, NULL)) < 0) + P_TEST_ERROR; + + if ((did = H5Dcreate2(fid, "bug_base_addr", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < + 0) + P_TEST_ERROR; + + /* Initialize data */ + for (i = 0; i < DSET_SELECT_DIM; i++) + wbuf[i] = i; + + if ((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0) + P_TEST_ERROR; + + /* Enable selection I/O */ + if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_ON) < 0) + P_TEST_ERROR; + + /* Independent by default and with selection I/O ON for reading */ + if ((dxpl_read = H5Pcopy(dxpl)) < 0) + P_TEST_ERROR; + + /* Enable collective and with selection I/O ON for writing */ + if (H5Pset_dxpl_mpio(dxpl, H5FD_MPIO_COLLECTIVE) < 0) + P_TEST_ERROR; + + if (H5Dwrite(did, tid, H5S_ALL, H5S_ALL, dxpl, wbuf) < 0) + P_TEST_ERROR; + + if (H5Dread(did, tid, H5S_ALL, H5S_ALL, dxpl_read, rbuf) < 0) + P_TEST_ERROR; + + if (H5Dclose(did) < 0) + P_TEST_ERROR; + + if (H5Pclose(dxpl) < 0) + P_TEST_ERROR; + + if (H5Pclose(dxpl_read) < 0) + P_TEST_ERROR; + + if (H5Sclose(sid) < 0) + P_TEST_ERROR; + + if (H5Pclose(fcpl) < 0) + P_TEST_ERROR; + + if (H5Fclose(fid) < 0) + P_TEST_ERROR; + return; + +} /* test_bug_base_addr() */ + +/* + * This bug is exposed when running testpar/t_2Gio.c with at least 2 processes. + * + * The root problem is from calling an API function from within the library i.e. + * calling H5FDread/write_vector_from_selection() for independent access in the + * mpio driver for selection I/O. + * + * The test scenario is described below with the test writing to a dataset + * via H5Dwrite(): + * --running with 2 processes + * --with selection I/O on + * --with COLLECTIVE xfer mode + * + * For process 1: + * The library internal calls H5D__write(): + * --io_info.use_select_io is ON + * --io_info.use_select_io is OFF after calling H5D__typeinfo_init_phase2() + * due to H5D_SEL_IO_TCONV_BUF_TOO_SMALL + * --H5D__mpio_opt_possible() returns 0 so xfer mode is set to + * H5FD_MPIO_INDEPENDENT + * The library eventually calls H5FD__mpio_write() performing scalar calls for the writes + * + * For process 0: + * The library internal calls H5D__write(): + * --io_info.use_select_io is ON + * --H5D__mpio_opt_possible() returns 0 so xfer mode is set to + * H5FD_MPIO_INDEPENDENT + * The library eventually calls H5FD__mpio_write_selection(): + * --since the xfer mode is INDEPENDENT it calls the API + * H5FDwrite_vector_from_selection(), which eventually calls + * H5FD__mpio_write_vector(). This routine obtains the + * xfer mode via API context which returns COLLECTIVE. + * Then the test hangs when trying to do MPI_File_set_view(). + * + * Fix: + * Create wrapper functions for the API H5FDread/write_vector_from_selection() and + * they will be called by H5FD__mpio_read/write_selection() for independent access. + * + */ +static void +test_bug_api_library(const char *filename, hid_t fapl) +{ + hid_t dxpl = H5I_INVALID_HID; + hid_t fid = H5I_INVALID_HID; + hid_t did = H5I_INVALID_HID; + hid_t sid = H5I_INVALID_HID; + hid_t fspace_id = H5I_INVALID_HID; + hid_t mspace_id = H5I_INVALID_HID; + hsize_t dims[2]; + hsize_t start[2]; + hsize_t stride[2]; + hsize_t count[2]; + hsize_t block[2]; + int *wbuf; + hsize_t i, j; + + if ((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + P_TEST_ERROR; + + dims[0] = (hsize_t)BIG_X_FACTOR; + dims[1] = (hsize_t)BIG_Y_FACTOR; + + if ((sid = H5Screate_simple(2, dims, NULL)) < 0) + P_TEST_ERROR; + + if ((did = H5Dcreate2(fid, "bug_coll_to_ind", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, + H5P_DEFAULT)) < 0) + P_TEST_ERROR; + + if ((wbuf = malloc((size_t)dims[0] * (size_t)dims[1] * sizeof(int))) == NULL) + P_TEST_ERROR; + + /* Each process takes a slabs of rows. */ + block[0] = (hsize_t)dims[0] / (hsize_t)mpi_size; + block[1] = (hsize_t)dims[1]; + stride[0] = block[0]; + stride[1] = block[1]; + count[0] = 1; + count[1] = 1; + start[0] = (hsize_t)mpi_rank * block[0]; + start[1] = 0; + + if ((fspace_id = H5Dget_space(did)) < 0) + P_TEST_ERROR; + if (MAINPROCESS) { + if (H5Sselect_none(fspace_id) < 0) + P_TEST_ERROR; + } /* end if */ + else { + if (H5Sselect_hyperslab(fspace_id, H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + } /* end else */ + + if ((mspace_id = H5Screate_simple(2, block, NULL)) < 0) + P_TEST_ERROR; + if (MAINPROCESS) { + if (H5Sselect_none(mspace_id) < 0) + P_TEST_ERROR; + } /* end if */ + + if ((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0) + P_TEST_ERROR; + + /* Enable collective transfer */ + if (H5Pset_dxpl_mpio(dxpl, H5FD_MPIO_COLLECTIVE) < 0) + P_TEST_ERROR; + + /* Enable selection I/O */ + if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_ON) < 0) + P_TEST_ERROR; + + /* Put some trivial data in wbuf */ + for (i = 0; i < block[0]; i++) { + for (j = 0; j < block[1]; j++) { + *wbuf = (int)((i + start[0]) * 100 + (j + start[1] + 1)); + wbuf++; + } + } + + /* With datatype conversion */ + if (H5Dwrite(did, H5T_NATIVE_UCHAR, mspace_id, fspace_id, dxpl, wbuf) < 0) + P_TEST_ERROR; + + if (H5Dclose(did) < 0) + P_TEST_ERROR; + + if (H5Pclose(dxpl) < 0) + P_TEST_ERROR; + + if (H5Sclose(fspace_id) < 0) + P_TEST_ERROR; + + if (H5Sclose(mspace_id) < 0) + P_TEST_ERROR; + + if (H5Fclose(fid) < 0) + P_TEST_ERROR; + + return; + +} /* test_bug_api_library() */ + +/* + * Verify bugs exposed when H5D_SELECTION_IO_MODE_ON is set as the + * default in the library. + */ +static void +test_bugs_select_on(const char *filename, hid_t fapl) +{ + if (MAINPROCESS) { + printf("\n"); + TESTING("to verify bugs exposed when H5D_SELECTION_IO_MODE_ON is set as library default"); + } + + curr_nerrors = nerrors; + + test_bug_optimized_bufs(filename, fapl); + test_bug_base_addr(filename, fapl); + test_bug_api_library(filename, fapl); + + CHECK_PASSED(); + return; + +} /* test_bugs_select_on() */ + /*------------------------------------------------------------------------- * Function: main * @@ -3740,12 +4139,10 @@ main(int argc, char *argv[]) if (H5Fclose(fid) < 0) P_TEST_ERROR; - if (MAINPROCESS) { - printf("\n"); - TESTING("Testing for H5Pget_no_selection_io_cause()"); - } test_get_no_selection_io_cause(FILENAME, fapl); + test_bugs_select_on(FILENAME, fapl); + /* Barrier to make sure all ranks are done before deleting the file, and * also to clean up output (make sure PASSED is printed before any of the * following messages) */ diff --git a/testpar/t_vfd.c b/testpar/t_vfd.c index 827faf4..5e9070d 100644 --- a/testpar/t_vfd.c +++ b/testpar/t_vfd.c @@ -100,6 +100,100 @@ static unsigned vector_write_test_6(int file_name_id, int mpi_rank, int mpi_size H5FD_mpio_collective_opt_t coll_opt_mode, const char *vfd_name); static unsigned vector_write_test_7(int file_name_id, int mpi_rank, int mpi_size, H5FD_mpio_xfer_t xfer_mode, H5FD_mpio_collective_opt_t coll_opt_mode, const char *vfd_name); +/* + * Tests for selection I/O: + * They are derived from test_selection_io() in test/vfd.c and modified for parallel testing. + */ + +/* + * Global declarations for selection I/O tests` + */ + +/* Number of errors */ +int nerrors = 0; +int curr_nerrors = 0; + +/* Test file name */ +#define SELECT_FNAME "mpio_select_test_file" + +/* Dimemsion sizes */ +#define SEL_IO_DIM0 4 +#define SEL_IO_DIM1 8 +int sel_dim0 = SEL_IO_DIM0; +int sel_dim1 = SEL_IO_DIM1; + +/* Write buffers */ +int *wbuf1 = NULL; +int *wbuf2 = NULL; +int *wbufs[2] = {NULL, NULL}; + +/* File buffers */ +int *fbuf1 = NULL; +int *fbuf2 = NULL; +int *fbufs[2] = {NULL, NULL}; /* Array of file buffers */ + +/* Expected read buffers */ +int *erbuf1 = NULL; +int *erbuf2 = NULL; +int *erbufs[2] = {NULL, NULL}; /* Array of expected read buffers */ + +/* iotypes for testing: + H5FD_MPIO_INDEPENDENT + H5FD_MPIO_COLLECTIVE + --H5FD_MPIO_COLLECTIVE_IO + --H5FD_MPIO_INDIVIDUAL_IO +*/ +#define iotypes 3 + +#define P_TEST_ERROR \ + do { \ + nerrors++; \ + H5_FAILED(); \ + AT(); \ + } while (0) + +#define CHECK_PASSED() \ + do { \ + int err_result = (nerrors > curr_nerrors); \ + \ + MPI_Allreduce(MPI_IN_PLACE, &err_result, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD); \ + \ + if (MAINPROCESS) { \ + if (err_result == 0) \ + PASSED(); \ + else \ + HDputs(" ***TEST FAILED***"); \ + } \ + } while (0) + +/* Utility functions for selection I/O */ +static herr_t test_selection_io_read_verify(hid_t dxpl, int mpi_rank, hsize_t start[], hsize_t block[], + H5FD_t *lf, H5FD_mem_t type, uint32_t count, hid_t mem_spaces[], + hid_t file_spaces[], haddr_t offsets[], size_t element_sizes[], + uint32_t rbufcount, int *erb[], hbool_t shorten_rbufs); + +static herr_t test_selection_io_write(hid_t dxpl, H5FD_t *lf, H5FD_mem_t type, uint32_t count, + hid_t mem_spaces[], hid_t file_spaces[], haddr_t offsets[], + size_t element_sizes[], int *wb[]); + +/* Test functions for selection I/O */ +static void test_selection_io(int mpi_rank, int mpi_size); +static void test_selection_io_real(int mpi_rank, int mpi_size, H5FD_t *lf, hid_t dxpl); +static void test_selection_io_types_1d(int mpi_rank, int mpi_size, H5FD_t *lf, hid_t dxpl, H5FD_mem_t type, + haddr_t addrs[], size_t element_sizes[], hid_t mem_spaces[], + hid_t file_spaces[], hsize_t dims1[]); +static void test_selection_io_types_2d(int mpi_rank, int mpi_size, H5FD_t *lf, hid_t dxpl, H5FD_mem_t type, + haddr_t addrs[], size_t element_sizes[], hid_t mem_spaces[], + hid_t file_spaces[], hsize_t dims2[]); +static void test_selection_io_types_1d_2d(int mpi_rank, int mpi_size, H5FD_t *lf, hid_t dxpl, H5FD_mem_t type, + haddr_t addrs[], size_t element_sizes[], hid_t mem_spaces[], + hid_t file_spaces[], hsize_t dims1[], hsize_t dims2[]); +static void test_selection_io_types_shorten(int mpi_rank, int mpi_size, H5FD_t *lf, hid_t dxpl, + H5FD_mem_t type, haddr_t addrs[], size_t element_sizes[], + hid_t mem_spaces[], hid_t file_spaces[], hsize_t dims1[], + hsize_t dims2[]); + +/****************************************************************************/ /****************************************************************************/ /***************************** Utility Functions ****************************/ @@ -4065,86 +4159,22 @@ vector_write_test_7(int file_name_id, int mpi_rank, int mpi_size, H5FD_mpio_xfer } /* vector_write_test_7() */ -/*------------------------------------------------------------------------- - * Function: main - * - * Purpose: Run parallel VFD tests. - * - * Return: Success: 0 - * - * Failure: 1 - * - *------------------------------------------------------------------------- - */ - -int -main(int argc, char **argv) +static void +test_vector_io(int mpi_rank, int mpi_size) { unsigned nerrs = 0; -#ifdef H5_HAVE_SUBFILING_VFD - int required = MPI_THREAD_MULTIPLE; - int provided = 0; -#endif - int mpi_size; - int mpi_rank = 0; - -#ifdef H5_HAVE_SUBFILING_VFD - if (MPI_SUCCESS != MPI_Init_thread(&argc, &argv, required, &provided)) { - printf(" MPI doesn't support MPI_Init_thread with MPI_THREAD_MULTIPLE. Exiting\n"); - goto finish; - } - - if (provided != required) { - printf(" MPI doesn't support MPI_Init_thread with MPI_THREAD_MULTIPLE. Exiting\n"); - goto finish; - } -#else - if (MPI_SUCCESS != MPI_Init(&argc, &argv)) { - printf(" MPI_Init failed. Exiting\n"); - goto finish; - } -#endif - - MPI_Comm_size(comm, &mpi_size); - MPI_Comm_rank(comm, &mpi_rank); - /* Attempt to turn off atexit post processing so that in case errors - * occur during the test and the process is aborted, it will not hang - * in the atexit post processing. If it does, it may try to make MPI - * calls which may not work. - */ - if (H5dont_atexit() < 0) - printf("%d:Failed to turn off atexit processing. Continue.\n", mpi_rank); - - H5open(); - - if (mpi_rank == 0) { - printf("=========================================\n"); - printf("Parallel virtual file driver (VFD) tests\n"); - printf(" mpi_size = %d\n", mpi_size); - printf("=========================================\n"); - } - - if (mpi_size < 2) { - if (mpi_rank == 0) - printf(" Need at least 2 processes. Exiting.\n"); - goto finish; - } - - alloc_and_init_file_images(mpi_size); + nerrs += alloc_and_init_file_images(mpi_size); if (!pass) { printf("\nAllocation and initialize of file image buffers failed. Test aborted.\n"); + nerrors += (int)nerrs; + return; } MPI_Barrier(comm); - if (mpi_rank == 0) { - - printf("\n\n --- TESTING MPIO VFD --- \n\n"); - } - nerrs += vector_read_test_1(0, mpi_rank, mpi_size, H5FD_MPIO_INDEPENDENT, H5FD_MPIO_INDIVIDUAL_IO, "mpio"); nerrs += vector_read_test_1(0, mpi_rank, mpi_size, H5FD_MPIO_COLLECTIVE, H5FD_MPIO_INDIVIDUAL_IO, "mpio"); @@ -4312,18 +4342,1643 @@ main(int argc, char **argv) H5FD_SUBFILING_NAME); #endif + nerrors += (int)nerrs; + + /* return(nerrs);*/ + +} /* test_vector_io() */ + +/* + * Utility routine to perform the actual selection I/O read + */ +static herr_t +test_selection_io_read_verify(hid_t dxpl, int mpi_rank, hsize_t start[], hsize_t block[], H5FD_t *lf, + H5FD_mem_t type, uint32_t count, hid_t mem_spaces[], hid_t file_spaces[], + haddr_t offsets[], size_t element_sizes[], uint32_t rbufcount, int *erb[], + hbool_t shorten_rbufs) +{ + int *rbuf1 = NULL; + int *rbuf2 = NULL; + int *rbufs[2] = {NULL, NULL}; + size_t bufsize; + int i; + int j; + + bufsize = (hsize_t)(sel_dim0 * sel_dim1) * sizeof(int); + if ((rbuf1 = malloc(bufsize)) == NULL) + goto error; + if ((rbuf2 = malloc(bufsize)) == NULL) + goto error; + rbufs[0] = rbuf1; + rbufs[1] = rbuf2; + + /* Initialize read buffer */ + for (i = 0; i < (int)rbufcount; i++) + for (j = 0; j < sel_dim0 * sel_dim1; j++) + rbufs[i][j] = -1; + + /* Handle elements in count that are not part of rbufcount */ + for (i = (int)rbufcount; i < (int)count; i++) + if (shorten_rbufs) + rbufs[i] = NULL; + else + rbufs[i] = rbufs[rbufcount - 1]; + + /* Issue read call */ + if (H5FDread_selection(lf, type, dxpl, count, mem_spaces, file_spaces, offsets, element_sizes, + (void **)rbufs) < 0) + goto error; + + /* Verify result */ + for (i = 0; i < (int)rbufcount; i++) { + hsize_t endblock = MIN((start[i] + block[i]), (hsize_t)(sel_dim0 * sel_dim1)); + for (j = (int)start[i]; j < (int)endblock; j++) + if (rbufs[i][j] != erb[i][j]) { + H5_FAILED(); + AT(); + printf( + "data read from file does not match expected values at mapping array location %d: %d\n", + i, mpi_rank); + printf("expected data: \n"); + for (j = 0; j < sel_dim0 * sel_dim1; j++) { + printf("%6d", erb[i][j]); + if (!((j + 1) % sel_dim1)) + printf("\n"); + } + printf("read data: \n"); + for (j = 0; j < (sel_dim0 * sel_dim1); j++) { + printf("%6d", rbufs[i][j]); + if (!((j + 1) % sel_dim1)) + printf("\n"); + } + goto error; + } + } + + if (rbuf1) + free(rbuf1); + if (rbuf2) + free(rbuf2); + return 0; + +error: + if (rbuf1) + free(rbuf1); + if (rbuf2) + free(rbuf2); + return -1; + +} /* end test_selection_io_read_verify() */ + +/* + * Utility routine to perform the actual selection I/O write + */ +static herr_t +test_selection_io_write(hid_t dxpl, H5FD_t *lf, H5FD_mem_t type, uint32_t count, hid_t mem_spaces[], + hid_t file_spaces[], haddr_t offsets[], size_t element_sizes[], int *wb[]) +{ + const void **bufs = NULL; /* Avoids cast/const warnings */ + int i; + int j; + + if (NULL == (bufs = calloc(count, sizeof(void *)))) + goto error; + + /* Update write buffer */ + for (i = 0; i < (int)count; i++) { + if (wb[i] && (i == 0 || wb[i] != wb[i - 1])) + for (j = 0; j < (sel_dim0 * sel_dim1); j++) + wb[i][j] += 2 * (sel_dim0 * sel_dim1); + bufs[i] = wb[i]; + } + + /* Issue write call */ + if (H5FDwrite_selection(lf, type, dxpl, count, mem_spaces, file_spaces, offsets, element_sizes, bufs) < 0) + goto error; + + if (bufs) + free(bufs); + + return 0; + +error: + if (bufs) + free(bufs); + return -1; + +} /* end test_selection_io_write() */ + +/* + * Perform the following tests that use shortened arrays for wbuf and element sizes + * --Test 1: Strided <> Strided 1D and 2D I/O for both file and memory spaces + * --Reset selections + * --Test 2: Strided <> Strided 2D I/O, 2 different selections in the same memory buffer + * --Reset selections + */ +static void +test_selection_io_types_shorten(int mpi_rank, int mpi_size, H5FD_t *lf, hid_t dxpl, H5FD_mem_t type, + haddr_t addrs[], size_t element_sizes[], hid_t mem_spaces[], + hid_t file_spaces[], hsize_t dims1[], hsize_t dims2[]) +{ + hsize_t start[2]; /* start for hyperslab */ + hsize_t stride[2]; /* stride for hyperslab */ + hsize_t count[2]; /* count for hyperslab */ + hsize_t block[2]; /* block for hyperslab */ + hsize_t verify_start[2] = {0, 0}; /* Starting block for verified data */ + hsize_t verify_block[2] = {0, 0}; /* Block size for verified data */ + int i; + int j; + int i2; + int j2; + + int shorten_element_sizes; /* Whether to shorten the element sizes array */ + + for (shorten_element_sizes = 0; shorten_element_sizes <= 1; shorten_element_sizes++) { + /* + * Test 1: Strided <> Strided 1D and 2D I/O + */ + /* sel_dim1 must be even */ + assert(sel_dim1 / 2 == (sel_dim1 + 1) / 2); + + /* Strided selection in memory (1D) */ + block[0] = 1; + count[0] = (hsize_t)(((sel_dim0 * sel_dim1) / 2) / mpi_size); + stride[0] = 2; + start[0] = (hsize_t)mpi_rank * stride[0] * count[0]; + if (H5Sselect_hyperslab(mem_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + verify_start[0] = start[0]; + verify_block[0] = (count[0] * stride[0]); + + /* Strided selection in file (1D) */ + start[0] = 1 + ((hsize_t)mpi_rank * stride[0] * count[0]); + if (H5Sselect_hyperslab(file_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Strided selection (across dim 1) in file (2D) */ + block[0] = 1; + block[1] = 1; + count[0] = (hsize_t)(sel_dim0 / mpi_size); + count[1] = (hsize_t)sel_dim1 / 2; + stride[0] = 1; + stride[1] = 2; + start[0] = (hsize_t)mpi_rank * count[0]; + start[1] = 1; + if (H5Sselect_hyperslab(file_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Strided selection (across dim 0) in memory (2D) */ + block[0] = 1; + block[1] = 1; + count[0] = (hsize_t)((sel_dim0 / 2) / mpi_size); + count[1] = (hsize_t)sel_dim1; + stride[0] = 2; + stride[1] = 1; + start[0] = 1 + ((hsize_t)mpi_rank * stride[0] * count[0]); + start[1] = 0; + if (H5Sselect_hyperslab(mem_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + verify_start[1] = start[0] * count[1]; + verify_block[1] = (count[0] * count[1] * stride[0]); + + /* Issue write call */ + if (test_selection_io_write(dxpl, lf, type, 2, mem_spaces, file_spaces, addrs, element_sizes, + (int **)wbufs) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* Update file bufs */ + for (i = 0; i < (sel_dim0 * sel_dim1) / 2; i++) + fbuf1[(2 * i) + 1] = wbuf1[2 * i]; + for (i = 1, i2 = 0, j2 = 1; i < sel_dim0; i += 2) + for (j = 0; j < sel_dim1; j++) { + assert(i2 < sel_dim0); + fbuf2[i2 * sel_dim1 + j2] = wbuf2[i * sel_dim1 + j]; + j2 += 2; + if (j2 >= sel_dim1) { + i2++; + j2 = 1; + } + } + + /* Update expected read bufs */ + for (i = 0; i < (sel_dim0 * sel_dim1); i++) + erbuf1[i] = -1; + for (i = 0; i < (sel_dim0 * sel_dim1) / 2; i++) + erbuf1[2 * i] = wbuf1[2 * i]; + for (i = 0; i < sel_dim0; i++) + for (j = 0; j < sel_dim1; j++) + erbuf2[i * sel_dim1 + j] = -1; + for (i = 1; i < sel_dim0; i += 2) + for (j = 0; j < sel_dim1; j++) + erbuf2[i * sel_dim1 + j] = wbuf2[i * sel_dim1 + j]; + + /* Read and verify */ + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 2, mem_spaces, + file_spaces, addrs, element_sizes, 2, (int **)erbufs, FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Reset selections + */ + if (H5Sselect_all(mem_spaces[0]) < 0) + P_TEST_ERROR; + if (H5Sselect_all(file_spaces[0]) < 0) + P_TEST_ERROR; + + /* Each process takes x number of elements */ + block[0] = dims1[0] / (hsize_t)mpi_size; + count[0] = 1; + stride[0] = block[0]; + start[0] = (hsize_t)mpi_rank * block[0]; + + verify_start[0] = start[0]; + verify_block[0] = block[0]; + + if (H5Sselect_hyperslab(mem_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + if (H5Sselect_hyperslab(file_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + if (H5Sselect_all(mem_spaces[1]) < 0) + P_TEST_ERROR; + if (H5Sselect_all(file_spaces[1]) < 0) + P_TEST_ERROR; + + /* Each process takes x number of elements */ + block[0] = dims2[0] / (hsize_t)mpi_size; + block[1] = dims2[1]; + count[0] = 1; + count[1] = 1; + stride[0] = block[0]; + stride[1] = block[1]; + start[0] = (hsize_t)mpi_rank * block[0]; + start[1] = 0; + + verify_start[1] = start[0] * block[1]; + verify_block[1] = (block[0] * block[1]); + + if (H5Sselect_hyperslab(mem_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + if (H5Sselect_hyperslab(file_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Read entire file buffer and verify */ + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 2, mem_spaces, + file_spaces, addrs, element_sizes, 2, (int **)fbufs, FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Test 2: Strided <> Strided 2D I/O, 2 different selections in the same memory buffer + */ + /* Switch mem and file spaces to both be 2D */ + if (H5Sset_extent_simple(mem_spaces[0], 2, dims2, NULL) < 0) + P_TEST_ERROR; + if (H5Sset_extent_simple(file_spaces[0], 2, dims2, NULL) < 0) + P_TEST_ERROR; + + /* Strided selection in memory (1st) */ + block[0] = 1; + block[1] = 1; + count[0] = (hsize_t)((sel_dim0 / 2) / mpi_size); + count[1] = (hsize_t)sel_dim1; + stride[0] = 2; + stride[1] = 1; + start[0] = (hsize_t)mpi_rank * count[0] * stride[0]; + start[1] = 0; + + if (H5Sselect_hyperslab(mem_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + verify_start[0] = start[0] * count[1]; + verify_block[0] = (count[0] * count[1] * stride[0]); + + /* Strided selection (across dim 0) in memory (2nd) */ + start[0] = 1 + ((hsize_t)mpi_rank * count[0] * stride[0]); + if (H5Sselect_hyperslab(mem_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + verify_start[1] = start[0] * count[1]; + verify_block[1] = (count[0] * count[1] * stride[0]); + + /* Strided selection in file (1st) */ + block[0] = 1; + block[1] = 1; + count[0] = (hsize_t)(sel_dim0 / mpi_size); + count[1] = (hsize_t)sel_dim1 / 2; + stride[0] = 1; + stride[1] = 2; + start[0] = (hsize_t)mpi_rank * count[0]; + start[1] = 0; + if (H5Sselect_hyperslab(file_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Strided selection (across dim 1) in file (2nd) */ + block[0] = 1; + block[1] = 1; + count[0] = (hsize_t)(sel_dim0 / mpi_size); + count[1] = (hsize_t)sel_dim1 / 2; + stride[0] = 1; + stride[1] = 2; + start[0] = (hsize_t)mpi_rank * count[0]; + start[1] = 1; + if (H5Sselect_hyperslab(file_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Use the same memory buffer for both selections */ + wbufs[0] = wbuf2; + + /* Shorten wbuf array */ + if (shorten_element_sizes) + wbufs[1] = NULL; + else + wbufs[1] = wbufs[0]; + + /* Issue write call */ + if (test_selection_io_write(dxpl, lf, type, 2, mem_spaces, file_spaces, addrs, element_sizes, + (int **)wbufs) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* Update file bufs - need to reuse 1D array so data stays consistent, so use math to + * find 1D index into 2D array */ + for (i = 0, i2 = 0, j2 = 0; i < sel_dim0; i += 2) + for (j = 0; j < sel_dim1; j++) { + assert(i2 < sel_dim0); + fbuf1[(i2 * sel_dim1) + j2] = wbuf2[i * sel_dim1 + j]; + j2 += 2; + if (j2 >= sel_dim1) { + i2++; + j2 = 0; + } + } + for (i = 1, i2 = 0, j2 = 1; i < sel_dim0; i += 2) + for (j = 0; j < sel_dim1; j++) { + assert(i2 < sel_dim0); + fbuf2[i2 * sel_dim1 + j2] = wbuf2[i * sel_dim1 + j]; + j2 += 2; + if (j2 >= sel_dim1) { + i2++; + j2 = 1; + } + } + + /* Update expected read buf */ + for (i = 0; i < sel_dim0; i++) + for (j = 0; j < sel_dim1; j++) + erbuf2[i * sel_dim1 + j] = -1; + for (i = 0; i < sel_dim0; i += 2) + for (j = 0; j < sel_dim1; j++) + erbuf2[i * sel_dim1 + j] = wbuf2[i * sel_dim1 + j]; + for (i = 1; i < sel_dim0; i += 2) + for (j = 0; j < sel_dim1; j++) + erbuf2[i * sel_dim1 + j] = wbuf2[i * sel_dim1 + j]; + + /* Read and verify */ + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 2, mem_spaces, + file_spaces, addrs, element_sizes, 1, (int **)&erbufs[1], + shorten_element_sizes ? TRUE : FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Reset selections + */ + if (H5Sselect_all(mem_spaces[0]) < 0) + P_TEST_ERROR; + if (H5Sselect_all(file_spaces[0]) < 0) + P_TEST_ERROR; + + if (H5Sselect_all(mem_spaces[1]) < 0) + P_TEST_ERROR; + if (H5Sselect_all(file_spaces[1]) < 0) + P_TEST_ERROR; + + /* Each process takes x number of elements */ + block[0] = dims2[0] / (hsize_t)mpi_size; + block[1] = dims2[1]; + count[0] = 1; + count[1] = 1; + stride[0] = block[0]; + stride[1] = block[1]; + start[0] = (hsize_t)mpi_rank * block[0]; + start[1] = 0; + + if (H5Sselect_hyperslab(mem_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + if (H5Sselect_hyperslab(file_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + if (H5Sselect_hyperslab(mem_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + if (H5Sselect_hyperslab(file_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Read entire file buffer and verify */ + verify_start[0] = start[0] * block[1]; + verify_block[0] = (block[0] * block[1]); + verify_start[1] = start[0] * block[1]; + verify_block[1] = (block[0] * block[1]); + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 2, mem_spaces, + file_spaces, addrs, element_sizes, 2, (int **)fbufs, FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* Reset first spaces to 1D */ + if (H5Sset_extent_simple(mem_spaces[0], 1, dims1, NULL) < 0) + P_TEST_ERROR; + if (H5Sset_extent_simple(file_spaces[0], 1, dims1, NULL) < 0) + P_TEST_ERROR; + + /* Reset write buffer array */ + wbufs[0] = wbuf1; + wbufs[1] = wbuf2; + + /* Change to shortened element sizes array */ + element_sizes[1] = 0; + + MPI_Barrier(comm); + } + + /* Reset element sizes array */ + element_sizes[1] = element_sizes[0]; + + return; + +} /* test_selection_io_types_shorten() */ + +/* + * Perform the following tests for 1 & 2 dimensional spaces: + * --Test 1: Strided 1D (memory) <> Strided 2D (file) I/O + * --Reset selections + * --Test 2: Strided 2D (memory) <> Strided 1D (file) I/O + * --Reset selections + */ +static void +test_selection_io_types_1d_2d(int mpi_rank, int mpi_size, H5FD_t *lf, hid_t dxpl, H5FD_mem_t type, + haddr_t addrs[], size_t element_sizes[], hid_t mem_spaces[], + hid_t file_spaces[], hsize_t dims1[], hsize_t dims2[]) +{ + hsize_t start[2]; /* start for hyperslab */ + hsize_t stride[2]; /* stride for hyperslab */ + hsize_t count[2]; /* count for hyperslab */ + hsize_t block[2]; /* block for hyperslab */ + hsize_t verify_start[2] = {0, 0}; /* Starting block for verified data */ + hsize_t verify_block[2] = {0, 0}; /* Block size for verified data */ + int i; + int j; + int i2; + int j2; + + /* + * Test 1: Strided 1D (memory) <> Strided 2D (file) I/O + */ + /* Strided selection (across dim 1) in file */ + block[0] = 1; + block[1] = 1; + count[0] = (hsize_t)(sel_dim0 / mpi_size); + count[1] = (hsize_t)sel_dim1 / 2; + stride[0] = 1; + stride[1] = 2; + start[0] = (hsize_t)mpi_rank * count[0]; + start[1] = 1; + if (H5Sselect_hyperslab(file_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Strided selection in memory */ + block[0] = 1; + count[0] = (hsize_t)(((sel_dim0 * sel_dim1) / 2) / mpi_size); + stride[0] = 2; + start[0] = 1 + ((hsize_t)mpi_rank * stride[0] * count[0]); + if (H5Sselect_hyperslab(mem_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Issue write call */ + if (test_selection_io_write(dxpl, lf, type, 1, &mem_spaces[0], &file_spaces[1], &addrs[1], element_sizes, + (int **)&wbufs[0]) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* Update file buf */ + for (i = 1, i2 = 0, j2 = 1; i < (sel_dim0 * sel_dim1); i += 2) { + assert(i2 < sel_dim0); + fbuf2[(i2 * sel_dim1) + j2] = wbuf1[i]; + j2 += 2; + if (j2 >= sel_dim1) { + i2++; + j2 = 1; + } + } + + /* Update expected read buf */ + for (i = 0; i < (sel_dim0 * sel_dim1); i++) + erbuf1[i] = -1; + for (i = 1; i < (sel_dim0 * sel_dim1); i += 2) + erbuf1[i] = wbuf1[i]; + + /* Read and verify */ + verify_start[0] = start[0]; + verify_block[0] = (count[0] * stride[0]); + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[0], + &file_spaces[1], &addrs[1], element_sizes, 1, (int **)&erbufs[0], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Reset selections + */ + if (H5Sselect_all(file_spaces[1]) < 0) + P_TEST_ERROR; + + if (H5Sselect_all(mem_spaces[0]) < 0) + P_TEST_ERROR; + + block[0] = dims2[0] / (hsize_t)mpi_size; + block[1] = dims2[1]; + count[0] = 1; + count[1] = 1; + stride[0] = block[0]; + stride[1] = block[1]; + start[0] = (hsize_t)mpi_rank * block[0]; + start[1] = 0; + if (H5Sselect_hyperslab(file_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + block[0] = dims1[0] / (hsize_t)mpi_size; + count[0] = 1; + stride[0] = block[0]; + start[0] = (hsize_t)mpi_rank * block[0]; + if (H5Sselect_hyperslab(mem_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Read entire file buffer and verify */ + verify_start[0] = start[0]; + verify_block[0] = block[0]; + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[0], + &file_spaces[1], &addrs[1], element_sizes, 1, (int **)&fbufs[1], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Test 2: Strided 2D (memory) <> Strided 1D (file) I/O + */ + /* Strided selection in file */ + block[0] = 1; + count[0] = (hsize_t)(((sel_dim0 * sel_dim1) / 2) / mpi_size); + stride[0] = 2; + start[0] = (hsize_t)mpi_rank * stride[0] * count[0]; + if (H5Sselect_hyperslab(file_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Strided selection (across dim 0) in memory */ + block[0] = 1; + block[1] = 1; + count[0] = (hsize_t)((sel_dim0 / 2) / mpi_size); + count[1] = (hsize_t)sel_dim1; + stride[0] = 2; + stride[1] = 1; + start[0] = (hsize_t)mpi_rank * count[0] * stride[0]; + start[1] = 0; + if (H5Sselect_hyperslab(mem_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Issue write call */ + if (test_selection_io_write(dxpl, lf, type, 1, &mem_spaces[1], &file_spaces[0], &addrs[0], element_sizes, + (int **)&wbufs[1]) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* Update file buf */ + for (i = 0, i2 = 0; i < sel_dim0; i += 2) + for (j = 0; j < sel_dim1; j++) { + assert(i2 < (sel_dim0 * sel_dim1)); + fbuf1[i2] = wbuf2[i * sel_dim1 + j]; + i2 += 2; + } + + /* Update expected read buf */ + for (i = 0; i < sel_dim0; i++) + for (j = 0; j < sel_dim1; j++) + erbuf2[(i * sel_dim1) + j] = -1; + for (i = 0; i < sel_dim0; i += 2) + for (j = 0; j < sel_dim1; j++) + erbuf2[(i * sel_dim1) + j] = wbuf2[i * sel_dim1 + j]; + + /* Read and verify */ + verify_start[0] = start[0] * count[1]; + verify_block[0] = (count[0] * count[1] * stride[0]); + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[1], + &file_spaces[0], &addrs[0], element_sizes, 1, (int **)&erbufs[1], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Reset selections + */ + if (H5Sselect_all(file_spaces[0]) < 0) + P_TEST_ERROR; + + if (H5Sselect_all(mem_spaces[1]) < 0) + P_TEST_ERROR; + + /* Each process takes x number of elements */ + block[0] = dims1[0] / (hsize_t)mpi_size; + count[0] = 1; + stride[0] = block[0]; + start[0] = (hsize_t)mpi_rank * block[0]; + if (H5Sselect_hyperslab(file_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Each process takes x number of elements */ + block[0] = dims2[0] / (hsize_t)mpi_size; + block[1] = dims2[1]; + count[0] = 1; + count[1] = 1; + stride[0] = block[0]; + stride[1] = block[1]; + start[0] = (hsize_t)mpi_rank * block[0]; + start[1] = 0; + if (H5Sselect_hyperslab(mem_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Read entire file buffer and verify */ + verify_start[0] = start[0] * block[1]; + verify_block[0] = (block[0] * block[1]); + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[1], + &file_spaces[0], &addrs[0], element_sizes, 1, (int **)&fbufs[0], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + return; + +} /* test_selection_io_types_1d_2d() */ + +/* + * Perform the following tests for 2 dimensional spaces: + * --Test 1: Simple 2D contiguous I/O for both file and memory spaces + * --Test 2: Strided (memory) <> Contiguous(file) 2D I/O + * --Reset selections + * --Test 3: Contiguous (memory) <> Strided (file) 2D I/O + * --Reset selections + * --Test 4: Strided (memory) <> Strided (file) 2D I/O + * --Reset selections + */ +static void +test_selection_io_types_2d(int mpi_rank, int mpi_size, H5FD_t *lf, hid_t dxpl, H5FD_mem_t type, + haddr_t addrs[], size_t element_sizes[], hid_t mem_spaces[], hid_t file_spaces[], + hsize_t dims2[]) +{ + hsize_t start[2]; /* start for hyperslab */ + hsize_t stride[2]; /* stride for hyperslab */ + hsize_t count[2]; /* count for hyperslab */ + hsize_t block[2]; /* block for hyperslab */ + hsize_t verify_start[2] = {0, 0}; /* Starting block for verified data */ + hsize_t verify_block[2] = {0, 0}; /* Block size for verified data */ + int i; + int j; + int i2; + int j2; + + /* + * Test 1: Simple 2D contiguous I/O + */ + + /* Contiguous selection in file and memory */ + block[0] = dims2[0] / (hsize_t)mpi_size; + block[1] = dims2[1]; + count[0] = 1; + count[1] = 1; + stride[0] = block[0]; + stride[1] = block[1]; + start[0] = (hsize_t)mpi_rank * block[0]; + start[1] = 0; + + if (H5Sselect_hyperslab(file_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + if (H5Sselect_hyperslab(mem_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + if (test_selection_io_write(dxpl, lf, type, 1, &mem_spaces[1], &file_spaces[1], &addrs[1], element_sizes, + (int **)&wbufs[1]) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* Update file buf */ + for (i = 0; i < sel_dim0; i++) + for (j = 0; j < sel_dim1; j++) + fbuf2[(i * sel_dim1) + j] = wbuf2[(i * sel_dim1) + j]; + + /* Read and verify */ + verify_start[0] = start[0] * block[1]; + verify_block[0] = (block[0] * block[1]); + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[1], + &file_spaces[1], &addrs[1], element_sizes, 1, (int **)&fbufs[1], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Test 2: Strided (memory) <> Contiguous(file) 2D I/O + */ + /* Contiguous selection in file */ + count[0] = (hsize_t)((sel_dim0 / 2) / mpi_size); + count[1] = (hsize_t)sel_dim1; + start[0] = 1 + ((hsize_t)mpi_rank * count[0]); + start[1] = 0; + if (H5Sselect_hyperslab(file_spaces[1], H5S_SELECT_SET, start, NULL, count, NULL) < 0) + P_TEST_ERROR; + + /* Strided selection in memory */ + block[0] = 1; + block[1] = 1; + stride[0] = 2; + stride[1] = 1; + start[0] = 1 + ((hsize_t)mpi_rank * stride[0] * count[0]); + start[1] = 0; + if (H5Sselect_hyperslab(mem_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Issue write call */ + if (test_selection_io_write(dxpl, lf, type, 1, &mem_spaces[1], &file_spaces[1], &addrs[1], element_sizes, + (int **)&wbufs[1]) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* Update file buf */ + for (i = 0; i < sel_dim0 / 2; i++) + for (j = 0; j < sel_dim1; j++) { + fbuf2[((i + 1) * sel_dim1) + j] = wbuf2[(((2 * i) + 1) * sel_dim1) + j]; + } + + /* Update expected read buf */ + for (i = 0; i < sel_dim0; i++) + for (j = 0; j < sel_dim1; j++) + erbuf2[(i * sel_dim1) + j] = -1; + for (i = 0; i < sel_dim0 / 2; i++) + for (j = 0; j < sel_dim1; j++) + erbuf2[(((2 * i) + 1) * sel_dim1) + j] = wbuf2[(((2 * i) + 1) * sel_dim1) + j]; + + /* Read and verify */ + verify_start[0] = start[0] * count[1]; + verify_block[0] = (count[0] * count[1] * stride[0]); + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[1], + &file_spaces[1], &addrs[1], element_sizes, 1, (int **)&erbufs[1], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Reset selections + */ + if (H5Sselect_all(mem_spaces[1]) < 0) + P_TEST_ERROR; + if (H5Sselect_all(file_spaces[1]) < 0) + P_TEST_ERROR; + + block[0] = dims2[0] / (hsize_t)mpi_size; + block[1] = dims2[1]; + count[0] = 1; + count[1] = 1; + stride[0] = block[0]; + stride[1] = block[1]; + start[0] = (hsize_t)mpi_rank * block[0]; + start[1] = 0; + + if (H5Sselect_hyperslab(mem_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + if (H5Sselect_hyperslab(file_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Read entire file buffer and verify */ + verify_start[0] = start[0] * block[1]; + verify_block[0] = (block[0] * block[1]); + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[1], + &file_spaces[1], &addrs[1], element_sizes, 1, (int **)&fbufs[1], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Test 3: Contiguous (memory) <> Strided (file) 2D I/O + */ + + /* Strided selection in file */ + block[0] = 1; + block[1] = 1; + count[0] = (hsize_t)(sel_dim0 / mpi_size); + count[1] = (hsize_t)sel_dim1 / 2; + stride[0] = 1; + stride[1] = 2; + start[0] = (hsize_t)mpi_rank * count[0]; + start[1] = 1; + if (H5Sselect_hyperslab(file_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Contiguous selection in memory */ + if (H5Sselect_hyperslab(mem_spaces[1], H5S_SELECT_SET, start, NULL, count, NULL) < 0) + P_TEST_ERROR; + + /* Issue write call */ + if (test_selection_io_write(dxpl, lf, type, 1, &mem_spaces[1], &file_spaces[1], &addrs[1], element_sizes, + (int **)&wbufs[1]) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* Update file buf */ + for (i = 0; i < sel_dim0; i++) + for (j = 0; j < sel_dim1 / 2; j++) + fbuf2[i * sel_dim1 + (2 * j) + 1] = wbuf2[i * sel_dim1 + (j + 1)]; + + /* Update expected read buf */ + for (i = 0; i < sel_dim0; i++) + for (j = 0; j < sel_dim1; j++) + erbuf2[i * sel_dim1 + j] = -1; + for (i = 0; i < sel_dim0; i++) + for (j = 0; j < sel_dim1 / 2; j++) + erbuf2[i * sel_dim1 + (j + 1)] = wbuf2[i * sel_dim1 + (j + 1)]; + + /* Read and verify */ + verify_start[0] = start[0] * count[1] * stride[1]; + verify_block[0] = (count[0] * count[1] * stride[1]); + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[1], + &file_spaces[1], &addrs[1], element_sizes, 1, (int **)&erbufs[1], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Reset selections + */ + if (H5Sselect_all(mem_spaces[1]) < 0) + P_TEST_ERROR; + if (H5Sselect_all(file_spaces[1]) < 0) + P_TEST_ERROR; + + block[0] = dims2[0] / (hsize_t)mpi_size; + block[1] = dims2[1]; + count[0] = 1; + count[1] = 1; + stride[0] = block[0]; + stride[1] = block[1]; + start[0] = (hsize_t)mpi_rank * block[0]; + start[1] = 0; + + if (H5Sselect_hyperslab(mem_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + if (H5Sselect_hyperslab(file_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Read entire file buffer and verify */ + verify_start[0] = start[0] * block[1]; + verify_block[0] = (block[0] * block[1]); + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[1], + &file_spaces[1], &addrs[1], element_sizes, 1, (int **)&fbufs[1], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Test 4: Strided (memory) <> Strided (file) 2D I/O + */ + /* sel_dim0 and sel_dim1 must be even */ + assert(sel_dim0 / 2 == (sel_dim0 + 1) / 2); + assert(sel_dim1 / 2 == (sel_dim1 + 1) / 2); + + /* Strided selection (across dim 0) in file */ + block[0] = 1; + block[1] = 1; + count[0] = (hsize_t)((sel_dim0 / 2) / mpi_size); + count[1] = (hsize_t)sel_dim1; + stride[0] = 2; + stride[1] = 1; + start[0] = 1 + ((hsize_t)mpi_rank * count[0] * stride[0]); + start[1] = 0; + if (H5Sselect_hyperslab(file_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Strided selection (across dim 1) in memory */ + block[0] = 1; + block[1] = 1; + count[0] = (hsize_t)(sel_dim0 / mpi_size); + count[1] = (hsize_t)sel_dim1 / 2; + stride[0] = 1; + stride[1] = 2; + start[0] = (hsize_t)mpi_rank * count[0]; + start[1] = 1; + if (H5Sselect_hyperslab(mem_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Issue write call */ + if (test_selection_io_write(dxpl, lf, type, 1, &mem_spaces[1], &file_spaces[1], &addrs[1], element_sizes, + (int **)&wbufs[1]) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* Update file buf */ + for (i = 0, i2 = 1, j2 = 0; i < sel_dim0; i++) + for (j = 1; j < sel_dim1; j += 2) { + assert(i2 < sel_dim0); + fbuf2[i2 * sel_dim1 + j2] = wbuf2[i * sel_dim1 + j]; + if (++j2 == sel_dim1) { + i2 += 2; + j2 = 0; + } + } + + /* Update expected read buf */ + for (i = 0; i < sel_dim0; i++) + for (j = 0; j < sel_dim1; j++) + erbuf2[i * sel_dim1 + j] = -1; + for (i = 0; i < sel_dim0; i++) + for (j = 1; j < sel_dim1; j += 2) + erbuf2[i * sel_dim1 + j] = wbuf2[i * sel_dim1 + j]; + /* Read and verify */ + verify_start[0] = start[0] * count[1] * stride[1]; + verify_block[0] = (count[0] * count[1] * stride[1]); + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[1], + &file_spaces[1], &addrs[1], element_sizes, 1, (int **)&erbufs[1], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Reset selections + */ + if (H5Sselect_all(file_spaces[1]) < 0) + P_TEST_ERROR; + if (H5Sselect_all(mem_spaces[1]) < 0) + P_TEST_ERROR; + + block[0] = dims2[0] / (hsize_t)mpi_size; + block[1] = dims2[1]; + count[0] = 1; + count[1] = 1; + stride[0] = block[0]; + stride[1] = block[1]; + start[0] = (hsize_t)mpi_rank * block[0]; + start[1] = 0; + + if (H5Sselect_hyperslab(file_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + if (H5Sselect_hyperslab(mem_spaces[1], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Read entire file buffer and verify */ + verify_start[0] = start[0] * block[1]; + verify_block[0] = (block[0] * block[1]); + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[1], + &file_spaces[1], &addrs[1], element_sizes, 1, (int **)&fbufs[1], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + return; + +} /* test_selection_io_types_2d() */ + +/* + * Perform the following tests for 1 dimensional spaces: + * --Test 1: Simple 1D contiguous I/O in both file and memory spaces + * --Test 2: Strided (memory) <> Contiguous (file) 1D I/O + * --Reset selections + * --Test 3: Contiguous (memory) <> Strided (file) 1D I/O + * --Reset selections + * --Test 4: Strided (memory) <> Strided 1D (file) I/O + * --Reset selections + */ +static void +test_selection_io_types_1d(int mpi_rank, int mpi_size, H5FD_t *lf, hid_t dxpl, H5FD_mem_t type, + haddr_t addrs[], size_t element_sizes[], hid_t mem_spaces[], hid_t file_spaces[], + hsize_t dims1[]) +{ + hsize_t start[2]; /* start for hyperslab */ + hsize_t stride[2]; /* stride for hyperslab */ + hsize_t count[2]; /* count for hyperslab */ + hsize_t block[2]; /* block for hyperslab */ + hsize_t verify_start[2] = {0, 0}; /* Starting block for verified data */ + hsize_t verify_block[2] = {0, 0}; /* Block size for verified data */ + int i; + + /* + * Test 1: Simple 1D contiguous I/O + */ + + /* Contiguous selection in file and memory */ + block[0] = dims1[0] / (hsize_t)mpi_size; + count[0] = 1; + stride[0] = block[0]; + start[0] = (hsize_t)mpi_rank * block[0]; + + if (H5Sselect_hyperslab(mem_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + if (H5Sselect_hyperslab(file_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Issue write call */ + if (test_selection_io_write(dxpl, lf, type, 1, &mem_spaces[0], &file_spaces[0], &addrs[0], element_sizes, + (int **)&wbufs[0]) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* Update file buf */ + for (i = 0; i < sel_dim0 * sel_dim1; i++) + fbuf1[i] = wbuf1[i]; + + /* Read and verify */ + verify_start[0] = start[0]; + verify_block[0] = block[0]; + + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[0], + &file_spaces[0], &addrs[0], element_sizes, 1, (int **)&fbufs[0], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Test 2: Strided (memory) <> Contiguous (file) 1D I/O + */ + /* sel_dim1 must be even */ + assert(sel_dim1 / 2 == (sel_dim1 + 1) / 2); + + /* Contiguous selection in file */ + count[0] = (hsize_t)(((sel_dim0 * sel_dim1) / 2) / mpi_size); + start[0] = 1 + ((hsize_t)mpi_rank * count[0]); + if (H5Sselect_hyperslab(file_spaces[0], H5S_SELECT_SET, start, NULL, count, NULL) < 0) + P_TEST_ERROR; + + /* Strided selection in memory */ + block[0] = 1; + stride[0] = 2; + start[0] = 1 + ((hsize_t)mpi_rank * stride[0] * count[0]); + if (H5Sselect_hyperslab(mem_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Issue write call */ + if (test_selection_io_write(dxpl, lf, type, 1, &mem_spaces[0], &file_spaces[0], &addrs[0], element_sizes, + (int **)&wbufs[0]) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* Update file buf */ + for (i = 0; i < (sel_dim0 * sel_dim1) / 2; i++) + fbuf1[i + 1] = wbuf1[(2 * i) + 1]; + + /* Update expected read buf */ + for (i = 0; i < (sel_dim0 * sel_dim1); i++) + erbuf1[i] = -1; + for (i = 0; i < (sel_dim0 * sel_dim1) / 2; i++) + erbuf1[(2 * i) + 1] = wbuf1[(2 * i) + 1]; + + /* Read and verify */ + verify_start[0] = start[0]; + verify_block[0] = (count[0] * stride[0]); + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[0], + &file_spaces[0], &addrs[0], element_sizes, 1, (int **)&erbufs[0], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Reset selections + */ + if (H5Sselect_all(mem_spaces[0]) < 0) + P_TEST_ERROR; + if (H5Sselect_all(file_spaces[0]) < 0) + P_TEST_ERROR; + + block[0] = dims1[0] / (hsize_t)mpi_size; + count[0] = 1; + stride[0] = block[0]; + start[0] = (hsize_t)mpi_rank * block[0]; + + if (H5Sselect_hyperslab(mem_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + if (H5Sselect_hyperslab(file_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Read entire file buffer and verify */ + verify_start[0] = start[0]; + verify_block[0] = block[0]; + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[0], + &file_spaces[0], &addrs[0], element_sizes, 1, (int **)&fbufs[0], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Test 3: Contiguous (memory) <> Strided (file) 1D I/O + */ + /* sel_dim1 must be even */ + assert(sel_dim1 / 2 == (sel_dim1 + 1) / 2); + + /* Strided selection in file */ + block[0] = 1; + count[0] = (hsize_t)(((sel_dim0 * sel_dim1) / 2) / mpi_size); /* count is this value from twice above */ + stride[0] = 2; /* stride is this value from twice above */ + start[0] = 1 + ((hsize_t)mpi_rank * stride[0] * count[0]); + if (H5Sselect_hyperslab(file_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Contiguous selection in memory */ + start[0] = 1 + ((hsize_t)mpi_rank * count[0]); + if (H5Sselect_hyperslab(mem_spaces[0], H5S_SELECT_SET, start, NULL, count, NULL) < 0) + P_TEST_ERROR; + + /* Issue write call */ + if (test_selection_io_write(dxpl, lf, type, 1, &mem_spaces[0], &file_spaces[0], &addrs[0], element_sizes, + (int **)&wbufs[0]) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* Update file buf */ + for (i = 0; i < (sel_dim0 * sel_dim1) / 2; i++) + fbuf1[(2 * i) + 1] = wbuf1[i + 1]; + + /* Update expected read buf */ + for (i = 0; i < (sel_dim0 * sel_dim1); i++) + erbuf1[i] = -1; + for (i = 0; i < (sel_dim0 * sel_dim1) / 2; i++) + erbuf1[i + 1] = wbuf1[i + 1]; + + /* Read and verify */ + verify_start[0] = start[0]; + verify_block[0] = count[0]; + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[0], + &file_spaces[0], &addrs[0], element_sizes, 1, (int **)&erbufs[0], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Reset selections + */ + if (H5Sselect_all(mem_spaces[0]) < 0) + P_TEST_ERROR; + if (H5Sselect_all(file_spaces[0]) < 0) + P_TEST_ERROR; + + block[0] = dims1[0] / (hsize_t)mpi_size; + count[0] = 1; + stride[0] = block[0]; + start[0] = (hsize_t)mpi_rank * block[0]; + + if (H5Sselect_hyperslab(mem_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + if (H5Sselect_hyperslab(file_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Read entire file buffer and verify */ + verify_start[0] = start[0]; + verify_block[0] = block[0]; + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[0], + &file_spaces[0], &addrs[0], element_sizes, 1, (int **)&fbufs[0], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Test 4: Strided (memory) <> Strided 1D (file) I/O + */ + /* sel_dim1 must be even */ + assert(sel_dim1 / 2 == (sel_dim1 + 1) / 2); + + /* Strided selection in file */ + block[0] = 1; + count[0] = (hsize_t)(((sel_dim0 * sel_dim1) / 2) / mpi_size); + stride[0] = 2; + start[0] = 0 + ((hsize_t)mpi_rank * stride[0] * count[0]); + if (H5Sselect_hyperslab(file_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Strided selection in memory */ + start[0] = 1 + ((hsize_t)mpi_rank * stride[0] * count[0]); + if (H5Sselect_hyperslab(mem_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Issue write call */ + if (test_selection_io_write(dxpl, lf, type, 1, &mem_spaces[0], &file_spaces[0], &addrs[0], element_sizes, + (int **)&wbufs[0]) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* Update file buf */ + for (i = 0; i < (sel_dim0 * sel_dim1) / 2; i++) + fbuf1[2 * i] = wbuf1[(2 * i) + 1]; + + /* Update expected read buf */ + for (i = 0; i < (sel_dim0 * sel_dim1); i++) + erbuf1[i] = -1; + for (i = 0; i < (sel_dim0 * sel_dim1) / 2; i++) + erbuf1[(2 * i) + 1] = wbuf1[(2 * i) + 1]; + + /* Read and verify */ + verify_start[0] = start[0]; + verify_block[0] = (count[0] * stride[0]); + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[0], + &file_spaces[0], &addrs[0], element_sizes, 1, (int **)&erbufs[0], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + /* + * Reset selections + */ + if (H5Sselect_all(mem_spaces[0]) < 0) + P_TEST_ERROR; + if (H5Sselect_all(file_spaces[0]) < 0) + P_TEST_ERROR; + + block[0] = dims1[0] / (hsize_t)mpi_size; + count[0] = 1; + stride[0] = block[0]; + start[0] = (hsize_t)mpi_rank * block[0]; + + if (H5Sselect_hyperslab(mem_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + if (H5Sselect_hyperslab(file_spaces[0], H5S_SELECT_SET, start, stride, count, block) < 0) + P_TEST_ERROR; + + /* Read entire file buffer and verify */ + verify_start[0] = start[0]; + verify_block[0] = block[0]; + if (test_selection_io_read_verify(dxpl, mpi_rank, verify_start, verify_block, lf, type, 1, &mem_spaces[0], + &file_spaces[0], &addrs[0], element_sizes, 1, (int **)&fbufs[0], + FALSE) < 0) + P_TEST_ERROR; + + MPI_Barrier(comm); + + return; + +} /* test_selection_io_types_1d() */ + +/* + * Perform the following tests for selection I/O: + * + * test_selection_io_types_1d(): + * ---Selection I/O tests for 1 dimensional spaces + * test_selection_io_types_2d() + * ---Selection I/O tests for 2 dimensional spaces + * test_selection_io_types_1d_2d() + * ---Selection I/O tests for 1 & 2 dimensional spaces + * test_selection_io_types_shorten() + * --Selection I/O tests that use shortened arrays for wbuf and element sizes + */ +static void +test_selection_io_real(int mpi_rank, int mpi_size, H5FD_t *lf, hid_t dxpl) +{ + hid_t mem_spaces[2] = {H5I_INVALID_HID, H5I_INVALID_HID}; /* memory dataspaces vector */ + hid_t file_spaces[2] = {H5I_INVALID_HID, H5I_INVALID_HID}; /* file dataspaces vector */ + hsize_t dims1[1]; /* 1d dimension sizes */ + hsize_t dims2[2]; /* 2d dimension sizes */ + + H5FD_mem_t type; /* File type */ + haddr_t addrs[2]; /* File allocation address */ + size_t element_sizes[2] = {sizeof(int), sizeof(int)}; /* Element size */ + size_t bufsize; /* Buffer size */ + int i; + int j; + + curr_nerrors = nerrors; + + /* + * Default dimension sizes for mpi_size 1 or 2: + * int sel_dim0 = SELECT_IO_DIM0; + * int sel_dim1 = SELECT_IO_DIM1; + */ + if (mpi_size >= 3) { + sel_dim0 = mpi_size * 2; + sel_dim1 = mpi_size * 4; + } + + dims1[0] = (hsize_t)(sel_dim0 * sel_dim1); + dims2[0] = (hsize_t)sel_dim0, dims2[1] = (hsize_t)sel_dim1; + + /* Create dataspaces - location 0 will be 1D and location 1 will be 2D */ + if ((mem_spaces[0] = H5Screate_simple(1, dims1, NULL)) < 0) + P_TEST_ERROR; + if ((mem_spaces[1] = H5Screate_simple(2, dims2, NULL)) < 0) + P_TEST_ERROR; + if ((file_spaces[0] = H5Screate_simple(1, dims1, NULL)) < 0) + P_TEST_ERROR; + if ((file_spaces[1] = H5Screate_simple(2, dims2, NULL)) < 0) + P_TEST_ERROR; + + /* Initialize global buffers: + * --wbuf1, wbuf2: write buffers + * --fbuf1, fbuf1: expected file buffers + * --erbuf1, erbuf2: expected read buffers + */ + bufsize = (size_t)(sel_dim0 * sel_dim1) * sizeof(int); + + if ((wbuf1 = malloc(bufsize)) == NULL) + P_TEST_ERROR; + + if ((wbuf2 = malloc(bufsize)) == NULL) + P_TEST_ERROR; + + wbufs[0] = wbuf1; + wbufs[1] = wbuf2; + + if ((fbuf1 = malloc(bufsize)) == NULL) + P_TEST_ERROR; + + if ((fbuf2 = malloc(bufsize)) == NULL) + P_TEST_ERROR; + + fbufs[0] = fbuf1; + fbufs[1] = fbuf2; + + if ((erbuf1 = malloc(bufsize)) == NULL) + P_TEST_ERROR; + + if ((erbuf2 = malloc(bufsize)) == NULL) + P_TEST_ERROR; + + erbufs[0] = erbuf1; + erbufs[1] = erbuf2; + + /* Initialize data */ + for (i = 0; i < sel_dim0; i++) + for (j = 0; j < sel_dim1; j++) { + wbuf1[(i * sel_dim1) + j] = (i * sel_dim1) + j; + wbuf2[(i * sel_dim1) + j] = (i * sel_dim1) + j + (sel_dim0 * sel_dim1); + } + + /* Loop over memory types */ + for (type = 1; type < H5FD_MEM_NTYPES; type++) { + + addrs[0] = H5FDalloc(lf, type, H5P_DEFAULT, (sizeof(int) * (hsize_t)sel_dim0 * (hsize_t)sel_dim1)); + addrs[1] = H5FDalloc(lf, type, H5P_DEFAULT, (sizeof(int) * (hsize_t)sel_dim0 * (hsize_t)sel_dim1)); + + test_selection_io_types_1d(mpi_rank, mpi_size, lf, dxpl, type, addrs, element_sizes, mem_spaces, + file_spaces, dims1); + test_selection_io_types_2d(mpi_rank, mpi_size, lf, dxpl, type, addrs, element_sizes, mem_spaces, + file_spaces, dims2); + test_selection_io_types_1d_2d(mpi_rank, mpi_size, lf, dxpl, type, addrs, element_sizes, mem_spaces, + file_spaces, dims1, dims2); + test_selection_io_types_shorten(mpi_rank, mpi_size, lf, dxpl, type, addrs, element_sizes, mem_spaces, + file_spaces, dims1, dims2); + + } /* end for */ + + /* Close dataspaces */ + for (i = 0; i < 2; i++) { + if (H5Sclose(mem_spaces[i]) < 0) + P_TEST_ERROR; + if (H5Sclose(file_spaces[i]) < 0) + P_TEST_ERROR; + } + + /* Free the buffers */ + if (wbuf1) + free(wbuf1); + if (wbuf2) + free(wbuf2); + if (fbuf1) + free(fbuf1); + if (fbuf2) + free(fbuf2); + if (erbuf1) + free(erbuf1); + if (erbuf2) + free(erbuf2); + + CHECK_PASSED(); + + return; + +} /* test_selection_io_real() */ + +/* + * These tests for selection I/O are derived from test_selection_io() in + * test/vfd.c and modified for parallel testing. + */ +static void +test_selection_io(int mpi_rank, int mpi_size) +{ + H5FD_t *lf = NULL; /* VFD struct ptr */ + hid_t fapl = H5I_INVALID_HID; /* File access property list */ + char filename[1024]; /* Test file name */ + unsigned flags = 0; /* File access flags */ + + unsigned collective; /* Types of I/O for testing */ + hid_t dxpl = H5I_INVALID_HID; /* Dataset transfer property list */ + hid_t def_dxpl = H5I_INVALID_HID; /* dxpl: independent access */ + hid_t col_xfer_dxpl = H5I_INVALID_HID; /* dxpl: collective access with collective I/O */ + hid_t ind_io_dxpl = H5I_INVALID_HID; /* dxpl: collective access with individual I/O */ + + /* If I use fapl in this call, I got an environment printout */ + h5_fixname(SELECT_FNAME, H5P_DEFAULT, filename, sizeof(filename)); + + if ((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) + P_TEST_ERROR; + + if (H5Pset_fapl_mpio(fapl, comm, info) < 0) + P_TEST_ERROR; + + /* Create file */ + flags = H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC; + + if (NULL == (lf = H5FDopen(filename, flags, fapl, HADDR_UNDEF))) + P_TEST_ERROR; + + /* Default dxpl which will be H5FD_MPIO_INDEPENDENT by default */ + def_dxpl = H5Pcreate(H5P_DATASET_XFER); + + /* Set dxpl for collective access which will have H5FD_MPIO_COLLECTIVE_IO as default */ + if ((col_xfer_dxpl = H5Pcopy(def_dxpl)) < 0) + P_TEST_ERROR; + if (H5Pset_dxpl_mpio(col_xfer_dxpl, H5FD_MPIO_COLLECTIVE) < 0) + P_TEST_ERROR; + + /* Set dxpl for H5FD_MPIO_INDIVIDUAL_IO */ + if ((ind_io_dxpl = H5Pcopy(col_xfer_dxpl)) < 0) + P_TEST_ERROR; + if (H5Pset_dxpl_mpio_collective_opt(ind_io_dxpl, H5FD_MPIO_INDIVIDUAL_IO) < 0) + P_TEST_ERROR; + + for (collective = 0; collective < iotypes; collective++) { + // for (collective = 0; collective < 1; collective++) { + if (collective) + dxpl = collective == 1 ? col_xfer_dxpl : ind_io_dxpl; + else + dxpl = def_dxpl; + + if (MAINPROCESS) { + if (collective) { + if (collective == 1) + printf(" Testing with Collective access: collective I/O "); + else + printf(" Testing with Collective_access: Individual I/O "); + } + else + printf(" Testing with Independent access "); + } + + /* Perform the actual tests */ + test_selection_io_real(mpi_rank, mpi_size, lf, dxpl); + } + + /* Close file */ + if (H5FDclose(lf) < 0) + P_TEST_ERROR; + + /* Close the fapl */ + if (H5Pclose(fapl) < 0) + P_TEST_ERROR; + + if (H5Pclose(def_dxpl) < 0) + P_TEST_ERROR; + if (H5Pclose(col_xfer_dxpl) < 0) + P_TEST_ERROR; + if (H5Pclose(ind_io_dxpl) < 0) + P_TEST_ERROR; + + // if (MAINPROCESS && HDremove(filename) < 0) + // P_TEST_ERROR; + +} /* test_selection_io() */ + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: Run parallel VFD tests. + * + * Return: Success: 0 + * + * Failure: 1 + * + *------------------------------------------------------------------------- + */ + +int +main(int argc, char **argv) +{ + +#ifdef H5_HAVE_SUBFILING_VFD + int required = MPI_THREAD_MULTIPLE; + int provided = 0; +#endif + int mpi_size; + int mpi_rank; + int ret; + +#ifdef H5_HAVE_SUBFILING_VFD + if (MPI_SUCCESS != MPI_Init_thread(&argc, &argv, required, &provided)) { + printf(" MPI doesn't support MPI_Init_thread with MPI_THREAD_MULTIPLE. Exiting\n"); + goto finish; + } + + if (provided != required) { + printf(" MPI doesn't support MPI_Init_thread with MPI_THREAD_MULTIPLE. Exiting\n"); + goto finish; + } +#else + if (MPI_SUCCESS != MPI_Init(&argc, &argv)) { + printf(" MPI_Init failed. Exiting\n"); + goto finish; + } +#endif + + MPI_Comm_size(comm, &mpi_size); + MPI_Comm_rank(comm, &mpi_rank); + + /* Attempt to turn off atexit post processing so that in case errors + * occur during the test and the process is aborted, it will not hang + * in the atexit post processing. If it does, it may try to make MPI + * calls which may not work. + */ + if (H5dont_atexit() < 0) + printf("%d:Failed to turn off atexit processing. Continue.\n", mpi_rank); + + H5open(); + + if (mpi_rank == 0) { + printf("=========================================\n"); + printf("Parallel virtual file driver (VFD) tests\n"); + printf(" mpi_size = %d\n", mpi_size); + printf("=========================================\n"); + } + + MPI_Barrier(comm); + + if (mpi_rank == 0) + printf("\n --- TESTING MPIO VFD: selection I/O --- \n"); + + test_selection_io(mpi_rank, mpi_size); + + if (mpi_rank == 0) + printf("\n --- TESTING MPIO VFD: vector I/O --- \n"); + + if (mpi_size < 2) { + if (mpi_rank == 0) { + printf(" Need at least 2 processes to run tests for vector I/O."); + SKIPPED(); + } + printf("\n"); + goto finish; + } + + test_vector_io(mpi_rank, mpi_size); + finish: /* make sure all processes are finished before final report, cleanup * and exit. */ MPI_Barrier(comm); - if (mpi_rank == 0) { /* only process 0 reports */ - printf("===================================\n"); - if (nerrs > 0) - printf("***vfd tests detected %d failures***\n", nerrs); + /* Gather errors from all processes */ + MPI_Allreduce(&nerrors, &ret, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD); + nerrors = ret; + + if (MAINPROCESS) { + printf("\n===================================\n"); + if (nerrors) + printf("***Parallel vfd tests detected %d errors***\n", nerrors); else - printf("vfd tests finished with no failures\n"); + printf("Parallel vfd tests finished with no errors\n"); printf("===================================\n"); } @@ -4337,6 +5992,6 @@ finish: MPI_Finalize(); /* cannot just return (nerrs) because exit code is limited to 1byte */ - return (nerrs > 0); + return (nerrors != 0); } /* main() */ |