summaryrefslogtreecommitdiffstats
path: root/perform/pio_engine.c
diff options
context:
space:
mode:
authorAlbert Cheng <acheng@hdfgroup.org>2001-11-07 15:28:33 (GMT)
committerAlbert Cheng <acheng@hdfgroup.org>2001-11-07 15:28:33 (GMT)
commitbb76b558e6d5c3e1c35a5f08da480435db039e19 (patch)
tree9eac65359e20b54a5d367ee7a501e901edf826a8 /perform/pio_engine.c
parent965e3bc3e20cefeb81b0b88002c1dc42d197c2ff (diff)
downloadhdf5-bb76b558e6d5c3e1c35a5f08da480435db039e19.zip
hdf5-bb76b558e6d5c3e1c35a5f08da480435db039e19.tar.gz
hdf5-bb76b558e6d5c3e1c35a5f08da480435db039e19.tar.bz2
[svn-r4592] Purpose:
New addition Description: Initial version of the Parallel I/O performance measurement program. Not fully implemented yet but checking them in before I may destroy them by accident. Don't run this in small file system (like AFS or eirene) since it generates gigabytes test files. Platforms tested: modi4 64bits. It compiled and ran but took a long time because the current test parametes are too "wild".
Diffstat (limited to 'perform/pio_engine.c')
-rw-r--r--perform/pio_engine.c832
1 files changed, 832 insertions, 0 deletions
diff --git a/perform/pio_engine.c b/perform/pio_engine.c
new file mode 100644
index 0000000..f54114c
--- /dev/null
+++ b/perform/pio_engine.c
@@ -0,0 +1,832 @@
+/*
+ * Author: Albert Cheng of NCSA, Oct 24, 2001.
+ */
+
+#include "hdf5.h"
+#ifdef H5_HAVE_PARALLEL
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include "pio_perf.h"
+#include "pio_timer.h"
+#ifdef OLDSTUFF
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/time.h>
+#endif /* OLDSTUFF */
+#include <mpi.h>
+#ifndef MPI_FILE_NULL /*MPIO may be defined in mpi.h already */
+# include <mpio.h>
+#endif
+
+
+/* Macro definitions */
+#define GOTOERROR(errcode) {ret_code=errcode; goto done;}
+#define GOTODONE {goto done;}
+#define ERRMSG(mesg) { \
+ fprintf(stderr, "Proc %d: ", myrank); \
+ fprintf(stderr, "*** Assertion failed (%s) at line %4d in %s\n", \
+ mesg, (int)__LINE__, __FILE__); \
+}
+#define MSG(mesg) { \
+ fprintf(stderr, "Proc %d: ", myrank); \
+ fprintf(stderr, "(%s) at line %4d in %s\n", \
+ mesg, (int)__LINE__, __FILE__); \
+}
+/* Verify:
+ * if val is false (0), print mesg.
+ */
+#define VRFY(val, mesg) do { \
+ if (!val) { \
+ ERRMSG(mesg); \
+ GOTOERROR(1); \
+ } \
+} while(0)
+
+#ifndef HDmalloc
+#define HDmalloc(x) malloc(x)
+#endif
+
+#ifndef HDfree
+#define HDfree(x) free(x)
+#endif
+
+#ifndef HDopen
+#ifdef O_BINARY
+#define HDopen(S,F,M) open(S,F|_O_BINARY,M)
+#else
+#define HDopen(S,F,M) open(S,F,M)
+#endif
+#endif
+
+#ifndef HDclose
+#define HDclose(F) close(F)
+#endif
+
+#ifndef HDseek
+#define HDseek(F,L,W) lseek(F,L,W)
+#endif
+
+#ifndef HDwrite
+#define HDwrite(F,B,S) write(F,B,S)
+#endif
+
+#ifndef HDread
+#define HDread(F,B,S) read(F,B,S)
+#endif
+
+/* Raw I/O macros */
+#define RAWCREATE(fn) HDopen(fn, O_CREAT|O_TRUNC|O_RDWR, 0600)
+#define RAWOPEN(fn, F) HDopen(fn, F, 0600)
+#define RAWCLOSE(F) HDclose(F)
+#define RAWSEEK(F,L) HDseek(F,L,SEEK_SET)
+#define RAWWRITE(F,B,S) HDwrite(F,B,S)
+#define RAWREAD(F,B,S) HDread(F,B,S)
+
+
+
+#ifdef OLDSTUFF
+hid_t dataset; /* Dataset ID */
+char *meta_ext, *raw_ext; /* holds the meta and raw file extension if */
+ /* opt_split_vfd is set */
+
+
+/* DEFAULT VALUES FOR OPTIONS */
+int64_t opt_block = 1048576*16;
+int opt_iter = 1;
+int opt_stripe = -1;
+int opt_correct = 0;
+int amode = O_RDWR | O_CREAT;
+char opt_file[256] = "/tmp/test.out\0";
+char opt_pvfstab[256] = "notset\0";
+int opt_pvfstab_set = 0;
+
+/* function prototypes */
+double Wtime(void);
+
+extern int errno;
+extern int debug_on;
+
+/* globals needed for getopt */
+extern char *optarg;
+extern int optind, opterr;
+#endif /* old stuff */
+
+int
+dopio(parameters param)
+{
+ MPI_Comm comm = MPI_COMM_NULL;
+ int myrank;
+ int nprocs=1;
+ int ret_code=0; /* return code */
+ iotype iot;
+ char fname[256];
+ unsigned int maxprocs;
+ unsigned int nfiles, nf;
+ unsigned long ndsets, nd;
+ unsigned long nelmts;
+ unsigned int niters;
+ unsigned long nelmts_towrite, nelmts_written;
+ unsigned long nelmts_toread, nelmts_read;
+ size_t elmt_size;
+ off_t dset_offset; /*dataset offset in a file */
+ off_t next_offset; /*offset of next I/O */
+ int rc; /*routine return code */
+ int color; /*for communicator creation */
+ int mrc; /*mpi return code */
+ char *buffer=NULL; /*data buffer pointer */
+ size_t buffer_size=1024*1024; /*data buffer size, 1MB */
+ size_t nelmts_in_buffer; /*Number of elmts the buffer*/
+ /*can hold.*/
+ size_t dset_size; /*one dataset size in Byte*/
+ int rawfd=-1; /*Raw IO file handle */
+ MPI_File mpifd=MPI_FILE_NULL; /*MPI IO file handle */
+ /* hdf5 variables */
+ hid_t acc_tpl=-1; /* File access templates */
+ hid_t h5fd=-1; /*HDF5 IO file handle */
+ herr_t hrc; /*HDF5 return code */
+ hsize_t h5dims[1]; /* dataset dim sizes */
+ hsize_t h5block[1], h5stride[1], h5count[1];
+ hssize_t h5start[1];
+ hid_t h5dset_space_id = -1; /*Dataset space ID */
+ hid_t h5mem_space_id = -1; /*memory dataspace ID */
+ char dname[64]; /*dataset name */
+ hid_t h5ds_id = -1; /*Dataset handle*/
+
+#ifdef OLDSTUFF
+ char *buf, *tmp, *buf2, *tmp2, *check;
+ int i, j, myrank=0, nprocs=1, err, my_correct = 1, correct, myerrno;
+ double stim, etim;
+ double write_tim = 0;
+ double read_tim = 0;
+ double read_bw, write_bw;
+ double max_read_tim, max_write_tim;
+ double min_read_tim, min_write_tim;
+ double ave_read_tim, ave_write_tim;
+ int64_t iter_jump = 0;
+ int64_t seek_position = 0;
+ MPI_File fh;
+ MPI_Status status;
+ int nchars;
+#endif /* OLDSTUFF */
+
+
+ /*
+ *Setup parameters and sanity check
+ */
+ /* IO type */
+ iot = param.io_type;
+ switch (iot) {
+ case RAW:
+ /* nothing */
+ break;
+ case MPIO:
+ break;
+ case PHDF5:
+ break;
+ default:
+ /* unknown request */
+ fprintf(stderr, "Unknown IO type request (%d)\n", iot);
+ GOTOERROR(1);
+ }
+
+ /* number of files */
+ nfiles = param.num_files;
+
+ /* number of datasets per file */
+ ndsets = param.num_dsets;
+
+ /* number of elements per dataset */
+ nelmts = param.num_elmts;
+ if (nelmts == 0 ){
+ fprintf(stderr,
+ "number of elements per dataset must be positive (%lu)\n",
+ nelmts);
+ GOTOERROR(1);
+ }
+
+ /* number of iterations of reads or writes */
+ niters = param.num_iters;
+
+ /* maximun number of mpi-processes to use */
+ maxprocs = param.max_num_procs;
+ if (maxprocs == 0 ){
+ fprintf(stderr,
+ "maximun number of process to use must be positive (%u)\n",
+ maxprocs);
+ GOTOERROR(1);
+ }
+ MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+ if (maxprocs > nprocs){
+ fprintf(stderr,
+ "maximun number of process(%d) must be <= process in MPI_COMM_WORLD(%d)\n",
+ maxprocs, nprocs);
+ GOTOERROR(1);
+ }
+
+
+/* DEBUG*/
+fprintf(stderr, "nfiles=%u\n", nfiles);
+fprintf(stderr, "ndsets=%lu\n", ndsets);
+fprintf(stderr, "nelmts=%lu\n", nelmts);
+fprintf(stderr, "niters=%u\n", niters);
+fprintf(stderr, "maxprocs=%u\n", maxprocs);
+nfiles=3;
+/*ndsets=5; */
+
+ /*
+ *Create a sub communicator for this run
+ *Easier to use the first N processes.
+ */
+ MPI_Comm_rank(comm, &myrank);
+ color = (myrank < maxprocs);
+ mrc = MPI_Comm_split (MPI_COMM_WORLD, color, myrank, &comm);
+ if (mrc!=MPI_SUCCESS) {
+ fprintf(stderr, "MPI_Comm_split failed\n");
+ GOTOERROR(1);
+ }
+
+ if (!color){ /* not involved in this run */
+ mrc = MPI_Comm_free(&comm);
+ GOTODONE;
+ }
+
+ /* determine the mpi rank of in the new comm */
+ MPI_Comm_size(comm, &nprocs);
+ MPI_Comm_rank(comm, &myrank);
+
+ /* Calculate dataset parameters */
+ /* Data type is always native C int */
+ elmt_size = sizeof(int);
+ dset_size = nelmts * elmt_size;
+
+ /* allocate data buffer */
+ buffer = HDmalloc(buffer_size);
+ if (buffer == NULL){
+ fprintf(stderr, "malloc for data buffer failed\n");
+ GOTOERROR(1);
+ }
+ nelmts_in_buffer = buffer_size/elmt_size;
+
+ /* hdf5 dataset setup */
+ if (iot == PHDF5){
+ /* define a contiquous dataset of nelmts native ints */
+ h5dims[0] = nelmts;
+ h5dset_space_id = H5Screate_simple (1, h5dims, NULL);
+ VRFY((h5dset_space_id >= 0), "H5Screate_simple");
+
+ /* create the memory dataspace */
+ h5dims[0] = nelmts_in_buffer;
+ h5mem_space_id = H5Screate_simple (1, h5dims, NULL);
+ VRFY((h5mem_space_id >= 0), "H5Screate_simple");
+ }
+
+
+
+
+
+ for (nf=1; nf <= nfiles; nf++){
+ /*
+ *Open file for write
+ */
+MSG("creating file");
+ sprintf(fname, "#pio_tmp_%u", nf);
+ switch (iot) {
+ case RAW:
+ strcat(fname, ".raw");
+ rawfd = RAWCREATE(fname);
+ if (rawfd < 0 ){
+ fprintf(stderr, "Raw File Create failed(%s)\n", fname);
+ GOTOERROR(1);
+ }
+ break;
+ case MPIO:
+ strcat(fname, ".mpio");
+ mrc = MPI_File_open(comm, fname, MPI_MODE_CREATE|MPI_MODE_RDWR,
+ MPI_INFO_NULL, &mpifd);
+ if (mrc != MPI_SUCCESS){
+ fprintf(stderr, "MPI File Create failed(%s)\n", fname);
+ GOTOERROR(1);
+ }
+ break;
+ case PHDF5:
+ strcat(fname, ".h5");
+ acc_tpl = H5Pcreate (H5P_FILE_ACCESS);
+ VRFY((acc_tpl >= 0), "");
+ hrc = H5Pset_fapl_mpio(acc_tpl, comm, MPI_INFO_NULL);
+ VRFY((hrc >= 0), "");
+ /*do not close acc_tpl. It will used to open file for read later*/
+ /* create the parallel file */
+ h5fd=H5Fcreate(fname,H5F_ACC_TRUNC,H5P_DEFAULT,acc_tpl);
+ if (h5fd < 0){
+ fprintf(stderr, "HDF5 file Create failed(%s)\n", fname);
+ GOTOERROR(1);
+ }
+ break;
+ }
+
+ for (nd=1; nd <= ndsets; nd++){
+ /* Calculate dataset offset within a file */
+
+ /* create dataset */
+ switch (iot){
+ case RAW:
+ case MPIO:
+ /* both raw and mpi io just need dataset offset in file*/
+ dset_offset = (nd-1)*dset_size;
+ break;
+ case PHDF5:
+ sprintf(dname, "Dataset_%lu", nd);
+ h5ds_id = H5Dcreate(h5fd, dname, H5T_NATIVE_INT, h5dset_space_id,
+ H5P_DEFAULT);
+ VRFY((h5ds_id >= 0), "H5Dcreate");
+ break;
+ }
+
+
+ nelmts_written = 0 ;
+ while (nelmts_written < nelmts){
+ nelmts_towrite = nelmts - nelmts_written;
+ if (nelmts - nelmts_written >= nelmts_in_buffer){
+ nelmts_towrite = nelmts_in_buffer;
+ }else{
+ /* last write of a partial buffer */
+ nelmts_towrite = nelmts - nelmts_written;
+ }
+
+ /*Prepare write data*/
+ {
+ int *intptr = (int*)buffer;
+ int i;
+ for (i=0; i<nelmts_towrite; i++){
+ *intptr++ = nelmts_towrite+i;
+ }
+ }
+
+
+ /* Write */
+
+ /* Calculate offset of write within a dataset/file */
+ switch (iot){
+ case RAW:
+ RAWSEEK(rawfd, dset_offset+nelmts_written*elmt_size);
+ RAWWRITE(rawfd, buffer, nelmts_towrite*elmt_size);
+ break;
+ case MPIO:
+ break;
+ }
+
+
+ nelmts_written += nelmts_towrite;
+fprintf(stderr, "wrote %lu elmts, %lu written\n", nelmts_towrite, nelmts_written);
+ }
+ /* Calculate write time */
+
+ /* Close dataset. Only HDF5 needs to do an explicit close. */
+ if (iot == PHDF5){
+ hrc = H5Dclose(h5ds_id);
+ VRFY((hrc>=0), "HDF5 Dataset Close failed\n");
+ h5ds_id = -1;
+ }
+ }
+
+ /* Close file for write */
+MSG("closing write file");
+ switch (iot) {
+ case RAW:
+ rc = RAWCLOSE(rawfd);
+ VRFY((rc==0), "HDclose");
+ rawfd = -1;
+ break;
+ case MPIO:
+ mrc = MPI_File_close(&mpifd);
+ if (mrc != MPI_SUCCESS){
+ fprintf(stderr, "MPI File close failed\n");
+ GOTOERROR(1);
+ }
+ break;
+ case PHDF5:
+ hrc=H5Fclose(h5fd);
+ if (hrc < 0){
+ fprintf(stderr, "HDF5 File Close failed(%s)\n", fname);
+ GOTOERROR(1);
+ }else{
+ h5fd=-1;
+ }
+ break;
+ }
+
+
+
+
+ /* Open file for read */
+MSG("opening file to read");
+ switch (iot) {
+ case RAW:
+ rawfd = RAWOPEN(fname, O_RDONLY);
+ if (rawfd < 0 ){
+ fprintf(stderr, "Raw File Open failed(%s)\n", fname);
+ GOTOERROR(1);
+ }
+ break;
+ case MPIO:
+ mrc = MPI_File_open(comm, fname, MPI_MODE_RDONLY,
+ MPI_INFO_NULL, &mpifd);
+ if (mrc != MPI_SUCCESS){
+ fprintf(stderr, "MPI File Open failed(%s)\n", fname);
+ GOTOERROR(1);
+ }
+ break;
+ case PHDF5:
+ /* open the parallel file */
+ h5fd=H5Fopen(fname,H5P_DEFAULT,acc_tpl);
+ if (h5fd < 0){
+ fprintf(stderr, "HDF5 file Open failed(%s)\n", fname);
+ GOTOERROR(1);
+ }
+ /* can release acc_tpl now */
+ hrc = H5Pclose(acc_tpl);
+ VRFY((hrc >= 0), "H5Pclose");
+ acc_tpl = -1;
+ break;
+ }
+
+ /* Calculate dataset offset within a file */
+
+ /* Open dataset for read */
+
+ /* Prepare read */
+
+ /* Calculate offset of read within a dataset/file */
+
+ /* Read */
+
+ /* Calculate read time */
+
+ /* Close dataset for read */
+
+ /* Close file for read */
+MSG("closing read file");
+ switch (iot) {
+ case RAW:
+ rc = RAWCLOSE(rawfd);
+ VRFY((rc==0), "HDclose");
+ rawfd = -1;
+ break;
+ case MPIO:
+ mrc = MPI_File_close(&mpifd);
+ if (mrc != MPI_SUCCESS){
+ fprintf(stderr, "MPI File close failed\n");
+ GOTOERROR(1);
+ }
+ break;
+ case PHDF5:
+ hrc=H5Fclose(h5fd);
+ if (h5fd < 0){
+ fprintf(stderr, "HDF5 file Create failed(%s)\n", fname);
+ GOTOERROR(1);
+ }else{
+ h5fd=-1;
+ }
+ break;
+ }
+
+ }
+
+done:
+ /* clean up */
+ /* release HDF5 objects */
+ if (acc_tpl != -1){
+ hrc = H5Pclose(acc_tpl);
+ if (hrc < 0){
+ fprintf(stderr, "HDF5 Property List Close failed\n");
+ ret_code=1;
+ }
+ else
+ acc_tpl = -1;
+ }
+ if (h5dset_space_id != -1){
+ hrc = H5Sclose(h5dset_space_id);
+ if (hrc < 0){
+ fprintf(stderr, "HDF5 Dataset Space Close failed\n");
+ ret_code=1;
+ }
+ else
+ h5dset_space_id = -1;
+ }
+ if (h5mem_space_id != -1){
+ hrc = H5Sclose(h5mem_space_id);
+ if (hrc < 0){
+ fprintf(stderr, "HDF5 Memory Space Close failed\n");
+ ret_code=1;
+ }
+ else
+ h5mem_space_id = -1;
+ }
+ if (h5ds_id != -1){
+ hrc = H5Dclose(h5ds_id);
+ if (hrc < 0){
+ fprintf(stderr, "HDF5 Dataset Close failed\n");
+ ret_code=1;
+ }
+ else
+ h5ds_id = -1;
+ }
+
+ /* close any opened files */
+ if (rawfd != -1){
+ rc = HDclose(rawfd);
+ if (rc != 0){
+ ERRMSG("Raw file close failed");
+ ret_code=1;
+ }
+ else
+ rawfd = -1;
+ }
+ if (mpifd != MPI_FILE_NULL){
+ MPI_File_close(&mpifd);
+ }
+ if (h5fd != -1){
+ H5Fclose(h5fd);
+ h5fd=-1;
+ }
+ /* release MPI resources */
+ if (comm != MPI_COMM_NULL){
+ MPI_Comm_free(&comm);
+ }
+ /* release generic resources */
+ if (buffer != NULL){
+ HDfree(buffer);
+ buffer = NULL;
+ }
+fprintf(stderr, "returning with ret_code=%d\n", ret_code);
+ return(ret_code);
+}
+
+#ifdef OLDSTUFF
+int
+original_main()
+{
+
+ /* parse the command line arguments */
+ parse_args(argc, argv);
+
+ if (mynod == 0) printf("# Using hdf5-io calls.\n");
+
+
+ /* kindof a weird hack- if the location of the pvfstab file was
+ * specified on the command line, then spit out this location into
+ * the appropriate environment variable: */
+
+#if H5_HAVE_SETENV
+/* no setenv or unsetenv */
+ if (opt_pvfstab_set) {
+ if((setenv("PVFSTAB_FILE", opt_pvfstab, 1)) < 0){
+ perror("setenv");
+ goto die_jar_jar_die;
+ }
+ }
+#endif
+
+ /* this is how much of the file data is covered on each iteration of
+ * the test. used to help determine the seek offset on each
+ * iteration */
+ iter_jump = nprocs * opt_block;
+
+ /* setup a buffer of data to write */
+ if (!(tmp = (char *) malloc(opt_block + 256))) {
+ perror("malloc");
+ goto die_jar_jar_die;
+ }
+ buf = tmp + 128 - (((long)tmp) % 128); /* align buffer */
+
+ if (opt_correct) {
+ /* do the same buffer setup for verifiable data */
+ if (!(tmp2 = (char *) malloc(opt_block + 256))) {
+ perror("malloc2");
+ goto die_jar_jar_die;
+ }
+ buf2 = tmp + 128 - (((long)tmp) % 128);
+ }
+
+ /* setup file access template with parallel IO access. */
+ if (opt_split_vfd){
+ hid_t mpio_pl;
+
+ mpio_pl = H5Pcreate (H5P_FILE_ACCESS);
+ VRFY((acc_tpl >= 0), "", H5FATAL);
+ ret = H5Pset_fapl_mpio(mpio_pl, MPI_COMM_WORLD, MPI_INFO_NULL);
+ VRFY((ret >= 0), "", H5FATAL);
+
+ /* set optional allocation alignment */
+ if (opt_alignment*opt_threshold != 1){
+ ret = H5Pset_alignment(acc_tpl, opt_threshold, opt_alignment );
+ VRFY((ret >= 0), "H5Pset_alignment succeeded", !H5FATAL);
+ }
+
+ /* setup file access template */
+ acc_tpl = H5Pcreate (H5P_FILE_ACCESS);
+ VRFY((acc_tpl >= 0), "", H5FATAL);
+ ret = H5Pset_fapl_split(acc_tpl, meta_ext, mpio_pl, raw_ext, mpio_pl);
+ VRFY((ret >= 0), "H5Pset_fapl_split succeeded", H5FATAL);
+ }else{
+
+ /* set optional allocation alignment */
+ if (opt_alignment*opt_threshold != 1){
+ ret = H5Pset_alignment(acc_tpl, opt_threshold, opt_alignment );
+ VRFY((ret >= 0), "H5Pset_alignment succeeded", !H5FATAL);
+ }
+ }
+
+
+
+ /* now each process writes a block of opt_block chars in round robbin
+ * fashion until the whole dataset is covered.
+ */
+ for (j=0; j < opt_iter; j++) {
+ /* setup a file dataspace selection */
+ start[0] = (j*iter_jump)+(mynod*opt_block);
+ stride[0] = block[0] = opt_block;
+ count[0]= 1;
+ ret=H5Sselect_hyperslab(file_dataspace, H5S_SELECT_SET, start, stride, count, block);
+ VRFY((ret >= 0), "H5Sset_hyperslab succeeded", H5FATAL);
+
+ if (opt_correct) /* fill in buffer for iteration */ {
+ for (i=mynod+j, check=buf; i<opt_block; i++,check++) *check=(char)i;
+ }
+
+ /* discover the starting time of the operation */
+ MPI_Barrier(MPI_COMM_WORLD);
+ stim = MPI_Wtime();
+
+ /* write data */
+ ret = H5Dwrite(dataset, H5T_NATIVE_CHAR, mem_dataspace, file_dataspace,
+ H5P_DEFAULT, buf);
+ VRFY((ret >= 0), "H5Dwrite dataset1 succeeded", !H5FATAL);
+
+ /* discover the ending time of the operation */
+ etim = MPI_Wtime();
+
+ write_tim += (etim - stim);
+
+ /* we are done with this "write" iteration */
+ }
+
+ /* close dataset and file */
+ ret=H5Dclose(dataset);
+ VRFY((ret >= 0), "H5Dclose succeeded", H5FATAL);
+ ret=H5Fclose(fid);
+ VRFY((ret >= 0), "H5Fclose succeeded", H5FATAL);
+
+
+
+ /* wait for everyone to synchronize at this point */
+ MPI_Barrier(MPI_COMM_WORLD);
+
+ /* reopen the file for reading */
+ fid=H5Fopen(opt_file,H5F_ACC_RDONLY,acc_tpl);
+ VRFY((fid >= 0), "", H5FATAL);
+
+ /* open the dataset */
+ dataset = H5Dopen(fid, "Dataset1");
+ VRFY((dataset >= 0), "H5Dopen succeeded", H5FATAL);
+
+ /* we can re-use the same mem_dataspace and file_dataspace
+ * the H5Dwrite used since the dimension size is the same.
+ */
+
+ /* we are going to repeat the read the same pattern the write used */
+ for (j=0; j < opt_iter; j++) {
+ /* setup a file dataspace selection */
+ start[0] = (j*iter_jump)+(mynod*opt_block);
+ stride[0] = block[0] = opt_block;
+ count[0]= 1;
+ ret=H5Sselect_hyperslab(file_dataspace, H5S_SELECT_SET, start, stride, count, block);
+ VRFY((ret >= 0), "H5Sset_hyperslab succeeded", H5FATAL);
+ /* seek to the appropriate spot give the current iteration and
+ * rank within the MPI processes */
+
+ /* discover the start time */
+ MPI_Barrier(MPI_COMM_WORLD);
+ stim = MPI_Wtime();
+
+ /* read data */
+ /* read in the file data */
+ if (!opt_correct){
+ ret = H5Dread(dataset, H5T_NATIVE_CHAR, mem_dataspace, file_dataspace,
+ H5P_DEFAULT, buf);
+ }
+ else{
+ ret = H5Dread(dataset, H5T_NATIVE_CHAR, mem_dataspace, file_dataspace,
+ H5P_DEFAULT, buf2);
+ }
+ myerrno = errno;
+ /* discover the end time */
+ etim = MPI_Wtime();
+ read_tim += (etim - stim);
+ VRFY((ret >= 0), "H5Dwrite dataset1 succeeded", !H5FATAL);
+
+
+ if (ret < 0) fprintf(stderr, "node %d, read error, loc = %Ld: %s\n",
+ mynod, mynod*opt_block, strerror(myerrno));
+
+ /* if the user wanted to check correctness, compare the write
+ * buffer to the read buffer */
+ if (opt_correct && memcmp(buf, buf2, opt_block)) {
+ fprintf(stderr, "node %d, correctness test failed\n", mynod);
+ my_correct = 0;
+ MPI_Allreduce(&my_correct, &correct, 1, MPI_INT, MPI_MIN,
+ MPI_COMM_WORLD);
+ }
+
+ /* we are done with this read iteration */
+ }
+
+ /* close dataset and file */
+ ret=H5Dclose(dataset);
+ VRFY((ret >= 0), "H5Dclose succeeded", H5FATAL);
+ ret=H5Fclose(fid);
+ VRFY((ret >= 0), "H5Fclose succeeded", H5FATAL);
+
+ /* compute the read and write times */
+ MPI_Allreduce(&read_tim, &max_read_tim, 1, MPI_DOUBLE, MPI_MAX,
+ MPI_COMM_WORLD);
+ MPI_Allreduce(&read_tim, &min_read_tim, 1, MPI_DOUBLE, MPI_MIN,
+ MPI_COMM_WORLD);
+ MPI_Allreduce(&read_tim, &ave_read_tim, 1, MPI_DOUBLE, MPI_SUM,
+ MPI_COMM_WORLD);
+
+ /* calculate the average from the sum */
+ ave_read_tim = ave_read_tim / nprocs;
+
+ MPI_Allreduce(&write_tim, &max_write_tim, 1, MPI_DOUBLE, MPI_MAX,
+ MPI_COMM_WORLD);
+ MPI_Allreduce(&write_tim, &min_write_tim, 1, MPI_DOUBLE, MPI_MIN,
+ MPI_COMM_WORLD);
+ MPI_Allreduce(&write_tim, &ave_write_tim, 1, MPI_DOUBLE, MPI_SUM,
+ MPI_COMM_WORLD);
+
+ /* calculate the average from the sum */
+ ave_write_tim = ave_write_tim / nprocs;
+
+ /* print out the results on one node */
+ if (mynod == 0) {
+ read_bw = ((int64_t)(opt_block*nprocs*opt_iter))/(max_read_tim*1000000.0);
+ write_bw = ((int64_t)(opt_block*nprocs*opt_iter))/(max_write_tim*1000000.0);
+
+ printf("nr_procs = %d, nr_iter = %d, blk_sz = %ld\n", nprocs,
+ opt_iter, (long)opt_block);
+
+ printf("# total_size = %ld\n", (long)(opt_block*nprocs*opt_iter));
+
+ printf("# Write: min_time = %f, max_time = %f, mean_time = %f\n",
+ min_write_tim, max_write_tim, ave_write_tim);
+ printf("# Read: min_time = %f, max_time = %f, mean_time = %f\n",
+ min_read_tim, max_read_tim, ave_read_tim);
+
+ printf("Write bandwidth = %f Mbytes/sec\n", write_bw);
+ printf("Read bandwidth = %f Mbytes/sec\n", read_bw);
+
+ if (opt_correct) {
+ printf("Correctness test %s.\n", correct ? "passed" : "failed");
+ }
+ }
+
+
+die_jar_jar_die:
+
+#if H5_HAVE_SETENV
+/* no setenv or unsetenv */
+ /* clear the environment variable if it was set earlier */
+ if (opt_pvfstab_set){
+ unsetenv("PVFSTAB_FILE");
+ }
+#endif
+
+ free(tmp);
+ if (opt_correct) free(tmp2);
+ MPI_Finalize();
+ return(0);
+}
+
+/* Wtime() - returns current time in sec., in a double */
+double Wtime()
+{
+ struct timeval t;
+
+ gettimeofday(&t, NULL);
+ return((double)t.tv_sec + (double)t.tv_usec / 1000000);
+}
+
+#endif /* OLDSTUFF */
+
+#else /* H5_HAVE_PARALLEL */
+/* dummy program since H5_HAVE_PARALLE is not configured in */
+int
+main()
+{
+printf("No parallel IO performance because parallel is not configured in\n");
+return(0);
+}
+#endif /* H5_HAVE_PARALLEL */