[MOAB-dev] r3293 - MOAB/trunk/tools/mbperf

kraftche at cae.wisc.edu kraftche at cae.wisc.edu
Fri Nov 6 11:44:56 CST 2009


Author: kraftche
Date: 2009-11-06 11:44:56 -0600 (Fri, 06 Nov 2009)
New Revision: 3293

Modified:
   MOAB/trunk/tools/mbperf/mbperf.cpp
Log:
o Restructure mbperf so as to allow for easy addition of new tests
o Use meaningful test name rather than 'A|B|C' for mbperf command
o Allow running multiple tests with one call to mbperf
o Make interval count optional, with default of 50
o Add command line option to list available tests


Modified: MOAB/trunk/tools/mbperf/mbperf.cpp
===================================================================
--- MOAB/trunk/tools/mbperf/mbperf.cpp	2009-11-06 15:51:45 UTC (rev 3292)
+++ MOAB/trunk/tools/mbperf/mbperf.cpp	2009-11-06 17:44:56 UTC (rev 3293)
@@ -30,6 +30,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <iostream>
+#include <iomanip>
 #include <time.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -46,15 +47,17 @@
 #include "HomXform.hpp"
 
 double LENGTH = 1.0;
+const int DEFAULT_INTERVALS = 50;
 
-void testA(const int nelem, const double *coords);
-void testB(const int nelem, const double *coords, const MBEntityHandle *connect);
-void testC(const int nelem, const double *coords);
+
+void testA(const int nelem);
+void testB(const int nelem);
+void testC(const int nelem);
 void print_time(const bool print_em, double &tot_time, double &utime, double &stime,
                 double &mem);
-void query_vert_to_elem();
-void query_elem_to_vert();
-void query_struct_elem_to_vert();
+void query_vert_to_elem(MBInterface*);
+void query_elem_to_vert(MBInterface*);
+void query_struct_elem_to_vert(MBInterface*);
 void get_time_mem(double &tot_time, double &user_time,
                   double &sys_time, double &tot_mem);
 
@@ -105,7 +108,7 @@
   }
 }
 
-void build_coords(const int nelem, double *&coords) 
+void build_coords(const int nelem, std::vector<double>& coords) 
 {
   double ttime0, ttime1, utime1, stime1, mem1;
   print_time(false, ttime0, utime1, stime1, mem1);
@@ -115,7 +118,7 @@
   int numv = nelem+1;
   int numv_sq = numv*numv;
   int tot_numv = numv*numv*numv;
-  coords = new double[3*tot_numv];
+  coords.resize(3*tot_numv);
 
 // use FORTRAN-like indexing
 #define VINDEX(i,j,k) (i + (j*numv) + (k*numv_sq))
@@ -248,12 +251,8 @@
             << mem1/1.0e6 << " MB." << std::endl;
 }
 
-void build_connect(const int nelem, const MBEntityHandle vstart, MBEntityHandle *&connect) 
+void build_connect(const int nelem, const MBEntityHandle vstart, MBEntityHandle *connect) 
 {
-    // allocate the memory
-  int nume_tot = nelem*nelem*nelem;
-  connect = new MBEntityHandle[8*nume_tot];
-
   MBEntityHandle vijk;
   int numv = nelem + 1;
   int numv_sq = numv*numv;
@@ -276,59 +275,113 @@
   }
 }
 
