From 48e075110624e0039b1918a7187316366a20462b Mon Sep 17 00:00:00 2001 From: Robb Matzke Date: Fri, 13 Mar 1998 12:50:38 -0500 Subject: [svn-r321] Changes since 19980306 ---------------------- ./MANIFEST ./src/H5D.c ./src/H5S.c ./src/H5Sprivate.h ./src/H5Ssimp.c ./src/H5Tpkg.h ./src/H5Tprivate.h ./src/H5V.c ./test/Makefile.in ./test/iopipe.c [NEW] Optimizations to the I/O pipeline. ./src/H5Fistore.c ./src/H5Oefl.c Fixed a few compiler warnings. ./MANIFEST Added entries for ./config/{intel-osf1,irix5.3} --- MANIFEST | 3 + src/H5D.c | 77 +++++++++++++-- src/H5Distore.c | 2 + src/H5Fistore.c | 2 + src/H5Oefl.c | 4 +- src/H5S.c | 3 + src/H5Sprivate.h | 20 ++++ src/H5Ssimp.c | 215 ++++++++++++++++++++++++++++++++++++++++ src/H5Tpkg.h | 2 - src/H5Tprivate.h | 7 ++ src/H5V.c | 29 +++--- test/Makefile.in | 23 ++++- test/iopipe.c | 293 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 653 insertions(+), 27 deletions(-) create mode 100644 test/iopipe.c diff --git a/MANIFEST b/MANIFEST index c5a2ada..771e466 100644 --- a/MANIFEST +++ b/MANIFEST @@ -20,6 +20,8 @@ ./config/depend.in ./config/freebsd2.2.1 ./config/hpux10.20 +./config/intel-osf1 +./config/irix5.3 ./config/irix6.2 ./config/irix64 ./config/linux @@ -170,6 +172,7 @@ ./test/extend.c ./test/external.c ./test/hyperslab.c +./test/iopipe.c ./test/istore.c ./test/testhdf5.c ./test/testhdf5.h diff --git a/src/H5D.c b/src/H5D.c index ead898f..b417ca7 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -31,6 +31,12 @@ static char RcsId[] = "@(#)$Revision$"; #define PABLO_MASK H5D_mask /* + * Define this to be zero or one depending on whether the I/O pipeline should + * be optimized. + */ +#define H5D_OPTIMIZE_PIPE 1 + +/* * A dataset is the following struct. */ struct H5D_t { @@ -807,7 +813,7 @@ H5D_create(H5F_t *f, const char *name, const H5T_t *type, const H5S_t *space, } /* Create (open for write access) an object header */ - if (H5O_create(f, 0, &(new_dset->ent)) < 0) { + if (H5O_create(f, 80, &(new_dset->ent)) < 0) { HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to create dataset object header"); } @@ -1090,6 +1096,7 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, H5S_number_t numbering; /*element numbering info*/ H5T_cdata_t *cdata = NULL; /*type conversion data */ herr_t ret_value = FAIL; + herr_t status; FUNC_ENTER(H5D_read, FAIL); @@ -1140,10 +1147,36 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, * Compute the size of the request and allocate scratch buffers. */ nelmts = H5S_get_npoints(mem_space); + + /* + * If there is no type conversion then try reading directly into the + * application's buffer. + */ + if (H5D_OPTIMIZE_PIPE && + H5T_conv_noop==tconv_func && + NULL!=sconv_func->read) { +#ifndef NDEBUG + fprintf (stderr, "HDF5-DIAG: Trying I/O pipe optimization...\n"); +#endif + status = (sconv_func->read)(dataset->ent.file, &(dataset->layout), + &(dataset->create_parms->efl), + H5T_get_size (dataset->type), file_space, + mem_space, buf/*out*/); + if (status>=0) goto succeed; +#ifndef NDEBUG + fprintf (stderr, "HDF5-DIAG: I/O pipe optimization failed\n"); +#endif + H5E_clear (); + } + + + /* + * This is the general case. + */ #ifndef LATER /* * Note: this prototype version allocates a buffer large enough to - * satisfy the entire request; strip mining is not implemented. + * satisfy the entire request; strip mining is not implemented. */ { size_t src_size = nelmts * H5T_get_size(dataset->type); @@ -1152,7 +1185,6 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, if (cdata->need_bkg) bkg_buf = H5MM_xmalloc (dst_size); } #endif - /* * Gather the data from disk into the data type conversion buffer. Also * gather data from application to background buffer (this step is not @@ -1192,9 +1224,12 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, &numbering, 0, nelmts, buf/*out*/)<0) { HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "scatter failed"); } + + + succeed: ret_value = SUCCEED; - done: + done: if (src_id >= 0) H5A_dec_ref(src_id); if (dst_id >= 0) H5A_dec_ref(dst_id); tconv_buf = H5MM_xfree(tconv_buf); @@ -1233,7 +1268,7 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, const H5S_conv_t *sconv_func = NULL; /*space conversion funcs*/ H5S_number_t numbering; /*element numbering info*/ H5T_cdata_t *cdata = NULL; /*type conversion data */ - herr_t ret_value = FAIL; + herr_t ret_value = FAIL, status; FUNC_ENTER(H5D_write, FAIL); @@ -1284,6 +1319,32 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, * Compute the size of the request and allocate scratch buffers. */ nelmts = H5S_get_npoints(mem_space); + + /* + * If there is no type conversion then try writing directly from + * application buffer to file. + */ + if (H5D_OPTIMIZE_PIPE && + H5T_conv_noop==tconv_func && + NULL!=sconv_func->write) { +#ifndef NDEBUG + fprintf (stderr, "HDF5-DIAG: Trying I/O pipe optimization...\n"); +#endif + status = (sconv_func->write)(dataset->ent.file, &(dataset->layout), + &(dataset->create_parms->efl), + H5T_get_size (dataset->type), file_space, + mem_space, buf); + if (status>=0) goto succeed; +#ifndef NDEBUG + fprintf (stderr, "HDF5-DIAG: I/O pipe optimization failed\n"); +#endif + H5E_clear (); + } + + + /* + * This is the general case. + */ #ifndef LATER /* * Note: This prototype version allocates a buffer large enough to @@ -1296,8 +1357,6 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, if (cdata->need_bkg) bkg_buf = H5MM_xmalloc (dst_size); } #endif - - /* * Gather data from application buffer into the data type conversion * buffer. Also gather data from the file into the background buffer @@ -1338,9 +1397,11 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, &numbering, 0, nelmts, tconv_buf)<0) { HGOTO_ERROR (H5E_DATASET, H5E_WRITEERROR, FAIL, "scatter failed"); } + + succeed: ret_value = SUCCEED; - done: + done: if (src_id >= 0) H5A_dec_ref(src_id); if (dst_id >= 0) H5A_dec_ref(dst_id); tconv_buf = H5MM_xfree(tconv_buf); diff --git a/src/H5Distore.c b/src/H5Distore.c index eeed99c..25b81b2 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -835,7 +835,9 @@ herr_t H5F_istore_create(H5F_t *f, H5O_layout_t *layout /*out */ ) { H5F_istore_ud1_t udata; +#ifndef NDEBUG int i; +#endif FUNC_ENTER(H5F_istore_create, FAIL); diff --git a/src/H5Fistore.c b/src/H5Fistore.c index eeed99c..25b81b2 100644 --- a/src/H5Fistore.c +++ b/src/H5Fistore.c @@ -835,7 +835,9 @@ herr_t H5F_istore_create(H5F_t *f, H5O_layout_t *layout /*out */ ) { H5F_istore_ud1_t udata; +#ifndef NDEBUG int i; +#endif FUNC_ENTER(H5F_istore_create, FAIL); diff --git a/src/H5Oefl.c b/src/H5Oefl.c index 1b3fa6a..5f2db2a 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -373,7 +373,7 @@ H5O_efl_read (H5F_t *f, const H5O_efl_t *efl, haddr_t *addr, size_t size, uint8 *buf) { int i, fd=-1; - size_t to_read, cur, skip; + size_t to_read, cur, skip=0; ssize_t n; herr_t ret_value = FAIL; @@ -458,7 +458,7 @@ H5O_efl_write (H5F_t *f, const H5O_efl_t *efl, haddr_t *addr, size_t size, const uint8 *buf) { int i, fd=-1; - size_t to_write, cur, skip; + size_t to_write, cur, skip=0; herr_t ret_value = FAIL; FUNC_ENTER (H5O_efl_write, FAIL); diff --git a/src/H5S.c b/src/H5S.c index d3a1ff9..c371e4b 100644 --- a/src/H5S.c +++ b/src/H5S.c @@ -538,6 +538,7 @@ H5S_get_npoints_max(const H5S_t *ds) FUNC_LEAVE(ret_value); } + /*------------------------------------------------------------------------- * Function: H5Sget_ndims @@ -1310,6 +1311,8 @@ H5S_find (const H5S_t *mem_space, const H5S_t *file_space) _conv.mscat = H5S_simp_mscat; _conv.mgath = H5S_simp_mgath; _conv.fscat = H5S_simp_fscat; + _conv.read = H5S_simp_read; + _conv.write = H5S_simp_write; conv = &_conv; } diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index c8a3aae..fbce725 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -88,6 +88,18 @@ typedef struct H5S_tconv_t { const struct H5O_efl_t *efl, size_t elmt_size, const H5S_t *file_space, const H5S_number_t *numbering, size_t start, size_t nelmts, const void *tconv_buf); + + /* Read from file to application w/o intermediate scratch buffer */ + herr_t (*read)(H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_efl_t *efl, size_t elmt_size, + const H5S_t *file_space, const H5S_t *mem_space, + void *buf/*out*/); + + /* Write directly from app buffer to file */ + herr_t (*write)(H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_efl_t *efl, size_t elmt_size, + const H5S_t *file_space, const H5S_t *mem_space, + const void *buf); } H5S_conv_t; H5S_t *H5S_copy (const H5S_t *src); @@ -125,4 +137,12 @@ herr_t H5S_simp_fscat (H5F_t *f, const struct H5O_layout_t *layout, const struct H5O_efl_t *efl, size_t elmt_size, const H5S_t *file_space, const H5S_number_t *numbering, size_t start, size_t nelmts, const void *tconv_buf); +herr_t H5S_simp_read (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_efl_t *efl, size_t elmt_size, + const H5S_t *file_space, const H5S_t *mem_space, + void *buf/*out*/); +herr_t H5S_simp_write (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_efl_t *efl, size_t elmt_size, + const H5S_t *file_space, const H5S_t *mem_space, + const void *buf); #endif diff --git a/src/H5Ssimp.c b/src/H5Ssimp.c index ee2d680..6f1f498 100644 --- a/src/H5Ssimp.c +++ b/src/H5Ssimp.c @@ -471,3 +471,218 @@ H5S_simp_fscat (H5F_t *f, const struct H5O_layout_t *layout, FUNC_LEAVE (SUCCEED); } + + +/*------------------------------------------------------------------------- + * Function: H5S_simp_read + * + * Purpose: Reads a dataset from file F directly into application memory + * BUF performing data space conversion in a single step from + * FILE_SPACE to MEM_SPACE. The dataset is stored in the file + * according to the LAYOUT and EFL (external file list) and data + * point in the file is ELMT_SIZE bytes. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Thursday, March 12, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_simp_read (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_efl_t *efl, size_t elmt_size, + const H5S_t *file_space, const H5S_t *mem_space, + void *buf/*out*/) +{ + size_t hslab_size[H5O_LAYOUT_NDIMS]; + size_t file_offset[H5O_LAYOUT_NDIMS]; + size_t mem_size[H5O_LAYOUT_NDIMS]; + size_t mem_offset[H5O_LAYOUT_NDIMS]; + int i; + + FUNC_ENTER (H5S_simp_read, FAIL); + +#ifndef NDEBUG + assert (file_space->type==mem_space->type); + assert (file_space->u.simple.rank==mem_space->u.simple.rank); + for (i=0; iu.simple.rank; i++) { + if (file_space->hslab_def && mem_space->hslab_def) { + assert (1==file_space->h.stride[i]); + assert (1==mem_space->h.stride[i]); + assert (file_space->h.count[i]==mem_space->h.count[i]); + } else if (file_space->hslab_def) { + assert (1==file_space->h.stride[i]); + assert (file_space->h.count[i]==mem_space->u.simple.size[i]); + } else if (mem_space->hslab_def) { + assert (1==mem_space->h.stride[i]); + assert (file_space->u.simple.size[i]==mem_space->h.count[i]); + } else { + assert (file_space->u.simple.size[i]== + mem_space->u.simple.size[i]); + } + } +#endif + + + /* + * Calculate size of hyperslab and offset of hyperslab into file and + * memory. + */ + if (file_space->hslab_def) { + for (i=0; iu.simple.rank; i++) { + hslab_size[i] = file_space->h.count[i]; + } + } else { + for (i=0; iu.simple.rank; i++) { + hslab_size[i] = file_space->u.simple.size[i]; + } + } + for (i=0; iu.simple.rank; i++) { + mem_size[i] = mem_space->u.simple.size[i]; + } + if (file_space->hslab_def) { + for (i=0; iu.simple.rank; i++) { + file_offset[i] = file_space->h.start[i]; + } + } else { + for (i=0; iu.simple.rank; i++) { + file_offset[i] = 0; + } + } + if (mem_space->hslab_def) { + for (i=0; iu.simple.rank; i++) { + mem_offset[i] = mem_space->h.start[i]; + } + } else { + for (i=0; iu.simple.rank; i++) { + mem_offset[i] = 0; + } + } + hslab_size[file_space->u.simple.rank] = elmt_size; + mem_size[file_space->u.simple.rank] = elmt_size; + file_offset[file_space->u.simple.rank] = 0; + mem_offset[file_space->u.simple.rank] = 0; + + /* Read the hyperslab */ + if (H5F_arr_read (f, layout, efl, hslab_size, + mem_size, mem_offset, file_offset, buf)<0) { + HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL, "unable to read dataset"); + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5S_simp_write + * + * Purpose: Write a dataset from application memory BUF directly into + * file F performing data space conversion in a single step from + * MEM_SPACE to FILE_SPACE. The dataset is stored in the file + * according to the LAYOUT and EFL (external file list) and data + * point in the file is ELMT_SIZE bytes. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Thursday, March 12, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_simp_write (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_efl_t *efl, size_t elmt_size, + const H5S_t *file_space, const H5S_t *mem_space, + const void *buf) +{ + size_t hslab_size[H5O_LAYOUT_NDIMS]; + size_t file_offset[H5O_LAYOUT_NDIMS]; + size_t mem_size[H5O_LAYOUT_NDIMS]; + size_t mem_offset[H5O_LAYOUT_NDIMS]; + int i; + + FUNC_ENTER (H5S_simp_write, FAIL); + +#ifndef NDEBUG + assert (file_space->type==mem_space->type); + assert (file_space->u.simple.rank==mem_space->u.simple.rank); + for (i=0; iu.simple.rank; i++) { + if (file_space->hslab_def && mem_space->hslab_def) { + assert (1==file_space->h.stride[i]); + assert (1==mem_space->h.stride[i]); + assert (file_space->h.count[i]==mem_space->h.count[i]); + } else if (file_space->hslab_def) { + assert (1==file_space->h.stride[i]); + assert (file_space->h.count[i]==mem_space->u.simple.size[i]); + } else if (mem_space->hslab_def) { + assert (1==mem_space->h.stride[i]); + assert (file_space->u.simple.size[i]==mem_space->h.count[i]); + } else { + assert (file_space->u.simple.size[i]== + mem_space->u.simple.size[i]); + } + } +#endif + + + /* + * Calculate size of hyperslab and offset of hyperslab into file and + * memory. + */ + if (file_space->hslab_def) { + for (i=0; iu.simple.rank; i++) { + hslab_size[i] = file_space->h.count[i]; + } + } else { + for (i=0; iu.simple.rank; i++) { + hslab_size[i] = file_space->u.simple.size[i]; + } + } + for (i=0; iu.simple.rank; i++) { + mem_size[i] = mem_space->u.simple.size[i]; + } + if (file_space->hslab_def) { + for (i=0; iu.simple.rank; i++) { + file_offset[i] = file_space->h.start[i]; + } + } else { + for (i=0; iu.simple.rank; i++) { + file_offset[i] = 0; + } + } + if (mem_space->hslab_def) { + for (i=0; iu.simple.rank; i++) { + mem_offset[i] = mem_space->h.start[i]; + } + } else { + for (i=0; iu.simple.rank; i++) { + mem_offset[i] = 0; + } + } + hslab_size[file_space->u.simple.rank] = elmt_size; + mem_size[file_space->u.simple.rank] = elmt_size; + file_offset[file_space->u.simple.rank] = 0; + mem_offset[file_space->u.simple.rank] = 0; + + /* Write the hyperslab */ + if (H5F_arr_write (f, layout, efl, hslab_size, + mem_size, mem_offset, file_offset, buf)<0) { + HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, + "unable to write dataset"); + } + + FUNC_LEAVE (SUCCEED); +} + + + + diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index a934b23..be52256 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -100,8 +100,6 @@ H5T_path_t *H5T_path_find (const H5T_t *src, const H5T_t *dst, hbool_t create, H5T_conv_t func); /* Conversion functions */ -herr_t H5T_conv_noop (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, - size_t nelmts, void *buf, void *bkg); herr_t H5T_conv_order (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, void *_buf, void *bkg); herr_t H5T_conv_struct (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index d67c38d..6af43b8 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -41,4 +41,11 @@ herr_t H5T_sort_by_offset (H5T_t *dt); herr_t H5T_pack (H5T_t *dt); herr_t H5T_debug (H5T_t *dt, FILE * stream); H5T_conv_t H5T_find (const H5T_t *src, const H5T_t *dst, H5T_cdata_t **pcdata); + +/* + * This conversion function is here so we can determine whether a conversion + * is a no-op or not. The other conversion functions can go in H5Tpkg.h + */ +herr_t H5T_conv_noop (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, + size_t nelmts, void *buf, void *bkg); #endif diff --git a/src/H5V.c b/src/H5V.c index 85d8752..c9f3de2 100644 --- a/src/H5V.c +++ b/src/H5V.c @@ -502,23 +502,30 @@ H5V_stride_copy(intn n, size_t elmt_size, const size_t *size, FUNC_ENTER(H5V_stride_copy, FAIL); - H5V_vector_cpy(n, idx, size); - nelmts = H5V_vector_reduce_product(n, size); - for (i = 0; i < nelmts; i++) { - /* Copy an element */ - HDmemcpy(dst, src, elmt_size); + if (n) { + H5V_vector_cpy(n, idx, size); + nelmts = H5V_vector_reduce_product(n, size); + for (i = 0; i < nelmts; i++) { - /* Decrement indices and advance pointers */ - for (j = n - 1, carry = TRUE; j >= 0 && carry; --j) { - src += src_stride[j]; - dst += dst_stride[j]; + /* Copy an element */ + HDmemcpy(dst, src, elmt_size); - if (--idx[j]) carry = FALSE; - else idx[j] = size[j]; + /* Decrement indices and advance pointers */ + for (j = n - 1, carry = TRUE; j >= 0 && carry; --j) { + src += src_stride[j]; + dst += dst_stride[j]; + + if (--idx[j]) carry = FALSE; + else idx[j] = size[j]; + } } + } else { + HDmemcpy (dst, src, elmt_size); + HRETURN (SUCCEED); } + FUNC_LEAVE(SUCCEED); } diff --git a/test/Makefile.in b/test/Makefile.in index 212d824..3bf75a4 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -11,21 +11,24 @@ CPPFLAGS=-I. -I../src @CPPFLAGS@ # These are our main targets. They should be listed in the order to be # executed, generally most specific tests to least specific tests. -PROGS=testhdf5 hyperslab istore dtypes dsets cmpd_dset extend external +PROGS=testhdf5 hyperslab istore dtypes dsets cmpd_dset extend external \ + iopipe TESTS=$(PROGS) # Temporary files MOSTLYCLEAN=cmpd_dset.h5 dataset.h5 extend.h5 istore.h5 tfile1.h5 tfile2.h5 \ tfile3.h5 th5s1.h5 theap.h5 tohdr.h5 tstab1.h5 tstab2.h5 \ - extern_1.h5 extern_2.h5 extern_3.h5 extern_1.raw extern_1b.raw extern_2.raw \ - extern_2b.raw extern_3.raw extern_3b.raw extern_4.raw extern_4b.raw + extern_1.h5 extern_2.h5 extern_3.h5 extern_1.raw extern_1b.raw \ + extern_2.raw extern_2b.raw extern_3.raw extern_3b.raw \ + extern_4.raw extern_4b.raw iopipe.raw iopipe.h5 # Source and object files for programs... The PROG_SRC list contains all the # source files and is used for things like dependencies, archiving, etc. The # other source lists are for the individual tests, the files of which may # overlap with other tests. PROG_SRC=testhdf5.c tfile.c theap.c tmeta.c tohdr.c tstab.c th5s.c dtypes.c \ - hyperslab.c istore.c dsets.c cmpd_dset.c extend.c external.c + hyperslab.c istore.c dsets.c cmpd_dset.c extend.c external.c \ + iopipe.c PROG_OBJ=$(PROG_SRC:.c=.o) TESTHDF5_SRC=testhdf5.c tfile.c theap.c tmeta.c tohdr.c tstab.c th5s.c @@ -52,6 +55,12 @@ EXTEND_OBJ=$(EXTEND_SRC:.c=.o) EXTERNAL_SRC=external.c EXTERNAL_OBJ=$(EXTERNAL_SRC:.c=.o) +GRPTIME_SRC=grptime.c +GRPTIME_OBJ=$(GRPTIME_SRC:.c=.o) + +IOPIPE_SRC=iopipe.c +IOPIPE_OBJ=$(IOPIPE_SRC:.c=.o) + # Private header files (not to be installed)... PRIVATE_HDR=testhdf5.h @@ -80,4 +89,10 @@ extend: $(EXTEND_OBJ) ../src/libhdf5.a external: $(EXTERNAL_OBJ) ../src/libhdf5.a $(CC) $(CFLAGS) -o $@ $(EXTERNAL_OBJ) ../src/libhdf5.a $(LIBS) +iopipe: $(IOPIPE_OBJ) ../src/libhdf5.a + $(CC) $(CFLAGS) -o $@ $(IOPIPE_OBJ) ../src/libhdf5.a $(LIBS) + +grptime: $(GRPTIME_OBJ) ../src/libhdf5.a + $(CC) $(CFLAGS) -o $@ $(GRPTIME_OBJ) ../src/libhdf5.a $(LIBS) + @CONCLUDE@ diff --git a/test/iopipe.c b/test/iopipe.c new file mode 100644 index 0000000..813150e --- /dev/null +++ b/test/iopipe.c @@ -0,0 +1,293 @@ +/* + * Copyright (C) 1998 NCSA + * All rights reserved. + * + * Programmer: Robb Matzke + * Thursday, March 12, 1998 + */ +#undef NDEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RAW_FILE_NAME "iopipe.raw" +#define HDF5_FILE_NAME "iopipe.h5" +#define REQUEST_SIZE_X 4579 +#define REQUEST_SIZE_Y 4579 +#define NREAD_REQUESTS 45 +#define NWRITE_REQUESTS 45 +#define HEADING "%-16s" +#define PROGRESS '=' + + +/*------------------------------------------------------------------------- + * Function: print_stats + * + * Purpose: Prints statistics + * + * Return: void + * + * Programmer: Robb Matzke + * Thursday, March 12, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +print_stats (const char *prefix, + struct rusage *r_start, struct rusage *r_stop, + struct timeval *t_start, struct timeval *t_stop, + size_t nbytes) +{ + double u_time, s_time, e_time, bw; + + u_time = (r_stop->ru_utime.tv_sec+r_stop->ru_utime.tv_usec/1000000.0) - + (r_start->ru_utime.tv_sec+r_start->ru_utime.tv_usec/1000000.0); + + s_time = (r_stop->ru_stime.tv_sec+r_stop->ru_stime.tv_usec/1000000.0) - + (r_start->ru_stime.tv_sec+r_start->ru_stime.tv_usec/1000000.0); + + e_time = (t_stop->tv_sec+t_stop->tv_usec/1000000.0) - + (t_start->tv_sec+t_start->tv_usec/1000000.0); + + bw = nbytes / e_time; + + printf (HEADING "%1.2fuser %1.2fsystem %1.2felapsed %1.2fMB/s\n", + prefix, u_time, s_time, e_time, bw/(1024*1024)); + +} + + +/*------------------------------------------------------------------------- + * Function: synchronize + * + * Purpose: + * + * Return: void + * + * Programmer: Robb Matzke + * Thursday, March 12, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +synchronize (void) +{ + system ("sync"); + system ("df >/dev/null"); +#if 0 + system ("/sbin/swapout 130"); +#endif +} + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: + * + * Return: Success: + * + * Failure: + * + * Programmer: Robb Matzke + * Thursday, March 12, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +main (void) +{ + static size_t size[2] = {REQUEST_SIZE_X, REQUEST_SIZE_Y}; + static int nread=NREAD_REQUESTS, nwrite=NWRITE_REQUESTS; + + unsigned char *the_data = NULL; + hid_t file, dset, file_space=-1; + herr_t status; + struct rusage r_start, r_stop; + struct timeval t_start, t_stop; + int i, fd; + ssize_t n; + off_t offset; + int start[2]; + size_t count[2]; + + printf ("I/O request size is %1.1fMB\n", (size[0]*size[1])/(1024.0*1024)); + + + /* Open the files */ + file = H5Fcreate (HDF5_FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + assert (file>=0); + fd = open (RAW_FILE_NAME, O_RDWR|O_CREAT|O_TRUNC, 0666); + assert (fd>=0); + + /* Create the dataset */ + file_space = H5Screate_simple (2, size, size); + assert (file_space>=0); + dset = H5Dcreate (file, "dset", H5T_NATIVE_UCHAR, file_space, H5P_DEFAULT); + assert (dset>=0); + the_data = malloc (size[0]*size[1]); + memset (the_data, 0xAA, size[0]*size[1]); /*initial fill for lazy malloc*/ + + /* Fill raw */ + synchronize (); + getrusage (RUSAGE_SELF, &r_start); + gettimeofday (&t_start, NULL); + fprintf (stderr, HEADING, "fill raw"); + for (i=0; i=0); + } + getrusage (RUSAGE_SELF, &r_stop); + gettimeofday (&t_stop, NULL); + putc ('\n', stderr); + print_stats ("fill hdf5", + &r_start, &r_stop, &t_start, &t_stop, + nread*size[0]*size[1]); + + /* Write the raw dataset */ + synchronize (); + getrusage (RUSAGE_SELF, &r_start); + gettimeofday (&t_start, NULL); + fprintf (stderr, HEADING, "out raw"); + for (i=0; i=0); + } + getrusage (RUSAGE_SELF, &r_stop); + gettimeofday (&t_stop, NULL); + putc ('\n', stderr); + print_stats ("out hdf5", + &r_start, &r_stop, &t_start, &t_stop, + nread*size[0]*size[1]); + + /* Read the raw dataset */ + synchronize (); + getrusage (RUSAGE_SELF, &r_start); + gettimeofday (&t_start, NULL); + fprintf (stderr, HEADING, "in raw"); + for (i=0; i=0); + } + getrusage (RUSAGE_SELF, &r_stop); + gettimeofday (&t_stop, NULL); + putc ('\n', stderr); + print_stats ("in hdf5", + &r_start, &r_stop, &t_start, &t_stop, + nread*size[0]*size[1]); + + /* Read hyperslab */ + assert (size[0]>20 && size[1]>20); + start[0] = start[1] = 10; + count[0] = count[1] = size[0]-20; + status = H5Sset_hyperslab (file_space, start, count, NULL); + assert (status>=0); + synchronize (); + getrusage (RUSAGE_SELF, &r_start); + gettimeofday (&t_start, NULL); + fprintf (stderr, HEADING, "in hdf5 partial"); + for (i=0; i=0); + } + getrusage (RUSAGE_SELF, &r_stop); + gettimeofday (&t_stop, NULL); + putc ('\n', stderr); + print_stats ("in hdf5 partial", + &r_start, &r_stop, &t_start, &t_stop, + nread*count[0]*count[1]); + + + + /* Close everything */ + close (fd); + H5Dclose (dset); + H5Sclose (file_space); + H5Fclose (file); + + return 0; +} -- cgit v0.12