summaryrefslogtreecommitdiffstats
path: root/perform/pio_perf.c
diff options
context:
space:
mode:
authorAlbert Cheng <acheng@hdfgroup.org>2001-11-07 15:28:33 (GMT)
committerAlbert Cheng <acheng@hdfgroup.org>2001-11-07 15:28:33 (GMT)
commitbb76b558e6d5c3e1c35a5f08da480435db039e19 (patch)
tree9eac65359e20b54a5d367ee7a501e901edf826a8 /perform/pio_perf.c
parent965e3bc3e20cefeb81b0b88002c1dc42d197c2ff (diff)
downloadhdf5-bb76b558e6d5c3e1c35a5f08da480435db039e19.zip
hdf5-bb76b558e6d5c3e1c35a5f08da480435db039e19.tar.gz
hdf5-bb76b558e6d5c3e1c35a5f08da480435db039e19.tar.bz2
[svn-r4592] Purpose:
New addition Description: Initial version of the Parallel I/O performance measurement program. Not fully implemented yet but checking them in before I may destroy them by accident. Don't run this in small file system (like AFS or eirene) since it generates gigabytes test files. Platforms tested: modi4 64bits. It compiled and ran but took a long time because the current test parametes are too "wild".
Diffstat (limited to 'perform/pio_perf.c')
-rw-r--r--perform/pio_perf.c324
1 files changed, 324 insertions, 0 deletions
diff --git a/perform/pio_perf.c b/perform/pio_perf.c
new file mode 100644
index 0000000..8971428
--- /dev/null
+++ b/perform/pio_perf.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2001
+ * National Center for Supercomputing Applications
+ * All rights reserved.
+ *
+ */
+
+/*
+ * Parallel HDF5 Performance Testing Code
+ * --------------------------------------
+ *
+ * Portable code to test performance on the different platforms we support.
+ * This is what the report should look like:
+ *
+ * nprocs = Max#Procs
+ * IO Type = Raw
+ * # Files = 1, # of dsets = 1000, Elements per dset = 37000
+ * Write Results = x MB/s
+ * Read Results = x MB/s
+ * # Files = 1, # of dsets = 3000, Elements per dset = 37000
+ * Write Results = x MB/s
+ * Read Results = x MB/s
+ *
+ * . . .
+ *
+ * IO Type = MPIO
+ * # Files = 1, # of dsets = 1000, Elements per dset = 37000
+ * Write Results = x MB/s
+ * Read Results = x MB/s
+ * # Files = 1, # of dsets = 3000, Elements per dset = 37000
+ * Write Results = x MB/s
+ * Read Results = x MB/s
+ *
+ * . . .
+ *
+ * IO Type = PHDF5
+ * # Files = 1, # of dsets = 1000, Elements per dset = 37000
+ * Write Results = x MB/s
+ * Read Results = x MB/s
+ * # Files = 1, # of dsets = 3000, Elements per dset = 37000
+ * Write Results = x MB/s
+ * Read Results = x MB/s
+ *
+ * . . .
+ *
+ * nprocs = Max#Procs / 2
+ *
+ * . . .
+ *
+ */
+
+/* system header files */
+#include <stdio.h>
+#include <stdlib.h>
+
+/* library header files */
+#include <mpi.h>
+
+/* our header files */
+#include "h5tools_utils.h"
+#include "pio_perf.h"
+
+/* useful macros */
+#define TAB_SPACE 4
+
+#define ONE_GB 1073741824UL
+
+#if 0
+#define MIN_HDF5_BUF_SIZE 1024
+#define MAX_HDF5_BUF_SIZE (ONE_GB / 2)
+#else
+#define MIN_HDF5_BUF_SIZE 1024*1024*8
+#define MAX_HDF5_BUF_SIZE MIN_HDF5_BUF_SIZE*4
+#endif
+
+/* local variables */
+static const char *progname = "pio_perf";
+
+/*
+ * Command-line options: The user can specify short or long-named
+ * parameters. The long-named ones can be partially spelled. When
+ * adding more, make sure that they don't clash with each other.
+ */
+#if 1
+static const char *s_opts = "ho:";
+#else
+static const char *s_opts = "hbo:";
+#endif /* 1 */
+static struct long_options l_opts[] = {
+ { "help", no_arg, 'h' },
+ { "hel", no_arg, 'h' },
+ { "he", no_arg, 'h' },
+#if 0
+ /* a siting of the elusive binary option */
+ { "binary", no_arg, 'b' },
+ { "binar", no_arg, 'b' },
+ { "bina", no_arg, 'b' },
+ { "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' },
+ { "output", require_arg, 'o' },
+ { "outpu", require_arg, 'o' },
+ { "outp", require_arg, 'o' },
+ { "out", require_arg, 'o' },
+ { "ou", require_arg, 'o' },
+ { NULL, 0, '\0' }
+};
+
+struct options {
+ const char *output_file; /* file to print report to */
+ long max_size; /* maximum size of file in gigabytes */
+};
+
+/* local functions */
+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 print_indent(register FILE *output, register int indent);
+static void usage(const char *prog);
+
+/*
+ * Function: main
+ * Purpose: Start things up. Initialize MPI and then call the test looping
+ * function.
+ * Return: EXIT_SUCCESS or EXIT_FAILURE
+ * Programmer: Bill Wendling, 30. October 2001
+ * Modifications:
+ */
+int
+main(int argc, char **argv)
+{
+ int world_size, ret;
+ int exit_value = EXIT_SUCCESS;
+ FILE *output = stdout;
+ struct options *opts;
+
+ opts = parse_command_line(argc, argv);
+
+ if (opts->output_file) {
+ if ((output = fopen(opts->output_file, "w")) == NULL) {
+ fprintf(stderr, "%s: cannot open output file\n", progname);
+ perror(opts->output_file);
+ goto onions;
+ }
+ }
+
+ /* initialize MPI and get the maximum num of processors we started with */
+ MPI_Init(&argc, &argv);
+ ret = MPI_Comm_size(MPI_COMM_WORLD, &world_size);
+
+ if (ret != MPI_SUCCESS) {
+ fprintf(stderr, "%s: MPI_Comm_size call failed\n", progname);
+
+ if (ret == MPI_ERR_COMM)
+ fprintf(stderr, "invalid MPI communicator\n");
+ else
+ fprintf(stderr, "invalid argument\n");
+
+ exit_value = EXIT_FAILURE;
+ goto cheese_and;
+ }
+
+ run_test_loop(output, world_size, opts->max_size);
+
+cheese_and:
+ MPI_Finalize();
+
+onions:
+ free(opts);
+ return exit_value;
+}
+
+/*
+ * Function: run_test_loop
+ * Purpose: Run the I/O tests. Write the results to OUTPUT.
+ *
+ * - The slowest changing part of the test is the number of
+ * processors to use. For each loop iteration, we divide that
+ * number by 2 and rerun the test.
+ *
+ * - The second slowest is what type of IO to perform. We have
+ * three choices: RAW, MPI-IO, and PHDF5.
+ *
+ * - Then we change the size of the buffer. This information is
+ * inferred from the number of datasets to create and the number
+ * of integers to put into each dataset. The backend code figures
+ * this out.
+ *
+ * Return: Nothing
+ * Programmer: Bill Wendling, 30. October 2001
+ * Modifications:
+ */
+static void
+run_test_loop(FILE *output, int max_num_procs, long max_size)
+{
+ parameters parms;
+
+ /* num_files stays ``1'' for now but may change later */
+ parms.num_files = 1;
+ parms.num_iters = 1;
+
+ /* divide the maximum number of processors by 2 for each loop iter */
+ for (; max_num_procs > 0; max_num_procs /= 2) {
+ register iotype i;
+
+ parms.max_num_procs = max_num_procs;
+ fprintf(output, "Number of processors = %u\n", parms.max_num_procs);
+
+ for (i = RAW; i <= PHDF5; ++i) {
+ register unsigned long j;
+
+ 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) {
+ parms.num_dsets = ONE_GB / j;
+ parms.num_elmts = (max_size * j) / 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 */
+ dopio(parms);
+ /* get back ``result'' object and report */
+ }
+ }
+ }
+}
+
+/*
+ * Function: print_indent
+ * Purpose: Print spaces to indent a new line of text for pretty printing
+ * things.
+ * Return: Nothing
+ * Programmer: Bill Wendling, 29. October 2001
+ * Modifications:
+ */
+static void
+print_indent(register FILE *output, register int indent)
+{
+ for (; indent > 0; --indent)
+ fputc(' ', output);
+
+ fputc('\n', 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 gigabytes [default: 2]\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
+ * structure which will need to be freed by the calling function.
+ * Return: Nothing
+ * Programmer: Bill Wendling, 31. October 2001
+ * Modifications:
+ */
+static struct options *
+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 = 2;
+
+ while ((opt = get_option(argc, (const char **)argv, s_opts, l_opts)) != EOF) {
+ switch ((char)opt) {
+#if 0
+ case 'b':
+ /* the future "binary" option */
+ break;
+#endif /* 0 */
+ case 'm':
+ cl_opts->max_size = atol(opt_arg);
+ break;
+ case 'o':
+ cl_opts->output_file = opt_arg;
+ break;
+ case 'h':
+ usage(progname);
+ exit(EXIT_SUCCESS);
+ case '?':
+ default:
+ usage(progname);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ return cl_opts;
+}