-MBInterface *gMB;
+typedef void (*test_func_t)( int );
+const struct {
+  std::string testName;
+  std::string testDesc;
+  test_func_t testFunc;
+} TestList[] = {
+ { "struct", "Conn. and adj. query time for structured mesh", &testA },
+ { "bulk",   "Conn. and adj. query time for bulk-created mesh", &testB },
+ { "indiv",  "Conn. and adj. query time for per-entity created mesh", &testC },
+// { "skin",       "Test skin time", &skin_time },
+// { "skin_adj",   "Test skin time using vertex-to-element adjacencies", &skin_adj },
+ };
+
+const int TestListSize = sizeof(TestList)/sizeof(TestList[0]); 
+
+void usage( const char* argv0, bool error = true )
+{
+  std::ostream& str = error ? std::cerr : std::cout;
+  str << "Usage: " << argv0 << " -i <ints_per_side> <test_name> [<test_name2> ...]" << std::endl;
+  str << "       " << argv0 << " [-h|-l]" << std::endl;
+  if (error)
+    return;
+  str << "  -i  : specify interverals per side (num hex = ints^3, default: " << DEFAULT_INTERVALS << std::endl;
+  str << "  -h  : print this help text." << std::endl;
+  str << "  -l  : list available tests"  << std::endl;
+}
+
+void list_tests( ) 
+{
+  unsigned max_test_name = 0, max_test_desc = 0;
+  for (int i = 0; i < TestListSize; ++i) {
+    if (TestList[i].testName.size() > max_test_name)
+      max_test_name = TestList[i].testName.size();
+    if (TestList[i].testDesc.size() > max_test_desc)
+      max_test_desc = TestList[i].testDesc.size();
+  }
+  std::cout << std::setw(max_test_name) << "NAME" << "   " 
+            << std::setw(max_test_desc) << std::left << "DESCRIPTION" << std::endl
+            << std::setfill('-') << std::setw(max_test_name) << "" << "   " 
+            << std::setfill('-') << std::setw(max_test_desc) << "" 
+            << std::setfill(' ') << std::endl;
+  for (int i = 0; i < TestListSize; ++i) 
+    std::cout << std::setw(max_test_name) << TestList[i].testName << " : "
+              << std::setw(max_test_desc) << std::left << TestList[i].testDesc << std::endl;
+}  
+  
 int main(int argc, char* argv[])
 {
-  int nelem = 20;
-  if (argc < 3) {
-    std::cout << "Usage: " << argv[0] << " <ints_per_side> <A|B|C>" << std::endl;
-    return 1;
+  int intervals = DEFAULT_INTERVALS;
+  std::vector<test_func_t> test_list;
+  bool did_help = false;
+  bool expect_ints = false;
+  for (int i = 1; i < argc; ++i) {
+    if (expect_ints) {
+      expect_ints = false;
+      char* endptr;
+      intervals = strtol( argv[i], &endptr, 0 );
+      if (intervals < 1) {
+        usage(argv[0]);
+        std::cerr << "Invalid interval count: " << intervals << std::endl;
+        return 1;
+      }
+    }
+    else if (*argv[i] == '-') { // flag
+      for (int j = 1; argv[i][j]; ++j) {
+        switch (argv[i][j]) {
+          case 'i': expect_ints = true; break;
+          case 'h': did_help = true; usage(argv[0],false); break;
+          case 'l': did_help = true; list_tests(); break;
+          default:
+            usage(argv[0]);
+            std::cerr << "Invalid option: -" << argv[i][j] << std::endl;
+            return 1;
+        }
+      }
+    }
+    else {
+      int j = -1;
+      do {
+        ++j;
+        if (j >= TestListSize) {
+          usage(argv[0]);
+          std::cerr << "Invalid test name: " << argv[i] << std::endl;
+          return 1;
+        }
+      } while (TestList[j].testName == argv[i]);
+      test_list.push_back( TestList[j].testFunc );
+    }
   }
   
-  char which_test = '\0';
-  
-  sscanf(argv[1], "%d", &nelem);
-  sscanf(argv[2], "%c", &which_test);
-
-  if (which_test != 'A' && which_test != 'B' && which_test != 'C') {
-      std::cout << "Must indicate A or B or C for test." << std::endl;
-      return 1;
+    // error if no input
+  if (test_list.empty() && !did_help) {
+    usage(argv[0]);
+    std::cerr << "No tests specified" << std::endl;
+    return 1;
   }
   
-  std::cout << "number of elements: " << nelem << "; test " 
-            << which_test << std::endl;
-
-  gMB = new MBCore();
-
-    // pre-build the coords array
-  double *coords = NULL;
-  build_coords(nelem, coords);
-  assert(NULL != coords);
-
-  MBEntityHandle *connect = NULL;
-  build_connect(nelem, 1, connect);
-
-  switch (which_test) {
-    case 'A':
-        // test A: create structured mesh
-      testA(nelem, coords);
-      break;
-      
-    case 'B':
-        // test B: create mesh using bulk interface
-      testB(nelem, coords, connect);
-      break;
-      
-    case 'C':
-    // test C: create mesh using individual interface
-      testC(nelem, coords);
-      break;
+    // now run the tests
+  for (std::vector<test_func_t>::iterator i = test_list.begin(); i != test_list.end(); ++i) {
+    test_func_t fptr = *i;
+    fptr(intervals);
   }
   
   return 0;
 }
 
-void query_elem_to_vert()
+void query_elem_to_vert(MBInterface* gMB)
 {
   MBRange all_hexes;
   MBErrorCode result = gMB->get_entities_by_type(0, MBHEX, all_hexes);
@@ -351,7 +404,7 @@
   }
 }
 
-void query_vert_to_elem()
+void query_vert_to_elem(MBInterface* gMB)
 {
   MBRange all_verts;
   std::vector<MBEntityHandle> neighbor_hexes;
@@ -364,7 +417,7 @@
   }
 }
 
-void query_struct_elem_to_vert()
+void query_struct_elem_to_vert(MBInterface* gMB)
 {
     // assumes brick mapped mesh with handles starting at zero
   MBRange all_hexes;
@@ -454,8 +507,10 @@
 }
 #endif
 
-void testA(const int nelem, const double *coords) 
+void testA( int nelem ) 
 {
+  MBCore moab;
+  MBInterface* gMB = &moab;
   double ttime0, ttime1, ttime2, ttime3, utime, stime, mem;
   
   print_time(false, ttime0, utime, stime, mem);
@@ -466,7 +521,7 @@
   EntitySequence *dum_seq = NULL;
   ScdVertexData *vseq = NULL;
   StructuredElementSeq *eseq = NULL;
-  SequenceManager *seq_mgr = dynamic_cast<MBCore*>(gMB)->sequence_manager();
+  SequenceManager *seq_mgr = moab.sequence_manager();
   HomCoord vseq_minmax[2] = {HomCoord(0,0,0), 
                              HomCoord(nelem, nelem, nelem)};
   MBEntityHandle vstart, estart;
@@ -488,6 +543,9 @@
                                vseq_minmax[0], vseq_minmax[0], vseq_minmax[0]);
   assert(MB_SUCCESS == result);
 
+  std::vector<double> coords;
+  build_coords(nelem, coords);
+
     // set the coordinates of the vertices
   MBEntityHandle handle;
   int i;
@@ -503,12 +561,12 @@
   std::cout << "Read model into MOAB; memory  = " << mem/1.0e6 << " MB." << std::endl;
 
     // query the mesh 2 ways
-  query_struct_elem_to_vert();
+  query_struct_elem_to_vert(gMB);
 
   print_time(false, ttime2, utime, stime, mem);
   std::cout << "After E-v query; memory  = " << mem/1.0e6 << " MB." << std::endl;
 
-  query_vert_to_elem();
+  query_vert_to_elem(gMB);
   
   print_time(false, ttime3, utime, stime, mem);
   std::cout << "After v-E query; memory  = " << mem/1.0e6 << " MB." << std::endl;
@@ -521,8 +579,10 @@
             << std::endl;
 }
 
