home *** CD-ROM | disk | FTP | other *** search
/ ftp.parl.clemson.edu / 2015-02-07.ftp.parl.clemson.edu.tar / ftp.parl.clemson.edu / pub / pvfs2 / tests / op_test.c < prev   
C/C++ Source or Header  |  2004-06-21  |  5KB  |  210 lines

  1. /*
  2.  * Joe insley reported slow open behavior.  Let's find out what is going on
  3.  * when an application opens a bunch of files 
  4.  *
  5.  * This can be further extented to test open behavior across several file
  6.  * systems ( pvfs, pvfs2, nfs, testfs )
  7.  *
  8.  * The timing and command-line parsing were so useful that this was further
  9.  * extended to test resize operations
  10.  *
  11.  * usage:  -d /path/to/directory -n number_of_files [-O] [-R]
  12.  */
  13.  
  14. #include <sys/types.h>
  15. #include <unistd.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <limits.h>
  20.  
  21. #include <mpi.h>
  22.  
  23. #ifndef PATH_MAX
  24. #define PATH_MAX FILENAME_MAX
  25. #endif
  26.  
  27. extern char *optarg;
  28. int opt_nfiles;
  29. char opt_basedir[PATH_MAX];
  30. int opt_do_open=0;
  31. int opt_do_resize=0;
  32.  
  33. void usage(char *name);
  34. int parse_args(int argc, char **argv);
  35. void handle_error(int errcode, char *str);
  36. int test_opens(int nfiles, char * test_dir, MPI_Info info);
  37. int test_resize(int rank, unsigned int seed, int iterations, 
  38.         char * test_dir, MPI_Info info);
  39.  
  40. void usage(char *name)
  41. {
  42.     fprintf(stderr, "usage: %s -d /path/to/directory -n #_of_files [TEST}\n", name);
  43.     fprintf(stderr, "   where TEST is one of:\n"
  44.             "     -O       test file open times\n"
  45.             "     -R       test file resize times\n");
  46.  
  47.         exit(-1);
  48. }
  49. int parse_args(int argc, char **argv)
  50. {
  51.     int c;
  52.     while ( (c = getopt(argc, argv, "d:n:OR")) != -1 ) {
  53.         switch (c) {
  54.             case 'd':
  55.                 strncpy(opt_basedir, optarg, PATH_MAX);
  56.                 break;
  57.             case 'n':
  58.                 opt_nfiles = atoi(optarg);
  59.                 break;
  60.             case 'O':
  61.                 opt_do_open = 1;
  62.                 break;
  63.             case 'R':
  64.                 opt_do_resize = 1;
  65.                 break;
  66.             case '?':
  67.             case ':':
  68.             default:
  69.                 usage(argv[0]);
  70.         }
  71.     }
  72.     if ( (opt_do_open == 0) && (opt_do_resize == 0) ) {
  73.         usage(argv[0]);
  74.     }
  75.     return 0;
  76. }
  77.  
  78. void handle_error(int errcode, char *str)
  79. {
  80.         char msg[MPI_MAX_ERROR_STRING];
  81.         int resultlen;
  82.         MPI_Error_string(errcode, msg, &resultlen);
  83.         fprintf(stderr, "%s: %s\n", str, msg);
  84.         MPI_Abort(MPI_COMM_WORLD, 1);
  85. }
  86.  
  87.  
  88. int main(int argc, char **argv)
  89. {
  90.     int rank, nprocs;
  91.     MPI_Info info;
  92.     double test_start, test_end;
  93.     double test_time, total_time;
  94.     pid_t    seed;     /* for tests that need some pseudorandomness */
  95.  
  96.     MPI_Init(&argc, &argv);
  97.     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  98.     MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
  99.  
  100.  
  101.     parse_args(argc, argv);
  102.  
  103.     /* provide hints if you want  */
  104.     info = MPI_INFO_NULL;
  105.  
  106.     /* we want some semblance of randomness, yet want all processors to
  107.      * have the same values.  everyone's got to seed w/ the same value */
  108.     if (rank == 0) 
  109.         seed = getpid();
  110.  
  111.     MPI_Bcast(&seed, sizeof(pid_t), MPI_BYTE, 0, MPI_COMM_WORLD);
  112.  
  113.     test_start = MPI_Wtime();
  114.     if (opt_do_open)
  115.         test_opens(opt_nfiles, opt_basedir, info);
  116.     else if (opt_do_resize)
  117.         test_resize(rank, seed, opt_nfiles, opt_basedir, info);
  118.  
  119.     test_end = MPI_Wtime();
  120.     test_time = test_end - test_start;
  121.     MPI_Allreduce(&test_time, &total_time, 1, 
  122.             MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
  123.     MPI_Finalize();
  124.  
  125.     if (rank == 0) {
  126.         if (opt_do_open) {
  127.             printf("%f seconds to open %d files: %f secs/open\n", 
  128.                     total_time, opt_nfiles, 
  129.                     (total_time)/opt_nfiles);
  130.         } else if (opt_do_resize) {
  131.             printf("%f seconds to perform %d resize ops: %f secs/opeeration\n", 
  132.                     total_time, opt_nfiles, 
  133.                     (total_time)/opt_nfiles);
  134.         }
  135.             
  136.     }
  137.     return 0;
  138. }
  139.  
  140. /* in directory 'test_dir', open and immediately close 'nfiles' files */
  141. /* a possible variant: open all the files first, then close */
  142. /* also test MPI_File_open behavior when there are a ton of files */
  143. int test_opens(int nfiles, char * test_dir, MPI_Info info)
  144. {
  145.     int i;
  146.     char test_file[PATH_MAX];
  147.     MPI_File fh;
  148.     int errcode;
  149.  
  150.     for (i=0; i<nfiles; i++) {
  151.         snprintf(test_file, PATH_MAX, "%s/testfile.%d", test_dir, i);
  152.         errcode = MPI_File_open(MPI_COMM_WORLD, test_file, 
  153.                 MPI_MODE_CREATE|MPI_MODE_RDWR, info, &fh);
  154.         if (errcode != MPI_SUCCESS) {
  155.             handle_error(errcode, "MPI_File_open");
  156.         }
  157.         errcode = MPI_File_close(&fh);
  158.         if (errcode != MPI_SUCCESS) {
  159.             handle_error(errcode, "MPI_File_close");
  160.         }
  161.  
  162.     }
  163.     /* since handle_error aborts, if we got here we are a-ok */
  164.     return 0;
  165. }
  166.  
  167. /* stuff these into separate object files. have a structure that provides a
  168.  * test() and result() function and a .time member */
  169.  
  170. /* inside directory 'test_dir', create a file and resize it to 'iterations'
  171.  * different sizes */
  172.  
  173. /* pass in a seed for the pseudorandom number generator: not fair to add the
  174.  * cost of MPI_Bcast to the resize operation */
  175.  
  176. int test_resize(int rank, unsigned int seed, int iterations, 
  177.         char * test_dir, MPI_Info info)
  178. {
  179.     int i;
  180.     char test_file[PATH_MAX];
  181.     MPI_File fh;
  182.     int errcode;
  183.     MPI_Offset size;
  184.  
  185.     snprintf(test_file, PATH_MAX, "%s/testfile", test_dir);
  186.     errcode = MPI_File_open(MPI_COMM_WORLD, test_file, 
  187.             MPI_MODE_CREATE|MPI_MODE_RDWR, info, &fh);
  188.     if (errcode != MPI_SUCCESS) {
  189.         handle_error(errcode, "MPI_File_open");
  190.     }
  191.     srand(seed);
  192.     /*
  193.     MPI_Barrier(MPI_COMM_WORLD);
  194.     */
  195.  
  196.     for(i=0; i<iterations; i++) {
  197.         size = rand();
  198.         errcode = MPI_File_set_size(fh, size);
  199.         if (errcode != MPI_SUCCESS) {
  200.             handle_error(errcode, "MPI_File_set_size");
  201.         }
  202.     }
  203.  
  204.     errcode = MPI_File_close(&fh);
  205.     if (errcode != MPI_SUCCESS) {
  206.         handle_error(errcode, "MPI_File_close");
  207.     }
  208.     return 0;
  209. }
  210.