[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:
Bill Wendling 2001-12-18 15:12:21 -05:00
parent 2b629eaceb
commit d1d532069b
3 changed files with 527 additions and 275 deletions

View File

@ -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 */

View File

@ -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 */
/*

View File

@ -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;