Changeset 3293

Show
Ignore:
Timestamp:
11/06/09 11:44:56 (2 weeks ago)
Author:
kraftche
Message:

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

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • MOAB/trunk/tools/mbperf/mbperf.cpp

    r3103 r3293  
    3131#include <stdio.h> 
    3232#include <iostream> 
     33#include <iomanip> 
    3334#include <time.h> 
    3435#include <unistd.h> 
     
    4748 
    4849double LENGTH = 1.0; 
    49  
    50 void testA(const int nelem, const double *coords); 
    51 void testB(const int nelem, const double *coords, const MBEntityHandle *connect); 
    52 void testC(const int nelem, const double *coords); 
     50const int DEFAULT_INTERVALS = 50; 
     51 
     52 
     53void testA(const int nelem); 
     54void testB(const int nelem); 
     55void testC(const int nelem); 
    5356void print_time(const bool print_em, double &tot_time, double &utime, double &stime, 
    5457                double &mem); 
    55 void query_vert_to_elem(); 
    56 void query_elem_to_vert(); 
    57 void query_struct_elem_to_vert(); 
     58void query_vert_to_elem(MBInterface*); 
     59void query_elem_to_vert(MBInterface*); 
     60void query_struct_elem_to_vert(MBInterface*); 
    5861void get_time_mem(double &tot_time, double &user_time, 
    5962                  double &sys_time, double &tot_mem); 
     
    106109} 
    107110 
    108 void build_coords(const int nelem, double *&coords)  
     111void build_coords(const int nelem, std::vector<double>& coords)  
    109112{ 
    110113  double ttime0, ttime1, utime1, stime1, mem1; 
     
    116119  int numv_sq = numv*numv; 
    117120  int tot_numv = numv*numv*numv; 
    118   coords = new double[3*tot_numv]; 
     121  coords.resize(3*tot_numv); 
    119122 
    120123// use FORTRAN-like indexing 
     
    249252} 
    250253 
    251 void build_connect(const int nelem, const MBEntityHandle vstart, MBEntityHandle *&connect)  
    252 { 
    253     // allocate the memory 
    254   int nume_tot = nelem*nelem*nelem; 
    255   connect = new MBEntityHandle[8*nume_tot]; 
    256  
     254void build_connect(const int nelem, const MBEntityHandle vstart, MBEntityHandle *connect)  
     255{ 
    257256  MBEntityHandle vijk; 
    258257  int numv = nelem + 1; 
     
    277276} 
    278277 
    279 MBInterface *gMB; 
     278typedef void (*test_func_t)( int ); 
     279const struct { 
     280  std::string testName; 
     281  std::string testDesc; 
     282  test_func_t testFunc; 
     283} TestList[] = { 
     284 { "struct", "Conn. and adj. query time for structured mesh", &testA }, 
     285 { "bulk",   "Conn. and adj. query time for bulk-created mesh", &testB }, 
     286 { "indiv",  "Conn. and adj. query time for per-entity created mesh", &testC }, 
     287// { "skin",       "Test skin time", &skin_time }, 
     288// { "skin_adj",   "Test skin time using vertex-to-element adjacencies", &skin_adj }, 
     289 }; 
     290 
     291const int TestListSize = sizeof(TestList)/sizeof(TestList[0]);  
     292 
     293void usage( const char* argv0, bool error = true ) 
     294{ 
     295  std::ostream& str = error ? std::cerr : std::cout; 
     296  str << "Usage: " << argv0 << " -i <ints_per_side> <test_name> [<test_name2> ...]" << std::endl; 
     297  str << "       " << argv0 << " [-h|-l]" << std::endl; 
     298  if (error) 
     299    return; 
     300  str << "  -i  : specify interverals per side (num hex = ints^3, default: " << DEFAULT_INTERVALS << std::endl; 
     301  str << "  -h  : print this help text." << std::endl; 
     302  str << "  -l  : list available tests"  << std::endl; 
     303} 
     304 
     305void list_tests( )  
     306{ 
     307  unsigned max_test_name = 0, max_test_desc = 0; 
     308  for (int i = 0; i < TestListSize; ++i) { 
     309    if (TestList[i].testName.size() > max_test_name) 
     310      max_test_name = TestList[i].testName.size(); 
     311    if (TestList[i].testDesc.size() > max_test_desc) 
     312      max_test_desc = TestList[i].testDesc.size(); 
     313  } 
     314  std::cout << std::setw(max_test_name) << "NAME" << "   "  
     315            << std::setw(max_test_desc) << std::left << "DESCRIPTION" << std::endl 
     316            << std::setfill('-') << std::setw(max_test_name) << "" << "   "  
     317            << std::setfill('-') << std::setw(max_test_desc) << ""  
     318            << std::setfill(' ') << std::endl; 
     319  for (int i = 0; i < TestListSize; ++i)  
     320    std::cout << std::setw(max_test_name) << TestList[i].testName << " : " 
     321              << std::setw(max_test_desc) << std::left << TestList[i].testDesc << std::endl; 
     322 
     323   
    280324int main(int argc, char* argv[]) 
    281325{ 
    282   int nelem = 20; 
    283   if (argc < 3) { 
    284     std::cout << "Usage: " << argv[0] << " <ints_per_side> <A|B|C>" << std::endl; 
     326  int intervals = DEFAULT_INTERVALS; 
     327  std::vector<test_func_t> test_list; 
     328  bool did_help = false; 
     329  bool expect_ints = false; 
     330  for (int i = 1; i < argc; ++i) { 
     331    if (expect_ints) { 
     332      expect_ints = false; 
     333      char* endptr; 
     334      intervals = strtol( argv[i], &endptr, 0 ); 
     335      if (intervals < 1) { 
     336        usage(argv[0]); 
     337        std::cerr << "Invalid interval count: " << intervals << std::endl; 
     338        return 1; 
     339      } 
     340    } 
     341    else if (*argv[i] == '-') { // flag 
     342      for (int j = 1; argv[i][j]; ++j) { 
     343        switch (argv[i][j]) { 
     344          case 'i': expect_ints = true; break; 
     345          case 'h': did_help = true; usage(argv[0],false); break; 
     346          case 'l': did_help = true; list_tests(); break; 
     347          default: 
     348            usage(argv[0]); 
     349            std::cerr << "Invalid option: -" << argv[i][j] << std::endl; 
     350            return 1; 
     351        } 
     352      } 
     353    } 
     354    else { 
     355      int j = -1; 
     356      do { 
     357        ++j; 
     358        if (j >= TestListSize) { 
     359          usage(argv[0]); 
     360          std::cerr << "Invalid test name: " << argv[i] << std::endl; 
     361          return 1; 
     362        } 
     363      } while (TestList[j].testName == argv[i]); 
     364      test_list.push_back( TestList[j].testFunc ); 
     365    } 
     366  } 
     367   
     368    // error if no input 
     369  if (test_list.empty() && !did_help) { 
     370    usage(argv[0]); 
     371    std::cerr << "No tests specified" << std::endl; 
    285372    return 1; 
    286373  } 
    287374   
    288   char which_test = '\0'; 
    289    
    290   sscanf(argv[1], "%d", &nelem); 
    291   sscanf(argv[2], "%c", &which_test); 
    292  
    293   if (which_test != 'A' && which_test != 'B' && which_test != 'C') { 
    294       std::cout << "Must indicate A or B or C for test." << std::endl; 
    295       return 1; 
    296   } 
    297    
    298   std::cout << "number of elements: " << nelem << "; test "  
    299             << which_test << std::endl; 
    300  
    301   gMB = new MBCore(); 
    302  
    303     // pre-build the coords array 
    304   double *coords = NULL; 
    305   build_coords(nelem, coords); 
    306   assert(NULL != coords); 
    307  
    308   MBEntityHandle *connect = NULL; 
    309   build_connect(nelem, 1, connect); 
    310  
    311   switch (which_test) { 
    312     case 'A': 
    313         // test A: create structured mesh 
    314       testA(nelem, coords); 
    315       break; 
    316        
    317     case 'B': 
    318         // test B: create mesh using bulk interface 
    319       testB(nelem, coords, connect); 
    320       break; 
    321        
    322     case 'C': 
    323     // test C: create mesh using individual interface 
    324       testC(nelem, coords); 
    325       break; 
     375    // now run the tests 
     376  for (std::vector<test_func_t>::iterator i = test_list.begin(); i != test_list.end(); ++i) { 
     377    test_func_t fptr = *i; 
     378    fptr(intervals); 
    326379  } 
    327380   
     
    329382} 
    330383 
    331 void query_elem_to_vert() 
     384void query_elem_to_vert(MBInterface* gMB) 
    332385{ 
    333386  MBRange all_hexes; 
     
    352405} 
    353406 
    354 void query_vert_to_elem() 
     407void query_vert_to_elem(MBInterface* gMB) 
    355408{ 
    356409  MBRange all_verts; 
     
    365418} 
    366419 
    367 void query_struct_elem_to_vert() 
     420void query_struct_elem_to_vert(MBInterface* gMB) 
    368421{ 
    369422    // assumes brick mapped mesh with handles starting at zero 
     
    455508#endif 
    456509 
    457 void testA(const int nelem, const double *coords)  
    458 { 
     510void testA( int nelem )  
     511{ 
     512  MBCore moab; 
     513  MBInterface* gMB = &moab; 
    459514  double ttime0, ttime1, ttime2, ttime3, utime, stime, mem; 
    460515   
     
    467522  ScdVertexData *vseq = NULL; 
    468523  StructuredElementSeq *eseq = NULL; 
    469   SequenceManager *seq_mgr = dynamic_cast<MBCore*>(gMB)->sequence_manager(); 
     524  SequenceManager *seq_mgr = moab.sequence_manager(); 
    470525  HomCoord vseq_minmax[2] = {HomCoord(0,0,0),  
    471526                             HomCoord(nelem, nelem, nelem)}; 
     
    489544  assert(MB_SUCCESS == result); 
    490545 
     546  std::vector<double> coords; 
     547  build_coords(nelem, coords); 
     548 
    491549    // set the coordinates of the vertices 
    492550  MBEntityHandle handle; 
     
    504562 
    505563    // query the mesh 2 ways 
    506   query_struct_elem_to_vert(); 
     564  query_struct_elem_to_vert(gMB); 
    507565 
    508566  print_time(false, ttime2, utime, stime, mem); 
    509567  std::cout << "After E-v query; memory  = " << mem/1.0e6 << " MB." << std::endl; 
    510568 
    511   query_vert_to_elem(); 
     569  query_vert_to_elem(gMB); 
    512570   
    513571  print_time(false, ttime3, utime, stime, mem); 
     
    522580} 
    523581 
    524 void testB(const int nelem, const double *coords, const MBEntityHandle *connect)  
    525 { 
     582void testB(const int nelem)  
     583{ 
     584  MBCore moab; 
     585  MBInterface* gMB = &moab; 
    526586  double ttime0, ttime1, ttime2, ttime3, utime, stime, mem; 
    527587   
     
    545605         coord_arrays[0] && coord_arrays[1] && coord_arrays[2]); 
    546606    // memcpy the coordinate data into place 
    547   memcpy(coord_arrays[0], coords, sizeof(double)*num_verts); 
     607  std::vector<double> coords; 
     608  build_coords(nelem, coords); 
     609  memcpy(coord_arrays[0], &coords[0], sizeof(double)*num_verts); 
    548610  memcpy(coord_arrays[1], &coords[num_verts], sizeof(double)*num_verts); 
    549611  memcpy(coord_arrays[2], &coords[2*num_verts], sizeof(double)*num_verts); 
     
    552614  result = readMeshIface->get_element_array(num_elems, 8, MBHEX, 1, estart, conn); 
    553615  assert(MB_SUCCESS == result); 
    554   memcpy(conn, connect, num_elems*8*sizeof(MBEntityHandle)); 
     616  build_connect(nelem, vstart, conn); 
    555617  result = readMeshIface->update_adjacencies(estart, num_elems, 8, conn); 
    556618  assert(MB_SUCCESS == result); 
     
    560622 
    561623    // query the mesh 2 ways 
    562   query_elem_to_vert(); 
     624  query_elem_to_vert(gMB); 
    563625 
    564626  print_time(false, ttime2, utime, stime, mem); 
    565627  std::cout << "After E-v query; memory = " << mem/1.0e6 << " MB." << std::endl; 
    566628 
    567   query_vert_to_elem(); 
     629  query_vert_to_elem(gMB); 
    568630   
    569631  print_time(false, ttime3, utime, stime, mem); 
     
    578640} 
    579641 
    580 void testC(const int nelem, const double *coords)  
    581 { 
     642void testC(const int nelem)  
     643{ 
     644  MBCore moab; 
     645  MBInterface* gMB = &moab; 
    582646  double ttime0, ttime1, ttime2, ttime3, utime, stime, mem; 
    583647   
     
    587651    // create the vertices; assume we don't need to keep a list of vertex handles, since they'll 
    588652    // be created in sequence 
     653  std::vector<double> coords; 
     654  build_coords(nelem, coords); 
    589655  int numv = nelem + 1; 
    590656  int numv_sq = numv*numv; 
     
    629695 
    630696    // query the mesh 2 ways 
    631   query_elem_to_vert(); 
     697  query_elem_to_vert(gMB); 
    632698 
    633699  print_time(false, ttime2, utime, stime, mem); 
    634700  std::cout << "After E-v query; memory  = " << mem/1.0e6 << " MB." << std::endl; 
    635701 
    636   query_vert_to_elem(); 
     702  query_vert_to_elem(gMB); 
    637703   
    638704  print_time(false, ttime3, utime, stime, mem);