summaryrefslogtreecommitdiffstats
path: root/perform/pio_perf.c
diff options
context:
space:
mode:
authorBill Wendling <wendling@ncsa.uiuc.edu>2001-12-18 20:12:21 (GMT)
committerBill Wendling <wendling@ncsa.uiuc.edu>2001-12-18 20:12:21 (GMT)
commitd1d532069bd98ad37afb130fc9fba76be92d098b (patch)
treee14f5ea53679b8e36c6c0a992fbfe819c6cc0772 /perform/pio_perf.c
parent2b629eaceb37a14a9e33dafa6a2a50765fd7d629 (diff)
downloadhdf5-d1d532069bd98ad37afb130fc9fba76be92d098b.zip
hdf5-d1d532069bd98ad37afb130fc9fba76be92d098b.tar.gz
hdf5-d1d532069bd98ad37afb130fc9fba76be92d098b.tar.bz2
[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...
Diffstat (limited to 'perform/pio_perf.c')
-rw-r--r--perform/pio_perf.c383
1 files changed, 306 insertions, 77 deletions
diff --git a/perform/pio_perf.c b/perform/pio_perf.c
index a195d25..a4602f8 100644
--- a/perform/pio_perf.c
+++ b/perform/pio_perf.c
@@ -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,96 +277,116 @@ 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 */
+
+ 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;
+ }
- /* num_files stays ``1'' for now but may change later */
- parms.num_files = 1;
- parms.num_iters = 1;
+ 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 = ");
-
- if (i == RAW)
- fprintf(output, "Raw\n");
- else if (i == MPIO)
- fprintf(output, "MPIO\n");
- else
- fprintf(output, "PHDF5\n");
-
- for (j = MIN_HDF5_BUF_SIZE; j <= MAX_HDF5_BUF_SIZE; j <<= 1) {
- results res;
-
- 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);
- }
+ fprintf(output,
+ "# of files: %u, # of dsets: %lu, Elements per dset: %lu\n",
+ parms.num_files, parms.num_dsets, parms.num_elmts);
+
+ if (io_runs | PIO_RAW)
+ run_test(output, RAW, parms);
+
+ if (io_runs | PIO_MPI)
+ run_test(output, MPIO, parms);
+
+ if (io_runs | PIO_HDF5)
+ run_test(output, PHDF5, parms);
}
}
}
/*
- * Function: print_indent
- * Purpose: Print spaces to indent a new line of text for pretty printing
- * things.
+ * Function: run_test
+ * Purpose: Inner loop call to actually run the I/O test.
* Return: Nothing
- * Programmer: Bill Wendling, 29. October 2001
+ * Programmer: Bill Wendling, 18. December 2001
* Modifications:
*/
static void
-print_indent(register FILE *output, register int indent)
+run_test(FILE *output, iotype iot, parameters parms)
{
- for (; indent > 0; --indent)
- fputc(' ', output);
+ 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: usage
- * Purpose: Print a usage message and then exit.
+ * Function: print_indent
+ * Purpose: Print spaces to indent a new line of text for pretty printing
+ * things.
* Return: Nothing
- * Programmer: Bill Wendling, 31. October 2001
+ * Programmer: Bill Wendling, 29. October 2001
* Modifications:
*/
static void
-usage(const char *prog)
+print_indent(register FILE *output, register int indent)
{
- 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");
+ for (; indent > 0; --indent)
+ fputc(' ', output);
}
/*
@@ -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 */
/*