mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-01-30 15:32:37 +08:00
[svn-r4733]
Purpose: Feature Changes Description: Okay, I needed to add in more parameters so that the user can modify how things are supposed to work with the PIO programs. Also needed to change the algorithm a bit to make these work. And needed to add in timing for the READ option. Solution: Added the above things. The parameters took a major rewrite of the command-line parsing stuff. Here's the usage statement: usage: pio_perf [OPTIONS] OPTIONS -h, --help Print a usage message and exit -d N, --num-dsets=N Number of datasets per file [default:1] -f S, --file-size=S Size of a single file [default: 64M] -F N, --num-files=N Number of files [default: 1] -H, --hdf5 Run HDF5 performance test -i, --num-iterations Number of iterations to perform [default: 1] -m, --mpiio Run MPI/IO performance test -o F, --output=F Output raw data into file F [default: none] -P N, --max-num-processes=N Maximum number of processes to use [default: 1] -p N, --min-num-processes=N Minimum number of processes to use [default: 1] -r, --raw Run raw (UNIX) performance test -X S, --max-xfer-size=S Maximum transfer buffer size [default: 1M] -x S, --min-xfer-size=S Minimum transfer buffer size [default: 1K] F - is a filename. N - is an integer >=0. S - is a size specifier, an integer >=0 followed by a size indicator: K - Kilobyte M - Megabyte G - Gigabyte Example: 37M = 37 Megabytes Platforms tested: Linux, but not fully finished...
This commit is contained in:
parent
2b629eaceb
commit
d1d532069b
@ -35,13 +35,13 @@
|
||||
#define GOTOERROR(errcode) { ret_code = errcode; goto done; }
|
||||
#define GOTODONE { goto done; }
|
||||
#define ERRMSG(mesg) { \
|
||||
fprintf(stderr, "Proc %d: ", pio_mpi_rank_g); \
|
||||
fprintf(stderr, "Proc %d: ", pio_mpi_rank_g); \
|
||||
fprintf(stderr, "*** Assertion failed (%s) at line %4d in %s\n", \
|
||||
mesg, (int)__LINE__, __FILE__); \
|
||||
}
|
||||
|
||||
#define MSG(mesg) { \
|
||||
fprintf(stderr, "Proc %d: ", pio_mpi_rank_g); \
|
||||
fprintf(stderr, "Proc %d: ", pio_mpi_rank_g); \
|
||||
fprintf(stderr, "(%s) at line %4d in %s\n", \
|
||||
mesg, (int)__LINE__, __FILE__); \
|
||||
}
|
||||
@ -93,13 +93,13 @@ enum {
|
||||
};
|
||||
|
||||
/* Global variables */
|
||||
MPI_Comm pio_comm_g; /* Communicator to run the PIO */
|
||||
int pio_mpi_rank_g; /* MPI rank of pio_comm_g */
|
||||
int pio_mpi_nprocs_g; /* number of processes of pio_comm_g */
|
||||
MPI_Comm pio_comm_g; /* Communicator to run the PIO */
|
||||
int pio_mpi_rank_g; /* MPI rank of pio_comm_g */
|
||||
int pio_mpi_nprocs_g; /* number of processes of pio_comm_g */
|
||||
|
||||
static int clean_file_g = -1; /*whether to cleanup temporary test */
|
||||
/*files. -1 is not defined; */
|
||||
/*0 is no cleanup; 1 is do cleanup */
|
||||
static int clean_file_g = -1; /*whether to cleanup temporary test */
|
||||
/*files. -1 is not defined; */
|
||||
/*0 is no cleanup; 1 is do cleanup */
|
||||
|
||||
|
||||
|
||||
@ -152,7 +152,7 @@ results
|
||||
do_pio(parameters param)
|
||||
{
|
||||
/* return codes */
|
||||
int rc; /*routine return code */
|
||||
int rc; /*routine return code */
|
||||
int mrc; /*MPI return code */
|
||||
herr_t ret_code = 0; /*return code */
|
||||
results res;
|
||||
@ -166,33 +166,34 @@ do_pio(parameters param)
|
||||
long ndsets, nelmts;
|
||||
int color; /*for communicator creation */
|
||||
char *buffer = NULL; /*data buffer pointer */
|
||||
long buf_size; /*data buffer size in bytes */
|
||||
long buf_size; /*data buffer size in bytes */
|
||||
|
||||
/* HDF5 variables */
|
||||
herr_t hrc; /*HDF5 return code */
|
||||
herr_t hrc; /*HDF5 return code */
|
||||
|
||||
/* MPI variables */
|
||||
int myrank, nprocs = 1;
|
||||
|
||||
pio_comm_g = MPI_COMM_NULL;
|
||||
|
||||
/* parameters sanity check */
|
||||
/* Sanity check parameters */
|
||||
|
||||
/* IO type */
|
||||
iot = param.io_type;
|
||||
|
||||
switch (iot) {
|
||||
case MPIO:
|
||||
fd.mpifd = MPI_FILE_NULL;
|
||||
fd.mpifd = MPI_FILE_NULL;
|
||||
res.timers = pio_time_new(MPI_TIMER);
|
||||
break;
|
||||
case RAW:
|
||||
fd.rawfd = -1;
|
||||
res.timers = pio_time_new(SYS_TIMER);
|
||||
break;
|
||||
case PHDF5:
|
||||
fd.h5fd = -1;
|
||||
fd.rawfd = -1;
|
||||
res.timers = pio_time_new(SYS_TIMER);
|
||||
break;
|
||||
case PHDF5:
|
||||
fd.h5fd = -1;
|
||||
res.timers = pio_time_new(SYS_TIMER);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* unknown request */
|
||||
fprintf(stderr, "Unknown IO type request (%d)\n", iot);
|
||||
@ -202,7 +203,7 @@ do_pio(parameters param)
|
||||
nfiles = param.num_files; /* number of files */
|
||||
ndsets = param.num_dsets; /* number of datasets per file */
|
||||
nelmts = param.num_elmts; /* number of elements per dataset */
|
||||
maxprocs = param.max_num_procs; /* max number of mpi-processes to use */
|
||||
maxprocs = param.num_procs; /* max number of mpi-processes to use */
|
||||
buf_size = param.buf_size;
|
||||
|
||||
if (nfiles < 0 ) {
|
||||
@ -295,7 +296,7 @@ buf_size=MIN(1024*1024, buf_size);
|
||||
|
||||
for (nf = 1; nf <= nfiles; nf++) {
|
||||
/*
|
||||
* Wirte performance measurement
|
||||
* Write performance measurement
|
||||
*/
|
||||
/* Open file for write */
|
||||
char base_name[256];
|
||||
@ -329,15 +330,25 @@ fprintf(stderr, "filename=%s\n", fname);
|
||||
* Read performance measurement
|
||||
*/
|
||||
/* Open file for read */
|
||||
set_time(res.timers, HDF5_FILE_OPENCLOSE, START);
|
||||
hrc = do_fopen(iot, fname, &fd, PIO_READ);
|
||||
set_time(res.timers, HDF5_FILE_OPENCLOSE, STOP);
|
||||
|
||||
VRFY((hrc == SUCCESS), "do_fopen failed");
|
||||
|
||||
hrc = do_read(&fd, iot, ndsets, nelmts, buf_size, buffer);
|
||||
VRFY((hrc == SUCCESS), "do_read failed");
|
||||
set_time(res.timers, HDF5_READ_FIXED_DIMS, START);
|
||||
hrc = do_read(&fd, iot, ndsets, nelmts, buf_size, buffer);
|
||||
set_time(res.timers, HDF5_READ_FIXED_DIMS, STOP);
|
||||
|
||||
VRFY((hrc == SUCCESS), "do_read failed");
|
||||
|
||||
/* Close file for read */
|
||||
set_time(res.timers, HDF5_FILE_OPENCLOSE, START);
|
||||
hrc = do_fclose(iot, &fd);
|
||||
set_time(res.timers, HDF5_FILE_OPENCLOSE, STOP);
|
||||
|
||||
VRFY((hrc == SUCCESS), "do_fclose failed");
|
||||
|
||||
do_cleanupfile(iot, fname);
|
||||
}
|
||||
|
||||
@ -349,26 +360,27 @@ done:
|
||||
/* no remove(fname) because that should have happened normally. */
|
||||
switch (iot) {
|
||||
case RAW:
|
||||
if (fd.rawfd != -1)
|
||||
hrc = do_fclose(iot, &fd);
|
||||
if (fd.rawfd != -1)
|
||||
hrc = do_fclose(iot, &fd);
|
||||
break;
|
||||
case MPIO:
|
||||
if (fd.mpifd != MPI_FILE_NULL)
|
||||
hrc = do_fclose(iot, &fd);
|
||||
hrc = do_fclose(iot, &fd);
|
||||
break;
|
||||
case PHDF5:
|
||||
if (fd.h5fd != -1)
|
||||
hrc = do_fclose(iot, &fd);
|
||||
hrc = do_fclose(iot, &fd);
|
||||
break;
|
||||
}
|
||||
|
||||
/* release MPI resources */
|
||||
if (pio_comm_g != MPI_COMM_NULL){
|
||||
mrc = MPI_Comm_free(&pio_comm_g);
|
||||
if (mrc != MPI_SUCCESS) {
|
||||
fprintf(stderr, "MPI_Comm_free failed\n");
|
||||
ret_code = FAIL;
|
||||
}
|
||||
|
||||
if (mrc != MPI_SUCCESS) {
|
||||
fprintf(stderr, "MPI_Comm_free failed\n");
|
||||
ret_code = FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* release generic resources */
|
||||
@ -499,27 +511,27 @@ static herr_t
|
||||
do_write(file_descr *fd, iotype iot, long ndsets,
|
||||
long nelmts, long buf_size, void *buffer)
|
||||
{
|
||||
int ret_code = SUCCESS;
|
||||
int rc; /*routine return code */
|
||||
int ret_code = SUCCESS;
|
||||
int rc; /*routine return code */
|
||||
int mrc; /*MPI return code */
|
||||
MPI_Offset mpi_offset;
|
||||
MPI_Status mpi_status;
|
||||
long ndset;
|
||||
long nelmts_towrite, nelmts_written;
|
||||
char dname[64];
|
||||
off_t dset_offset; /*dataset offset in a file */
|
||||
off_t file_offset; /*file offset of the next transfer */
|
||||
long dset_size; /*one dataset size in bytes */
|
||||
long nelmts_in_buf;
|
||||
long elmts_begin; /*first elmt this process transfer */
|
||||
long elmts_count; /*number of elmts this process transfer */
|
||||
long ndset;
|
||||
long nelmts_towrite, nelmts_written;
|
||||
char dname[64];
|
||||
off_t dset_offset; /*dataset offset in a file */
|
||||
off_t file_offset; /*file offset of the next transfer */
|
||||
long dset_size; /*one dataset size in bytes */
|
||||
long nelmts_in_buf;
|
||||
long elmts_begin; /*first elmt this process transfer */
|
||||
long elmts_count; /*number of elmts this process transfer */
|
||||
|
||||
/* HDF5 variables */
|
||||
herr_t hrc; /*HDF5 return code */
|
||||
hsize_t h5dims[1]; /*dataset dim sizes */
|
||||
hid_t h5dset_space_id = -1; /*dataset space ID */
|
||||
hid_t h5mem_space_id = -1; /*memory dataspace ID */
|
||||
hid_t h5ds_id = -1; /* dataset handle */
|
||||
hid_t h5ds_id = -1; /*dataset handle */
|
||||
|
||||
#if AKCDEBUG
|
||||
fprintf(stderr, "In do_write\n");
|
||||
@ -527,6 +539,7 @@ fprintf(stderr, "ndsets=%ld\n", ndsets);
|
||||
fprintf(stderr, "nelmts=%ld\n", nelmts);
|
||||
fprintf(stderr, "buffer size=%ld\n", buf_size);
|
||||
#endif
|
||||
|
||||
/* calculate dataset parameters. data type is always native C int */
|
||||
dset_size = nelmts * ELMT_SIZE;
|
||||
nelmts_in_buf = buf_size/ELMT_SIZE;
|
||||
@ -569,19 +582,19 @@ fprintf(stderr, "buffer size=%ld\n", buf_size);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Calculate the first element and how many elements this process
|
||||
* transfer. First calculate the beginning element of this process
|
||||
* and the next process. Count of elements is the difference between
|
||||
* these two beginnings. This way, it avoids any rounding errors.
|
||||
*/
|
||||
elmts_begin = (nelmts*1.0)/pio_mpi_nprocs_g*pio_mpi_rank_g;
|
||||
if (pio_mpi_rank_g < (pio_mpi_nprocs_g - 1)){
|
||||
elmts_count = ((nelmts*1.0)/pio_mpi_nprocs_g*(pio_mpi_rank_g+1)) -
|
||||
elmts_begin;
|
||||
}else{
|
||||
/* last process. Take whatever are left */
|
||||
elmts_count = nelmts - elmts_begin;
|
||||
}
|
||||
/* Calculate the first element and how many elements this process
|
||||
* transfer. First calculate the beginning element of this process
|
||||
* and the next process. Count of elements is the difference between
|
||||
* these two beginnings. This way, it avoids any rounding errors.
|
||||
*/
|
||||
elmts_begin = (nelmts*1.0)/pio_mpi_nprocs_g*pio_mpi_rank_g;
|
||||
|
||||
if (pio_mpi_rank_g < (pio_mpi_nprocs_g - 1))
|
||||
elmts_count = ((nelmts * 1.0) / pio_mpi_nprocs_g * (pio_mpi_rank_g + 1))
|
||||
- elmts_begin;
|
||||
else
|
||||
/* last process. Take whatever are left */
|
||||
elmts_count = nelmts - elmts_begin;
|
||||
|
||||
#if AKCDEBUG
|
||||
fprintf(stderr, "proc %d: elmts_begin=%ld, elmts_count=%ld\n",
|
||||
@ -589,6 +602,7 @@ fprintf(stderr, "proc %d: elmts_begin=%ld, elmts_count=%ld\n",
|
||||
#endif
|
||||
|
||||
nelmts_written = 0 ;
|
||||
|
||||
while (nelmts_written < elmts_count){
|
||||
nelmts_towrite = elmts_count - nelmts_written;
|
||||
|
||||
@ -612,56 +626,60 @@ fprintf(stderr, "proc %d: elmts_begin=%ld, elmts_count=%ld\n",
|
||||
|
||||
/* Write */
|
||||
/* Calculate offset of write within a dataset/file */
|
||||
switch (iot){
|
||||
switch (iot) {
|
||||
case RAW:
|
||||
file_offset = dset_offset +
|
||||
(elmts_begin + nelmts_written)*ELMT_SIZE;
|
||||
file_offset = dset_offset + (elmts_begin + nelmts_written)*ELMT_SIZE;
|
||||
|
||||
#if AKCDEBUG
|
||||
fprintf(stderr, "proc %d: writes %ld bytes at file-offset %ld\n",
|
||||
pio_mpi_rank_g, nelmts_towrite*ELMT_SIZE, file_offset);
|
||||
pio_mpi_rank_g, nelmts_towrite*ELMT_SIZE, file_offset);
|
||||
#endif
|
||||
|
||||
rc = RAWSEEK(fd->rawfd, file_offset);
|
||||
VRFY((rc>=0), "RAWSEEK");
|
||||
VRFY((rc>=0), "RAWSEEK");
|
||||
rc = RAWWRITE(fd->rawfd, buffer, nelmts_towrite*ELMT_SIZE);
|
||||
VRFY((rc==(nelmts_towrite*ELMT_SIZE)), "RAWWRITE");
|
||||
VRFY((rc==(nelmts_towrite*ELMT_SIZE)), "RAWWRITE");
|
||||
break;
|
||||
|
||||
case MPIO:
|
||||
mpi_offset = dset_offset +
|
||||
(elmts_begin + nelmts_written)*ELMT_SIZE;
|
||||
mpi_offset = dset_offset + (elmts_begin + nelmts_written)*ELMT_SIZE;
|
||||
|
||||
#if AKCDEBUG
|
||||
fprintf(stderr, "proc %d: writes %ld bytes at mpi-offset %ld\n",
|
||||
pio_mpi_rank_g, nelmts_towrite*ELMT_SIZE, mpi_offset);
|
||||
pio_mpi_rank_g, nelmts_towrite*ELMT_SIZE, mpi_offset);
|
||||
#endif
|
||||
mrc = MPI_File_write_at(fd->mpifd, mpi_offset, buffer,
|
||||
nelmts_towrite*ELMT_SIZE, MPI_CHAR, &mpi_status);
|
||||
VRFY((mrc==MPI_SUCCESS), "MPIO_WRITE");
|
||||
break;
|
||||
|
||||
mrc = MPI_File_write_at(fd->mpifd, mpi_offset, buffer,
|
||||
nelmts_towrite * ELMT_SIZE, MPI_CHAR,
|
||||
&mpi_status);
|
||||
VRFY((mrc==MPI_SUCCESS), "MPIO_WRITE");
|
||||
break;
|
||||
case PHDF5:
|
||||
/*set up the dset space id to select the segment to process */
|
||||
{
|
||||
hsize_t block[1], stride[1], count[1];
|
||||
hssize_t start[1];
|
||||
|
||||
start[0] = elmts_begin + nelmts_written;
|
||||
stride[0] = block[0] = nelmts_towrite;
|
||||
count[0] = 1;
|
||||
hrc = H5Sselect_hyperslab(h5dset_space_id, H5S_SELECT_SET,
|
||||
start, stride, count, block);
|
||||
VRFY((hrc >= 0), "H5Sset_hyperslab");
|
||||
/*set up the dset space id to select the segment to process */
|
||||
{
|
||||
hsize_t block[1], stride[1], count[1];
|
||||
hssize_t start[1];
|
||||
|
||||
start[0] = elmts_begin + nelmts_written;
|
||||
stride[0] = block[0] = nelmts_towrite;
|
||||
count[0] = 1;
|
||||
hrc = H5Sselect_hyperslab(h5dset_space_id, H5S_SELECT_SET,
|
||||
start, stride, count, block);
|
||||
VRFY((hrc >= 0), "H5Sset_hyperslab");
|
||||
|
||||
/*setup the memory space id too. Only start is different */
|
||||
start[0] = 0;
|
||||
hrc = H5Sselect_hyperslab(h5mem_space_id, H5S_SELECT_SET,
|
||||
start, stride, count, block);
|
||||
VRFY((hrc >= 0), "H5Sset_hyperslab");
|
||||
}
|
||||
MPI_Barrier(pio_comm_g);
|
||||
/*setup the memory space id too. Only start is different */
|
||||
start[0] = 0;
|
||||
hrc = H5Sselect_hyperslab(h5mem_space_id, H5S_SELECT_SET,
|
||||
start, stride, count, block);
|
||||
VRFY((hrc >= 0), "H5Sset_hyperslab");
|
||||
}
|
||||
|
||||
/* set write time here */
|
||||
hrc = H5Dwrite(h5ds_id, H5T_NATIVE_INT, h5mem_space_id,
|
||||
h5dset_space_id, H5P_DEFAULT, buffer);
|
||||
VRFY((hrc >= 0), "H5Dwrite");
|
||||
MPI_Barrier(pio_comm_g);
|
||||
|
||||
/* set write time here */
|
||||
hrc = H5Dwrite(h5ds_id, H5T_NATIVE_INT, h5mem_space_id,
|
||||
h5dset_space_id, H5P_DEFAULT, buffer);
|
||||
VRFY((hrc >= 0), "H5Dwrite");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -708,7 +726,6 @@ done:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: do_read
|
||||
* Purpose: read the required amount of data from the file.
|
||||
@ -720,27 +737,27 @@ static herr_t
|
||||
do_read(file_descr *fd, iotype iot, long ndsets,
|
||||
long nelmts, long buf_size, void *buffer /*out*/)
|
||||
{
|
||||
int ret_code = SUCCESS;
|
||||
int rc; /*routine return code */
|
||||
int ret_code = SUCCESS;
|
||||
int rc; /*routine return code */
|
||||
int mrc; /*MPI return code */
|
||||
MPI_Offset mpi_offset;
|
||||
MPI_Status mpi_status;
|
||||
long ndset;
|
||||
long nelmts_toread, nelmts_read;
|
||||
char dname[64];
|
||||
off_t dset_offset; /*dataset offset in a file */
|
||||
off_t file_offset; /*file offset of the next transfer */
|
||||
long dset_size; /*one dataset size in bytes */
|
||||
long nelmts_in_buf;
|
||||
long elmts_begin; /*first elmt this process transfer */
|
||||
long elmts_count; /*number of elmts this process transfer */
|
||||
MPI_Offset mpi_offset;
|
||||
MPI_Status mpi_status;
|
||||
long ndset;
|
||||
long nelmts_toread, nelmts_read;
|
||||
char dname[64];
|
||||
off_t dset_offset; /*dataset offset in a file */
|
||||
off_t file_offset; /*file offset of the next transfer */
|
||||
long dset_size; /*one dataset size in bytes */
|
||||
long nelmts_in_buf;
|
||||
long elmts_begin; /*first elmt this process transfer */
|
||||
long elmts_count; /*number of elmts this process transfer */
|
||||
|
||||
/* HDF5 variables */
|
||||
herr_t hrc; /*HDF5 return code */
|
||||
hsize_t h5dims[1]; /*dataset dim sizes */
|
||||
hid_t h5dset_space_id = -1; /*dataset space ID */
|
||||
hid_t h5mem_space_id = -1; /*memory dataspace ID */
|
||||
hid_t h5ds_id = -1; /* dataset handle */
|
||||
herr_t hrc; /*HDF5 return code */
|
||||
hsize_t h5dims[1]; /*dataset dim sizes */
|
||||
hid_t h5dset_space_id = -1; /*dataset space ID */
|
||||
hid_t h5mem_space_id = -1; /*memory dataspace ID */
|
||||
hid_t h5ds_id = -1; /*dataset handle */
|
||||
|
||||
#if AKCDEBUG
|
||||
fprintf(stderr, "In do_read\n");
|
||||
@ -748,6 +765,7 @@ fprintf(stderr, "ndsets=%ld\n", ndsets);
|
||||
fprintf(stderr, "nelmts=%ld\n", nelmts);
|
||||
fprintf(stderr, "buffer size=%ld\n", buf_size);
|
||||
#endif
|
||||
|
||||
/* calculate dataset parameters. data type is always native C int */
|
||||
dset_size = nelmts * ELMT_SIZE;
|
||||
nelmts_in_buf = buf_size/ELMT_SIZE;
|
||||
@ -766,7 +784,6 @@ fprintf(stderr, "buffer size=%ld\n", buf_size);
|
||||
}
|
||||
|
||||
for (ndset = 1; ndset <= ndsets; ++ndset) {
|
||||
|
||||
/* Calculate dataset offset within a file */
|
||||
|
||||
/* create dataset */
|
||||
@ -788,88 +805,94 @@ fprintf(stderr, "buffer size=%ld\n", buf_size);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Calculate the first element and how many elements this process
|
||||
* transfer. First calculate the beginning element of this process
|
||||
* and the next process. Count of elements is the difference between
|
||||
* these two beginnings. This way, it avoids any rounding errors.
|
||||
*/
|
||||
elmts_begin = (nelmts*1.0)/pio_mpi_nprocs_g*pio_mpi_rank_g;
|
||||
if (pio_mpi_rank_g < (pio_mpi_nprocs_g - 1)){
|
||||
elmts_count = ((nelmts*1.0)/pio_mpi_nprocs_g*(pio_mpi_rank_g+1)) -
|
||||
elmts_begin;
|
||||
}else{
|
||||
/* last process. Take whatever are left */
|
||||
elmts_count = nelmts - elmts_begin;
|
||||
}
|
||||
/*
|
||||
* Calculate the first element and how many elements this process
|
||||
* transfer. First calculate the beginning element of this process
|
||||
* and the next process. Count of elements is the difference between
|
||||
* these two beginnings. This way, it avoids any rounding errors.
|
||||
*/
|
||||
elmts_begin = (nelmts*1.0)/pio_mpi_nprocs_g*pio_mpi_rank_g;
|
||||
|
||||
if (pio_mpi_rank_g < (pio_mpi_nprocs_g - 1))
|
||||
elmts_count = ((nelmts * 1.0) / pio_mpi_nprocs_g * (pio_mpi_rank_g + 1)) -
|
||||
elmts_begin;
|
||||
else
|
||||
/* last process. Take whatever are left */
|
||||
elmts_count = nelmts - elmts_begin;
|
||||
|
||||
#if AKCDEBUG
|
||||
fprintf(stderr, "proc %d: elmts_begin=%ld, elmts_count=%ld\n",
|
||||
pio_mpi_rank_g, elmts_begin, elmts_count);
|
||||
pio_mpi_rank_g, elmts_begin, elmts_count);
|
||||
#endif
|
||||
|
||||
nelmts_read = 0 ;
|
||||
|
||||
while (nelmts_read < elmts_count){
|
||||
nelmts_toread = elmts_count - nelmts_read;
|
||||
|
||||
if (elmts_count - nelmts_read >= nelmts_in_buf) {
|
||||
if (elmts_count - nelmts_read >= nelmts_in_buf)
|
||||
nelmts_toread = nelmts_in_buf;
|
||||
} else {
|
||||
else
|
||||
/* last read of a partial buffer */
|
||||
nelmts_toread = elmts_count - nelmts_read;
|
||||
}
|
||||
|
||||
/* read */
|
||||
/* Calculate offset of read within a dataset/file */
|
||||
switch (iot){
|
||||
case RAW:
|
||||
file_offset = dset_offset +
|
||||
(elmts_begin + nelmts_read)*ELMT_SIZE;
|
||||
file_offset = dset_offset + (elmts_begin + nelmts_read)*ELMT_SIZE;
|
||||
|
||||
#if AKCDEBUG
|
||||
fprintf(stderr, "proc %d: read %ld bytes at file-offset %ld\n",
|
||||
pio_mpi_rank_g, nelmts_toread*ELMT_SIZE, file_offset);
|
||||
pio_mpi_rank_g, nelmts_toread*ELMT_SIZE, file_offset);
|
||||
#endif
|
||||
|
||||
rc = RAWSEEK(fd->rawfd, file_offset);
|
||||
VRFY((rc>=0), "RAWSEEK");
|
||||
VRFY((rc>=0), "RAWSEEK");
|
||||
rc = RAWREAD(fd->rawfd, buffer, nelmts_toread*ELMT_SIZE);
|
||||
VRFY((rc==(nelmts_toread*ELMT_SIZE)), "RAWREAD");
|
||||
VRFY((rc==(nelmts_toread*ELMT_SIZE)), "RAWREAD");
|
||||
break;
|
||||
|
||||
case MPIO:
|
||||
mpi_offset = dset_offset +
|
||||
(elmts_begin + nelmts_read)*ELMT_SIZE;
|
||||
mpi_offset = dset_offset + (elmts_begin + nelmts_read)*ELMT_SIZE;
|
||||
|
||||
#if AKCDEBUG
|
||||
fprintf(stderr, "proc %d: read %ld bytes at mpi-offset %ld\n",
|
||||
pio_mpi_rank_g, nelmts_toread*ELMT_SIZE, mpi_offset);
|
||||
#endif
|
||||
mrc = MPI_File_read_at(fd->mpifd, mpi_offset, buffer,
|
||||
nelmts_toread*ELMT_SIZE, MPI_CHAR, &mpi_status);
|
||||
VRFY((mrc==MPI_SUCCESS), "MPIO_read");
|
||||
break;
|
||||
|
||||
mrc = MPI_File_read_at(fd->mpifd, mpi_offset, buffer,
|
||||
nelmts_toread*ELMT_SIZE, MPI_CHAR,
|
||||
&mpi_status);
|
||||
VRFY((mrc==MPI_SUCCESS), "MPIO_read");
|
||||
break;
|
||||
|
||||
case PHDF5:
|
||||
/*set up the dset space id to select the segment to process */
|
||||
{
|
||||
hsize_t block[1], stride[1], count[1];
|
||||
hssize_t start[1];
|
||||
|
||||
start[0] = elmts_begin + nelmts_read;
|
||||
stride[0] = block[0] = nelmts_toread;
|
||||
count[0] = 1;
|
||||
hrc = H5Sselect_hyperslab(h5dset_space_id, H5S_SELECT_SET,
|
||||
start, stride, count, block);
|
||||
VRFY((hrc >= 0), "H5Sset_hyperslab");
|
||||
/*set up the dset space id to select the segment to process */
|
||||
{
|
||||
hsize_t block[1], stride[1], count[1];
|
||||
hssize_t start[1];
|
||||
|
||||
start[0] = elmts_begin + nelmts_read;
|
||||
stride[0] = block[0] = nelmts_toread;
|
||||
count[0] = 1;
|
||||
hrc = H5Sselect_hyperslab(h5dset_space_id, H5S_SELECT_SET,
|
||||
start, stride, count, block);
|
||||
VRFY((hrc >= 0), "H5Sset_hyperslab");
|
||||
|
||||
/*setup the memory space id too. Only start is different */
|
||||
start[0] = 0;
|
||||
hrc = H5Sselect_hyperslab(h5mem_space_id, H5S_SELECT_SET,
|
||||
start, stride, count, block);
|
||||
VRFY((hrc >= 0), "H5Sset_hyperslab");
|
||||
}
|
||||
MPI_Barrier(pio_comm_g);
|
||||
/*setup the memory space id too. Only start is different */
|
||||
start[0] = 0;
|
||||
hrc = H5Sselect_hyperslab(h5mem_space_id, H5S_SELECT_SET,
|
||||
start, stride, count, block);
|
||||
VRFY((hrc >= 0), "H5Sset_hyperslab");
|
||||
}
|
||||
|
||||
/* set read time here */
|
||||
hrc = H5Dread(h5ds_id, H5T_NATIVE_INT, h5mem_space_id,
|
||||
h5dset_space_id, H5P_DEFAULT, buffer);
|
||||
VRFY((hrc >= 0), "H5Dread");
|
||||
MPI_Barrier(pio_comm_g);
|
||||
|
||||
/* set read time here */
|
||||
hrc = H5Dread(h5ds_id, H5T_NATIVE_INT, h5mem_space_id,
|
||||
h5dset_space_id, H5P_DEFAULT, buffer);
|
||||
VRFY((hrc >= 0), "H5Dread");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -880,7 +903,7 @@ fprintf(stderr, "proc %d: read %ld bytes at mpi-offset %ld\n",
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < nelmts_towrite; ++i)
|
||||
/* TO BE IMPLEMENTED */
|
||||
/* TO BE IMPLEMENTED */
|
||||
;
|
||||
}
|
||||
#endif
|
||||
@ -928,7 +951,6 @@ done:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: do_fopen
|
||||
* Purpose: Open the specified file.
|
||||
@ -945,11 +967,10 @@ do_fopen(iotype iot, char *fname, file_descr *fd /*out*/, int flags)
|
||||
|
||||
switch (iot) {
|
||||
case RAW:
|
||||
if (flags & (PIO_CREATE | PIO_WRITE)) {
|
||||
if (flags & (PIO_CREATE | PIO_WRITE))
|
||||
fd->rawfd = RAWCREATE(fname);
|
||||
} else {
|
||||
else
|
||||
fd->rawfd = RAWOPEN(fname, O_RDONLY);
|
||||
}
|
||||
|
||||
if (fd->rawfd < 0 ) {
|
||||
fprintf(stderr, "Raw File Open failed(%s)\n", fname);
|
||||
@ -960,30 +981,32 @@ do_fopen(iotype iot, char *fname, file_descr *fd /*out*/, int flags)
|
||||
|
||||
case MPIO:
|
||||
if (flags & (PIO_CREATE | PIO_WRITE)) {
|
||||
MPI_File_delete(fname, MPI_INFO_NULL);
|
||||
MPI_File_delete(fname, MPI_INFO_NULL);
|
||||
mrc = MPI_File_open(pio_comm_g, fname, MPI_MODE_CREATE | MPI_MODE_RDWR,
|
||||
MPI_INFO_NULL, &fd->mpifd);
|
||||
if (mrc != MPI_SUCCESS) {
|
||||
fprintf(stderr, "MPI File Open failed(%s)\n", fname);
|
||||
GOTOERROR(FAIL);
|
||||
}
|
||||
/*since MPI_File_open with MPI_MODE_CREATE does not truncate */
|
||||
/*filesize , set size to 0 explicitedly. */
|
||||
mrc = MPI_File_set_size(fd->mpifd, 0);
|
||||
if (mrc != MPI_SUCCESS) {
|
||||
fprintf(stderr, "MPI_File_set_size failed\n");
|
||||
GOTOERROR(FAIL);
|
||||
}
|
||||
|
||||
if (mrc != MPI_SUCCESS) {
|
||||
fprintf(stderr, "MPI File Open failed(%s)\n", fname);
|
||||
GOTOERROR(FAIL);
|
||||
}
|
||||
|
||||
/*since MPI_File_open with MPI_MODE_CREATE does not truncate */
|
||||
/*filesize , set size to 0 explicitedly. */
|
||||
mrc = MPI_File_set_size(fd->mpifd, 0);
|
||||
|
||||
if (mrc != MPI_SUCCESS) {
|
||||
fprintf(stderr, "MPI_File_set_size failed\n");
|
||||
GOTOERROR(FAIL);
|
||||
}
|
||||
} else {
|
||||
mrc = MPI_File_open(pio_comm_g, fname, MPI_MODE_RDONLY,
|
||||
MPI_INFO_NULL, &fd->mpifd);
|
||||
if (mrc != MPI_SUCCESS) {
|
||||
fprintf(stderr, "MPI File Open failed(%s)\n", fname);
|
||||
GOTOERROR(FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
if (mrc != MPI_SUCCESS) {
|
||||
fprintf(stderr, "MPI File Open failed(%s)\n", fname);
|
||||
GOTOERROR(FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@ -1095,21 +1118,21 @@ static void
|
||||
do_cleanupfile(iotype iot, char *fname)
|
||||
{
|
||||
if (pio_mpi_rank_g != 0)
|
||||
return;
|
||||
return;
|
||||
|
||||
if (clean_file_g == -1)
|
||||
clean_file_g = (getenv("HDF5_NOCLEANUP")==NULL) ? 1 : 0;
|
||||
clean_file_g = (getenv("HDF5_NOCLEANUP")==NULL) ? 1 : 0;
|
||||
|
||||
if (clean_file_g){
|
||||
switch (iot){
|
||||
case RAW:
|
||||
remove(fname);
|
||||
break;
|
||||
case MPIO:
|
||||
case PHDF5:
|
||||
MPI_File_delete(fname, MPI_INFO_NULL);
|
||||
break;
|
||||
}
|
||||
switch (iot){
|
||||
case RAW:
|
||||
remove(fname);
|
||||
break;
|
||||
case MPIO:
|
||||
case PHDF5:
|
||||
MPI_File_delete(fname, MPI_INFO_NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* H5_HAVE_PARALLEL */
|
||||
|
@ -71,6 +71,10 @@
|
||||
#define ONE_MB (ONE_KB * ONE_KB)
|
||||
#define ONE_GB (ONE_MB * ONE_KB)
|
||||
|
||||
#define PIO_RAW 020
|
||||
#define PIO_MPI 040
|
||||
#define PIO_HDF5 060
|
||||
|
||||
#define MB_PER_SEC(bytes,t) (((bytes) / ONE_MB) / t)
|
||||
|
||||
#define MIN_HDF5_BUF_SIZE (ONE_MB >> 1)
|
||||
@ -85,9 +89,9 @@ static const char *progname = "pio_perf";
|
||||
* adding more, make sure that they don't clash with each other.
|
||||
*/
|
||||
#if 1
|
||||
static const char *s_opts = "ho:m:";
|
||||
static const char *s_opts = "hf:HP:p:X:x:md:F:i:o:r";
|
||||
#else
|
||||
static const char *s_opts = "hbo:m:";
|
||||
static const char *s_opts = "hbf:HP:p:X:x:md:F:i:o:r";
|
||||
#endif /* 1 */
|
||||
static struct long_options l_opts[] = {
|
||||
{ "help", no_arg, 'h' },
|
||||
@ -101,28 +105,102 @@ static struct long_options l_opts[] = {
|
||||
{ "bin", no_arg, 'b' },
|
||||
{ "bi", no_arg, 'b' },
|
||||
#endif /* 0 */
|
||||
{ "max-size", require_arg, 'm' },
|
||||
{ "max-siz", require_arg, 'm' },
|
||||
{ "max-si", require_arg, 'm' },
|
||||
{ "max-s", require_arg, 'm' },
|
||||
{ "max", require_arg, 'm' },
|
||||
{ "ma", require_arg, 'm' },
|
||||
{ "file-size", require_arg, 'f' },
|
||||
{ "file-siz", require_arg, 'f' },
|
||||
{ "file-si", require_arg, 'f' },
|
||||
{ "file-s", require_arg, 'f' },
|
||||
{ "file", require_arg, 'f' },
|
||||
{ "fil", require_arg, 'f' },
|
||||
{ "fi", require_arg, 'f' },
|
||||
{ "hdf5", no_arg, 'H' },
|
||||
{ "hdf", no_arg, 'H' },
|
||||
{ "hd", no_arg, 'H' },
|
||||
{ "max-num-processes", require_arg, 'P' },
|
||||
{ "max-num-processe", require_arg, 'P' },
|
||||
{ "max-num-process", require_arg, 'P' },
|
||||
{ "max-num-proces", require_arg, 'P' },
|
||||
{ "max-num-proce", require_arg, 'P' },
|
||||
{ "max-num-proc", require_arg, 'P' },
|
||||
{ "max-num-pro", require_arg, 'P' },
|
||||
{ "max-num-pr", require_arg, 'P' },
|
||||
{ "max-num-p", require_arg, 'P' },
|
||||
{ "min-num-processes", require_arg, 'p' },
|
||||
{ "min-num-processe", require_arg, 'p' },
|
||||
{ "min-num-process", require_arg, 'p' },
|
||||
{ "min-num-proces", require_arg, 'p' },
|
||||
{ "min-num-proce", require_arg, 'p' },
|
||||
{ "min-num-proc", require_arg, 'p' },
|
||||
{ "min-num-pro", require_arg, 'p' },
|
||||
{ "min-num-pr", require_arg, 'p' },
|
||||
{ "min-num-p", require_arg, 'p' },
|
||||
{ "max-xfer-size", require_arg, 'X' },
|
||||
{ "max-xfer-siz", require_arg, 'X' },
|
||||
{ "max-xfer-si", require_arg, 'X' },
|
||||
{ "max-xfer-s", require_arg, 'X' },
|
||||
{ "max-xfer", require_arg, 'X' },
|
||||
{ "max-xfe", require_arg, 'X' },
|
||||
{ "max-xf", require_arg, 'X' },
|
||||
{ "max-x", require_arg, 'X' },
|
||||
{ "min-xfer-size", require_arg, 'x' },
|
||||
{ "min-xfer-siz", require_arg, 'x' },
|
||||
{ "min-xfer-si", require_arg, 'x' },
|
||||
{ "min-xfer-s", require_arg, 'x' },
|
||||
{ "min-xfer", require_arg, 'x' },
|
||||
{ "min-xfe", require_arg, 'x' },
|
||||
{ "min-xf", require_arg, 'x' },
|
||||
{ "min-x", require_arg, 'x' },
|
||||
{ "mpiio", no_arg, 'm' },
|
||||
{ "mpii", no_arg, 'm' },
|
||||
{ "mpi", no_arg, 'm' },
|
||||
{ "mp", no_arg, 'm' },
|
||||
{ "num-dsets", require_arg, 'd' },
|
||||
{ "num-dset", require_arg, 'd' },
|
||||
{ "num-dse", require_arg, 'd' },
|
||||
{ "num-ds", require_arg, 'd' },
|
||||
{ "num-d", require_arg, 'd' },
|
||||
{ "num-files", require_arg, 'F' },
|
||||
{ "num-file", require_arg, 'F' },
|
||||
{ "num-fil", require_arg, 'F' },
|
||||
{ "num-fi", require_arg, 'F' },
|
||||
{ "num-f", require_arg, 'F' },
|
||||
{ "num-iterations", require_arg, 'i' },
|
||||
{ "num-iteration", require_arg, 'i' },
|
||||
{ "num-iteratio", require_arg, 'i' },
|
||||
{ "num-iterati", require_arg, 'i' },
|
||||
{ "num-iterat", require_arg, 'i' },
|
||||
{ "num-itera", require_arg, 'i' },
|
||||
{ "num-iter", require_arg, 'i' },
|
||||
{ "num-ite", require_arg, 'i' },
|
||||
{ "num-it", require_arg, 'i' },
|
||||
{ "num-i", require_arg, 'i' },
|
||||
{ "output", require_arg, 'o' },
|
||||
{ "outpu", require_arg, 'o' },
|
||||
{ "outp", require_arg, 'o' },
|
||||
{ "out", require_arg, 'o' },
|
||||
{ "ou", require_arg, 'o' },
|
||||
{ "raw", no_arg, 'r' },
|
||||
{ "ra", no_arg, 'r' },
|
||||
{ NULL, 0, '\0' }
|
||||
};
|
||||
|
||||
struct options {
|
||||
long io_types; /* bitmask of which I/O types to test */
|
||||
const char *output_file; /* file to print report to */
|
||||
long max_size; /* maximum size of file in gigabytes */
|
||||
long file_size; /* size of file */
|
||||
long num_dsets; /* number of datasets */
|
||||
long num_files; /* number of files */
|
||||
long num_iters; /* number of iterations */
|
||||
long max_num_procs; /* maximum number of processes to use */
|
||||
long min_num_procs; /* minimum number of processes to use */
|
||||
long max_xfer_size; /* maximum transfer buffer size */
|
||||
long min_xfer_size; /* minimum transfer buffer size */
|
||||
};
|
||||
|
||||
/* local functions */
|
||||
static long parse_size_directive(const char *size);
|
||||
static struct options *parse_command_line(int argc, char *argv[]);
|
||||
static void run_test_loop(FILE *output, int max_num_procs, long max_size);
|
||||
static void run_test_loop(FILE *output, struct options *options);
|
||||
static void run_test(FILE *output, iotype iot, parameters parms);
|
||||
static void print_indent(register FILE *output, register int indent);
|
||||
static void usage(const char *prog);
|
||||
|
||||
@ -168,7 +246,7 @@ main(int argc, char **argv)
|
||||
goto cheese_and;
|
||||
}
|
||||
|
||||
run_test_loop(output, world_size, opts->max_size);
|
||||
run_test_loop(output, opts);
|
||||
|
||||
cheese_and:
|
||||
MPI_Finalize();
|
||||
@ -199,62 +277,103 @@ onions:
|
||||
* Modifications:
|
||||
*/
|
||||
static void
|
||||
run_test_loop(FILE *output, int max_num_procs, long max_size)
|
||||
run_test_loop(FILE *output, struct options *opts)
|
||||
{
|
||||
parameters parms;
|
||||
long num_procs;
|
||||
int io_runs = PIO_HDF5 | PIO_MPI | PIO_RAW; /* default to run all tests */
|
||||
|
||||
/* num_files stays ``1'' for now but may change later */
|
||||
parms.num_files = 1;
|
||||
parms.num_iters = 1;
|
||||
if (opts->io_types & ~07) {
|
||||
/* we want to run only a select subset of these tests */
|
||||
opts->io_types = 0;
|
||||
|
||||
if (opts->io_types | PIO_HDF5)
|
||||
io_runs |= PIO_HDF5;
|
||||
|
||||
if (opts->io_types | PIO_MPI)
|
||||
io_runs |= PIO_MPI;
|
||||
|
||||
if (opts->io_types | PIO_RAW)
|
||||
io_runs |= PIO_RAW;
|
||||
}
|
||||
|
||||
parms.num_files = opts->num_files;
|
||||
parms.num_dsets = opts->num_dsets;
|
||||
parms.num_iters = opts->num_iters;
|
||||
|
||||
/* divide the maximum number of processors by 2 for each loop iter */
|
||||
for (; max_num_procs > 0; max_num_procs /= 2) {
|
||||
register iotype i;
|
||||
for (num_procs = opts->min_num_procs;
|
||||
num_procs <= opts->max_num_procs; num_procs <<= 1) {
|
||||
register long j;
|
||||
|
||||
parms.max_num_procs = max_num_procs;
|
||||
fprintf(output, "Number of processors = %u\n", parms.max_num_procs);
|
||||
parms.num_procs = num_procs;
|
||||
fprintf(output, "Number of processors = %u\n", parms.num_procs);
|
||||
|
||||
for (i = RAW; i <= PHDF5; ++i) {
|
||||
register unsigned long j;
|
||||
for (j = opts->min_xfer_size; j <= opts->max_xfer_size; j <<= 1) {
|
||||
parms.buf_size = j;
|
||||
parms.num_elmts = opts->file_size / (parms.num_dsets * sizeof(int));
|
||||
|
||||
parms.io_type = i;
|
||||
print_indent(output, TAB_SPACE * 1);
|
||||
fprintf(output, "Type of IO = ");
|
||||
fprintf(output,
|
||||
"# of files: %u, # of dsets: %lu, Elements per dset: %lu\n",
|
||||
parms.num_files, parms.num_dsets, parms.num_elmts);
|
||||
|
||||
if (i == RAW)
|
||||
fprintf(output, "Raw\n");
|
||||
else if (i == MPIO)
|
||||
fprintf(output, "MPIO\n");
|
||||
else
|
||||
fprintf(output, "PHDF5\n");
|
||||
if (io_runs | PIO_RAW)
|
||||
run_test(output, RAW, parms);
|
||||
|
||||
for (j = MIN_HDF5_BUF_SIZE; j <= MAX_HDF5_BUF_SIZE; j <<= 1) {
|
||||
results res;
|
||||
if (io_runs | PIO_MPI)
|
||||
run_test(output, MPIO, parms);
|
||||
|
||||
parms.buf_size = j;
|
||||
parms.num_dsets = MAX_HDF5_BUF_SIZE / j;
|
||||
parms.num_dsets = (parms.num_dsets ? parms.num_dsets : 1);
|
||||
parms.num_elmts = max_size / (parms.num_dsets * sizeof(int));
|
||||
|
||||
print_indent(output, TAB_SPACE * 2);
|
||||
fprintf(output,
|
||||
"# of files: %u, # of dsets: %lu, Elements per dset: %lu\n",
|
||||
parms.num_files, parms.num_dsets, parms.num_elmts);
|
||||
|
||||
/* call Albert's testing here */
|
||||
res = do_pio(parms);
|
||||
|
||||
print_indent(output, TAB_SPACE * 3);
|
||||
fprintf(output, "Write Results = %.2f MB/s\n",
|
||||
MB_PER_SEC(parms.num_dsets * parms.num_elmts * sizeof(int),
|
||||
get_time(res.timers, HDF5_WRITE_FIXED_DIMS)));
|
||||
|
||||
pio_time_destroy(res.timers);
|
||||
}
|
||||
if (io_runs | PIO_HDF5)
|
||||
run_test(output, PHDF5, parms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: run_test
|
||||
* Purpose: Inner loop call to actually run the I/O test.
|
||||
* Return: Nothing
|
||||
* Programmer: Bill Wendling, 18. December 2001
|
||||
* Modifications:
|
||||
*/
|
||||
static void
|
||||
run_test(FILE *output, iotype iot, parameters parms)
|
||||
{
|
||||
results res;
|
||||
|
||||
parms.io_type = iot;
|
||||
print_indent(output, TAB_SPACE * 2);
|
||||
fprintf(output, "Type of IO = ");
|
||||
|
||||
switch (iot) {
|
||||
case RAW:
|
||||
fprintf(output, "Raw\n");
|
||||
break;
|
||||
case MPIO:
|
||||
fprintf(output, "MPIO\n");
|
||||
break;
|
||||
case PHDF5:
|
||||
fprintf(output, "PHDF5\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* call Albert's testing here */
|
||||
res = do_pio(parms);
|
||||
|
||||
print_indent(output, TAB_SPACE * 3);
|
||||
fprintf(output, "Write Results = %.2f MB/s\n",
|
||||
MB_PER_SEC(parms.num_dsets * parms.num_elmts * sizeof(int),
|
||||
get_time(res.timers, HDF5_WRITE_FIXED_DIMS)));
|
||||
|
||||
print_indent(output, TAB_SPACE * 3);
|
||||
fprintf(output, "Read Results = %.2f MB/s\n",
|
||||
MB_PER_SEC(parms.num_dsets * parms.num_elmts * sizeof(int),
|
||||
get_time(res.timers, HDF5_READ_FIXED_DIMS)));
|
||||
|
||||
pio_time_destroy(res.timers);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: print_indent
|
||||
* Purpose: Print spaces to indent a new line of text for pretty printing
|
||||
@ -270,27 +389,6 @@ print_indent(register FILE *output, register int indent)
|
||||
fputc(' ', output);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: usage
|
||||
* Purpose: Print a usage message and then exit.
|
||||
* Return: Nothing
|
||||
* Programmer: Bill Wendling, 31. October 2001
|
||||
* Modifications:
|
||||
*/
|
||||
static void
|
||||
usage(const char *prog)
|
||||
{
|
||||
fflush(stdout);
|
||||
fprintf(stdout, "usage: %s [OPTIONS]\n", prog);
|
||||
fprintf(stdout, " OPTIONS\n");
|
||||
fprintf(stdout, " -h, --help Print a usage message and exit\n");
|
||||
fprintf(stdout, " -m #, --max-size=# Maximum size of file in megabytes [default: 512]\n");
|
||||
fprintf(stdout, " -o F, --output=F Output raw data into file F\n");
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, " F - is a filename.\n");
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: parse_command_line
|
||||
* Purpose: Parse the command line options and return a STRUCT OPTIONS
|
||||
@ -305,8 +403,18 @@ parse_command_line(int argc, char *argv[])
|
||||
int opt;
|
||||
struct options *cl_opts;
|
||||
|
||||
cl_opts = (struct options *)calloc(1, sizeof(struct options));
|
||||
cl_opts->max_size = 512 * ONE_MB;
|
||||
cl_opts = (struct options *)malloc(sizeof(struct options));
|
||||
|
||||
cl_opts->output_file = NULL;
|
||||
cl_opts->file_size = 64 * ONE_MB;
|
||||
cl_opts->io_types = 07; /* bottom bits indicate default type to run */
|
||||
cl_opts->num_dsets = 1;
|
||||
cl_opts->num_files = 1;
|
||||
cl_opts->num_iters = 1;
|
||||
cl_opts->max_num_procs = 1;
|
||||
cl_opts->min_num_procs = 1;
|
||||
cl_opts->max_xfer_size = 1 * ONE_MB;
|
||||
cl_opts->min_xfer_size = 1 * ONE_KB;
|
||||
|
||||
while ((opt = get_option(argc, (const char **)argv, s_opts, l_opts)) != EOF) {
|
||||
switch ((char)opt) {
|
||||
@ -315,12 +423,45 @@ parse_command_line(int argc, char *argv[])
|
||||
/* the future "binary" option */
|
||||
break;
|
||||
#endif /* 0 */
|
||||
case 'd':
|
||||
cl_opts->num_dsets = strtol(opt_arg, NULL, 10);
|
||||
break;
|
||||
case 'f':
|
||||
cl_opts->file_size = parse_size_directive(opt_arg);
|
||||
break;
|
||||
case 'F':
|
||||
cl_opts->num_files = strtol(opt_arg, NULL, 10);
|
||||
break;
|
||||
case 'H':
|
||||
cl_opts->io_types &= ~07;
|
||||
cl_opts->io_types |= PIO_HDF5;
|
||||
break;
|
||||
case 'i':
|
||||
cl_opts->num_iters = strtol(opt_arg, NULL, 10);
|
||||
break;
|
||||
case 'm':
|
||||
cl_opts->max_size = atol(opt_arg) * ONE_MB;
|
||||
cl_opts->io_types &= ~07;
|
||||
cl_opts->io_types |= PIO_MPI;
|
||||
break;
|
||||
case 'o':
|
||||
cl_opts->output_file = opt_arg;
|
||||
break;
|
||||
case 'p':
|
||||
cl_opts->min_num_procs = strtol(opt_arg, NULL, 10);
|
||||
break;
|
||||
case 'P':
|
||||
cl_opts->max_num_procs = strtol(opt_arg, NULL, 10);
|
||||
break;
|
||||
case 'r':
|
||||
cl_opts->io_types &= ~07;
|
||||
cl_opts->io_types |= PIO_RAW;
|
||||
break;
|
||||
case 'x':
|
||||
cl_opts->min_xfer_size = parse_size_directive(opt_arg);
|
||||
break;
|
||||
case 'X':
|
||||
cl_opts->max_xfer_size = parse_size_directive(opt_arg);
|
||||
break;
|
||||
case 'h':
|
||||
usage(progname);
|
||||
exit(EXIT_SUCCESS);
|
||||
@ -335,6 +476,94 @@ parse_command_line(int argc, char *argv[])
|
||||
return cl_opts;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: parse_size_directive
|
||||
* Purpose: Parse the size directive passed on the commandline. The size
|
||||
* directive is an integer followed by a size indicator:
|
||||
*
|
||||
* K, k - Kilobyte
|
||||
* M, m - Megabyte
|
||||
* G, g - Gigabyte
|
||||
*
|
||||
* Return: The size as a LONG. If an unknown size indicator is used, then
|
||||
* the program will exit with EXIT_FAILURE as the return value.
|
||||
* Programmer: Bill Wendling, 18. December 2001
|
||||
* Modifications:
|
||||
*/
|
||||
static long
|
||||
parse_size_directive(const char *size)
|
||||
{
|
||||
long s;
|
||||
char *endptr;
|
||||
|
||||
s = strtol(size, &endptr, 10);
|
||||
|
||||
if (endptr && *endptr) {
|
||||
while (*endptr != '\0' && (*endptr == ' ' || *endptr == '\t'))
|
||||
++endptr;
|
||||
|
||||
switch (*endptr) {
|
||||
case 'K':
|
||||
case 'k':
|
||||
s *= ONE_KB;
|
||||
break;
|
||||
case 'M':
|
||||
case 'm':
|
||||
s *= ONE_MB;
|
||||
break;
|
||||
case 'G':
|
||||
case 'g':
|
||||
s *= ONE_GB;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Illegal size specifier '%c'\n", *endptr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: usage
|
||||
* Purpose: Print a usage message and then exit.
|
||||
* Return: Nothing
|
||||
* Programmer: Bill Wendling, 31. October 2001
|
||||
* Modifications:
|
||||
*/
|
||||
static void
|
||||
usage(const char *prog)
|
||||
{
|
||||
fflush(stdout);
|
||||
fprintf(stdout, "usage: %s [OPTIONS]\n", prog);
|
||||
fprintf(stdout, " OPTIONS\n");
|
||||
fprintf(stdout, " -h, --help Print a usage message and exit\n");
|
||||
fprintf(stdout, " -d N, --num-dsets=N Number of datasets per file [default:1]\n");
|
||||
fprintf(stdout, " -f S, --file-size=S Size of a single file [default: 64M]\n");
|
||||
fprintf(stdout, " -F N, --num-files=N Number of files [default: 1]\n");
|
||||
fprintf(stdout, " -H, --hdf5 Run HDF5 performance test\n");
|
||||
fprintf(stdout, " -i, --num-iterations Number of iterations to perform [default: 1]\n");
|
||||
fprintf(stdout, " -m, --mpiio Run MPI/IO performance test\n");
|
||||
fprintf(stdout, " -o F, --output=F Output raw data into file F [default: none]\n");
|
||||
fprintf(stdout, " -P N, --max-num-processes=N Maximum number of processes to use [default: 1]\n");
|
||||
fprintf(stdout, " -p N, --min-num-processes=N Minimum number of processes to use [default: 1]\n");
|
||||
fprintf(stdout, " -r, --raw Run raw (UNIX) performance test\n");
|
||||
fprintf(stdout, " -X S, --max-xfer-size=S Maximum transfer buffer size [default: 1M]\n");
|
||||
fprintf(stdout, " -x S, --min-xfer-size=S Minimum transfer buffer size [default: 1K]\n");
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, " F - is a filename.\n");
|
||||
fprintf(stdout, " N - is an integer >=0.\n");
|
||||
fprintf(stdout, " S - is a size specifier, an integer >=0 followed by a size indicator:\n");
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, " K - Kilobyte\n");
|
||||
fprintf(stdout, " M - Megabyte\n");
|
||||
fprintf(stdout, " G - Gigabyte\n");
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, " Example: 37M = 37 Megabytes\n");
|
||||
fprintf(stdout, "\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
#else /* H5_HAVE_PARALLEL */
|
||||
|
||||
/*
|
||||
|
@ -17,12 +17,12 @@ typedef enum iotype_ {
|
||||
} iotype;
|
||||
|
||||
typedef struct parameters_ {
|
||||
int max_num_procs; /* Maximum number of processes to use */
|
||||
iotype io_type; /* The type of IO test to perform */
|
||||
int num_files; /* Number of files to create */
|
||||
long num_dsets; /* Number of datasets to create */
|
||||
long num_elmts; /* Number of native ints in each dset */
|
||||
int num_iters; /* Number of times to loop doing the IO */
|
||||
iotype io_type; /* The type of IO test to perform */
|
||||
int num_procs; /* Maximum number of processes to use */
|
||||
int num_files; /* Number of files to create */
|
||||
long num_dsets; /* Number of datasets to create */
|
||||
long num_elmts; /* Number of native ints in each dset */
|
||||
int num_iters; /* Number of times to loop doing the IO */
|
||||
long buf_size; /* Buffer size */
|
||||
} parameters;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user