-void testB(const int nelem, const double *coords, const MBEntityHandle *connect) 
+void testB(const int nelem) 
 {
+  MBCore moab;
+  MBInterface* gMB = &moab;
   double ttime0, ttime1, ttime2, ttime3, utime, stime, mem;
   
   print_time(false, ttime0, utime, stime, mem);
@@ -544,14 +604,16 @@
   assert(MB_SUCCESS == result && 1 == vstart &&
          coord_arrays[0] && coord_arrays[1] && coord_arrays[2]);
     // memcpy the coordinate data into place
-  memcpy(coord_arrays[0], coords, sizeof(double)*num_verts);
+  std::vector<double> coords;
+  build_coords(nelem, coords);
+  memcpy(coord_arrays[0], &coords[0], sizeof(double)*num_verts);
   memcpy(coord_arrays[1], &coords[num_verts], sizeof(double)*num_verts);
   memcpy(coord_arrays[2], &coords[2*num_verts], sizeof(double)*num_verts);
   
   MBEntityHandle *conn = 0;
   result = readMeshIface->get_element_array(num_elems, 8, MBHEX, 1, estart, conn);
   assert(MB_SUCCESS == result);
-  memcpy(conn, connect, num_elems*8*sizeof(MBEntityHandle));
+  build_connect(nelem, vstart, conn);
   result = readMeshIface->update_adjacencies(estart, num_elems, 8, conn);
   assert(MB_SUCCESS == result);
 
@@ -559,12 +621,12 @@
   std::cout << "Read model into MOAB; memory = " << mem/1.0e6 << " MB." << std::endl;
 
     // query the mesh 2 ways
-  query_elem_to_vert();
+  query_elem_to_vert(gMB);
 
   print_time(false, ttime2, utime, stime, mem);
   std::cout << "After E-v query; memory = " << mem/1.0e6 << " MB." << std::endl;
 
-  query_vert_to_elem();
+  query_vert_to_elem(gMB);
   
   print_time(false, ttime3, utime, stime, mem);
   std::cout << "After v-E query; memory = " << mem/1.0e6 << " MB." << std::endl;
@@ -577,8 +639,10 @@
             << std::endl;
 }
 
-void testC(const int nelem, const double *coords) 
+void testC(const int nelem) 
 {
+  MBCore moab;
+  MBInterface* gMB = &moab;
   double ttime0, ttime1, ttime2, ttime3, utime, stime, mem;
   
   print_time(false, ttime0, utime, stime, mem);
@@ -586,6 +650,8 @@
 
     // create the vertices; assume we don't need to keep a list of vertex handles, since they'll
     // be created in sequence
+  std::vector<double> coords;
+  build_coords(nelem, coords);
   int numv = nelem + 1;
   int numv_sq = numv*numv;
   int num_verts = numv*numv*numv;
@@ -628,12 +694,12 @@
   std::cout << "Read data into MOAB; memory  = " << mem/1.0e6 << " MB." << std::endl;
 
     // query the mesh 2 ways
-  query_elem_to_vert();
+  query_elem_to_vert(gMB);
 
   print_time(false, ttime2, utime, stime, mem);
   std::cout << "After E-v query; memory  = " << mem/1.0e6 << " MB." << std::endl;
 
-  query_vert_to_elem();
+  query_vert_to_elem(gMB);
   
   print_time(false, ttime3, utime, stime, mem);
   std::cout << "After v-E query; memory  = " << mem/1.0e6 << " MB." << std::endl;



More information about the moab-dev mailing list