FEI Version of the Day
test_benchmarks.cpp
00001 /*
00002 // @HEADER
00003 // ************************************************************************
00004 //             FEI: Finite Element Interface to Linear Solvers
00005 //                  Copyright (2005) Sandia Corporation.
00006 //
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the
00008 // U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Alan Williams (william@sandia.gov) 
00038 //
00039 // ************************************************************************
00040 // @HEADER
00041 */
00042 
00043 #include <fei_macros.hpp>
00044 #include <fei_utils.hpp>
00045 #include <test_utils/fei_test_utils.hpp>
00046 #include <test_utils/test_benchmarks.hpp>
00047 #include <snl_fei_Utils.hpp>
00048 #include <fei_ctg_set.hpp>
00049 #include <snl_fei_RaggedTable.hpp>
00050 #include <snl_fei_RaggedTable_specialize.hpp>
00051 #include <test_utils/HexBeam.hpp>
00052 
00053 #undef fei_file
00054 #define fei_file "test_benchmarks.cpp"
00055 
00056 #include <fei_ErrMacros.hpp>
00057 
00058 test_benchmarks::test_benchmarks(MPI_Comm comm)
00059   : tester(comm)
00060 {
00061 }
00062 
00063 test_benchmarks::~test_benchmarks()
00064 {
00065 }
00066 
00067 template<typename MAP_TYPE, typename SET_TYPE>
00068 double time_raggedtable_insert(int len)
00069 {
00070   double start_time = fei::utils::cpu_time();
00071 
00072   HexBeam hexcube(10, len, 1, HexBeam::OneD, 1, 0);
00073 
00074   snl_fei::RaggedTable<MAP_TYPE,SET_TYPE> table(0, hexcube.numLocalNodes());
00075 
00076   int numIndices = hexcube.numNodesPerElem();
00077 
00078   int* indices = new int[numIndices];
00079 
00080   int first = hexcube.firstLocalElem();
00081 
00082   for(int n=0; n<hexcube.numLocalElems(); ++n) {
00083     int elem = first+n;
00084 
00085     hexcube.getElemConnectivity(elem, indices);
00086 
00087     table.addIndices(numIndices, indices, numIndices, indices);
00088   }
00089 
00090   delete [] indices;
00091 
00092   double elapsed_time = fei::utils::cpu_time() - start_time;
00093   return(elapsed_time);
00094 }
00095 
00096 template<typename MAP_TYPE, typename SET_TYPE>
00097 double benchmark_raggedtable()
00098 {
00099   int len = 80;
00100 
00101   //first find a len such that time_taken is at least 1 second
00102   double time_taken = time_raggedtable_insert<MAP_TYPE,SET_TYPE>(len);
00103   while(time_taken < 1.0) {
00104     len *= 2;
00105     time_taken = time_raggedtable_insert<MAP_TYPE,SET_TYPE>(len);
00106   }
00107 
00108   //now repeat until time_taken passes 5 seconds
00109   time_taken = 0.0;
00110   int i=0;
00111   while(time_taken<5.0) {
00112     time_taken += time_raggedtable_insert<MAP_TYPE,SET_TYPE>(len);
00113     ++i;
00114   }
00115 
00116   return((double)(i*len)/time_taken);
00117 }
00118 
00119 void print_benchmark_banner()
00120 {
00121 
00122   FEI_COUT.width(38);
00123   FEI_COUT << " Benchmark name         ";
00124   FEI_COUT.width(10);
00125   FEI_COUT << "Value  ";
00126   FEI_COUT.width(12);
00127   FEI_COUT << "gold-copy";
00128   FEI_COUT.width(10);
00129   FEI_COUT <<" Result "<<FEI_ENDL;
00130 
00131   FEI_COUT.width(38);
00132   FEI_COUT << " -----------------------";
00133   FEI_COUT.width(10);
00134   FEI_COUT << "-----  ";
00135   FEI_COUT.width(12);
00136   FEI_COUT << "---------";
00137   FEI_COUT.width(10);
00138   FEI_COUT <<" ------ "<<FEI_ENDL;
00139 }
00140 
00141 void print_benchmark_line(const char* name,
00142         double value,
00143         double goldvalue,
00144         const char* passfail)
00145 {
00146   FEI_COUT.setf(IOS_FIXED, IOS_FLOATFIELD);
00147   FEI_COUT.precision(1);
00148 
00149   FEI_COUT.width(38);
00150   FEI_COUT << name;
00151   FEI_COUT.width(10);
00152   FEI_COUT << value;
00153   FEI_COUT.width(12);
00154   if (goldvalue < 0.0) FEI_COUT << "n/a";
00155   else FEI_COUT << goldvalue;
00156   FEI_COUT.width(10);
00157   FEI_COUT << passfail << FEI_ENDL;
00158 }
00159 
00160 std::string add_macro_values(const char* name)
00161 {
00162   FEI_OSTRINGSTREAM osstr;
00163   osstr << name;
00164 
00165 #if defined(FEI_PLATFORM) && defined(FEI_OPT_LEVEL)
00166   osstr << "_" << FEI_PLATFORM << "_" << FEI_OPT_LEVEL;
00167 #else
00168   osstr << "_unknown_unknown";
00169 #endif
00170 
00171   return(osstr.str());
00172 }
00173 
00174 int test_benchmarks::runtests()
00175 {
00176   if (numProcs_ > 1) return(0);
00177 
00178   //CHK_ERR( test3() );
00179 
00180   FEI_COUT << FEI_ENDL
00181      << "  ***** Benchmarks pass if within 10% of 'gold-copy' *****"
00182      <<FEI_ENDL<<FEI_ENDL;
00183 
00184 #if defined(FEI_PLATFORM) && defined(FEI_OPT_LEVEL)
00185   FEI_COUT << "  FEI_PLATFORM: "<<FEI_PLATFORM
00186      <<", FEI_OPT_LEVEL: "<<FEI_OPT_LEVEL
00187      <<FEI_ENDL<<FEI_ENDL;
00188   FEI_COUT << "  'gold-copy' benchmark values will be searched for in ./fei_utest_timings.txt"<<FEI_ENDL;
00189   FEI_COUT <<FEI_ENDL;
00190 #else
00191   FEI_COUT << "  preprocessor macros FEI_PLATFORM and FEI_OPT_LEVEL aren't defined, so"<<FEI_ENDL;
00192   FEI_COUT << "  ./fei_utest_timings.txt will not be searched for 'gold-copy' benchmark values"<<FEI_ENDL<<FEI_ENDL;
00193 #endif
00194 
00195   CHK_ERR( test1() );
00196   CHK_ERR( test2() );
00197   CHK_ERR( test4() );
00198   CHK_ERR( test5() );
00199   CHK_ERR( test6() );
00200   CHK_ERR( test7() );
00201   CHK_ERR( test8() );
00202 
00203   return(0);
00204 }
00205 
00206 int test_benchmarks::test1()
00207 {
00208   FEI_COUT << "Following group of benchmarks inserts integers into ragged tables"
00209      << " (simulating"<<FEI_ENDL
00210      << "matrix-graph construction) using various data structures."<<FEI_ENDL
00211      << "A higher number is better, indicating more insertions"
00212      << " in fixed amount of time." << FEI_ENDL<<FEI_ENDL;
00213 
00214   print_benchmark_banner();
00215 
00216   int returnValue = 0;
00217   double value, goldvalue;
00218   std::string passfail;
00219   std::string testname;
00220 
00221   value = benchmark_raggedtable<std::map<int,std::set<int>*>,std::set<int> >();
00222   goldvalue = -1.0;
00223   passfail = " ";
00224   print_benchmark_line("std::map<std::set>", value, goldvalue, passfail.c_str());
00225 
00226   testname = add_macro_values("std::map<fei::ctg_set>");
00227   value = benchmark_raggedtable<std::map<int,fei::ctg_set<int>*>,fei::ctg_set<int> >();
00228   try {
00229     goldvalue = fei_test_utils::get_file_benchmark("./fei_utest_timings.txt",
00230               testname.c_str());
00231     passfail = fei_test_utils::check_test_result(value, goldvalue, 10);
00232     if (passfail != "passed") returnValue = -1;
00233   }
00234   catch(...) {
00235     goldvalue = -1.0;
00236     passfail = " ";
00237   }
00238 
00239   print_benchmark_line("std::map<fei::ctg_set>", value, goldvalue, passfail.c_str());
00240 
00241 
00242 
00243   testname = add_macro_values("snl_fei::MapContig<fei::ctg_set>");
00244   value = benchmark_raggedtable<snl_fei::MapContig<fei::ctg_set<int>*>,fei::ctg_set<int> >();
00245   try {
00246     goldvalue = fei_test_utils::get_file_benchmark("./fei_utest_timings.txt",
00247               testname.c_str());
00248     passfail = fei_test_utils::check_test_result(value, goldvalue, 10);
00249     if (passfail != "passed") returnValue = -1;
00250   }
00251   catch(...) {
00252     goldvalue = -1.0;
00253     passfail = " ";
00254   }
00255 
00256   print_benchmark_line("snl_fei::MapContig<fei::ctg_set>", value, goldvalue, passfail.c_str());
00257 
00258 
00259 
00260 #ifdef FEI_HASH_MAP
00261   value = benchmark_raggedtable<FEI_HASH_MAP<int,FEI_HASH_SET<int>*>,FEI_HASH_SET<int> >();
00262   goldvalue = -1.0;
00263   passfail = " ";
00264   print_benchmark_line("hash_map<hash_set>", value, goldvalue, passfail.c_str());
00265 
00266 
00267 #endif
00268 
00269 
00270   FEI_COUT << FEI_ENDL;
00271   if (returnValue != 0) {
00272     FEI_COUT << "at least 1 benchmark failed."<< FEI_ENDL << FEI_ENDL;
00273   }
00274   return(returnValue);
00275 }
00276 
00277 template<typename SET_TYPE>
00278 double time_set_insert(int len)
00279 {
00280   double start_time = fei::utils::cpu_time();
00281 
00282   SET_TYPE* set_objs = new SET_TYPE[len];
00283 
00284   int inner = 24;
00285   int outer = 8;
00286 
00287   int first = 9000;
00288   int inner_2 = inner/2;
00289 
00290   for(int n=0; n<len; ++n) {
00291     int col_n = first+n;
00292     SET_TYPE& set_ref = set_objs[n];
00293 
00294     for(int i=0; i<outer; ++i) {
00295       int col_i = col_n+i*outer;
00296 
00297       for(int j=0; j<inner_2; ++j) {
00298   set_ref.insert(col_i+j);
00299   set_ref.insert(col_i+j+inner_2);
00300       }
00301     }
00302   }
00303 
00304   delete [] set_objs;
00305 
00306   double elapsed_time = fei::utils::cpu_time() - start_time;
00307   return(elapsed_time);
00308 }
00309 
00310 template<typename SET_TYPE>
00311 double time_set_insert2(int len)
00312 {
00313   double start_time = fei::utils::cpu_time();
00314 
00315   SET_TYPE* set_objs = new SET_TYPE[len];
00316 
00317   int inner = 24;
00318   int outer = 8;
00319 
00320   int first = 9000;
00321 
00322   for(int n=0; n<len; ++n) {
00323     int col_n = first+n;
00324     SET_TYPE& set_ref = set_objs[n];
00325 
00326     for(int i=0; i<outer; ++i) {
00327       int col_i = col_n+i*outer;
00328 
00329       for(int j=0; j<inner/2; ++j) {
00330   set_ref.insert2(col_i+j);
00331   set_ref.insert2(col_i+j+inner/2);
00332       }
00333     }
00334   }
00335 
00336   delete [] set_objs;
00337 
00338   double elapsed_time = fei::utils::cpu_time() - start_time;
00339   return(elapsed_time);
00340 }
00341 
00342 template<typename SET_TYPE>
00343 double benchmark_set()
00344 {
00345   int len = 1200;
00346 
00347   //first find a len such that time_taken is at least 1 second
00348   double time_taken = time_set_insert<SET_TYPE>(len);
00349   while(time_taken < 1.0) {
00350     len *= 2;
00351     time_taken = time_set_insert<SET_TYPE>(len);
00352   }
00353 
00354   //now repeat until time_taken passes 5 seconds
00355   time_taken = 0.0;
00356   int i=0;
00357   while(time_taken<5.0) {
00358     time_taken += time_set_insert<SET_TYPE>(len);
00359     ++i;
00360   }
00361 
00362   return((double)(i*len)/time_taken);
00363 }
00364 
00365 template<typename SET_TYPE>
00366 double benchmark_set2()
00367 {
00368   int len = 1200;
00369 
00370   //first find a len such that time_taken is at least 1 second
00371   double time_taken = time_set_insert2<SET_TYPE>(len);
00372   while(time_taken < 1.0) {
00373     len *= 2;
00374     time_taken = time_set_insert2<SET_TYPE>(len);
00375   }
00376 
00377   //now repeat until time_taken passes 5 seconds
00378   time_taken = 0.0;
00379   int i=0;
00380   while(time_taken<5.0) {
00381     time_taken += time_set_insert2<SET_TYPE>(len);
00382     ++i;
00383   }
00384 
00385   return((double)(i*len)/time_taken);
00386 }
00387 
00388 
00389 int test_benchmarks::test2()
00390 {
00391   int returnValue = 0;
00392 
00393   FEI_COUT<<FEI_ENDL;
00394   FEI_COUT << "Following group of benchmarks inserts integers into sorted lists"
00395      << " (actually"<<FEI_ENDL
00396      << "sets), which is a sub-task of the ragged-table benchmarks..."<<FEI_ENDL
00397      << "A higher number is better."<<FEI_ENDL<<FEI_ENDL;
00398 
00399   print_benchmark_banner();
00400 
00401   double value, goldvalue;
00402   std::string passfail;
00403   std::string testname;
00404 
00405 
00406   value = benchmark_set<fei::ctg_set<int> >();
00407   testname = add_macro_values("fei::ctg_set");
00408   try {
00409     goldvalue = fei_test_utils::get_file_benchmark("./fei_utest_timings.txt",
00410               testname.c_str());
00411     passfail = fei_test_utils::check_test_result(value, goldvalue, 10);
00412     if (passfail != "passed") returnValue = -1;
00413   }
00414   catch(...) {
00415     goldvalue = -1.0;
00416     passfail = " ";
00417   }
00418 
00419   print_benchmark_line("fei::ctg_set::insert", value, goldvalue, passfail.c_str());
00420 
00421 
00422 #ifndef FEI_NO_STL_SET
00423 
00424   value = benchmark_set<std::set<int> >();
00425   goldvalue = -1.0;
00426   passfail = " ";
00427   print_benchmark_line("std::set::insert", value, goldvalue, passfail.c_str());
00428 
00429 #endif
00430 
00431 #ifdef FEI_HASH_SET
00432 
00433   value = benchmark_set<FEI_HASH_SET<int> >();
00434   goldvalue = -1.0;
00435   passfail = " ";
00436   print_benchmark_line("hash_set::insert", value, goldvalue, passfail.c_str());
00437 
00438 #endif
00439   FEI_COUT << FEI_ENDL;
00440   FEI_COUT << "More list/set insertions..." << FEI_ENDL << FEI_ENDL;
00441 
00442   print_benchmark_banner();
00443 
00444 
00445   value = benchmark_set2<fei::ctg_set<int> >();
00446   testname = add_macro_values("fei::ctg_set2");
00447   try {
00448     goldvalue = fei_test_utils::get_file_benchmark("./fei_utest_timings.txt",
00449               testname.c_str());
00450     passfail = fei_test_utils::check_test_result(value, goldvalue, 10);
00451     if (passfail != "passed") returnValue = -1;
00452   }
00453   catch(...) {
00454     goldvalue = -1.0;
00455     passfail = " ";
00456   }
00457 
00458   print_benchmark_line("fei::ctg_set::insert2", value, goldvalue, passfail.c_str());
00459 
00460   FEI_COUT << FEI_ENDL;
00461   if (returnValue != 0) {
00462     FEI_COUT << "at least 1 benchmark failed."<< FEI_ENDL << FEI_ENDL;
00463   }
00464 
00465   return(returnValue);
00466 }
00467 
00468 int test_benchmarks::test3()
00469 {
00470   int len = 100000;
00471   int   n = 100000;
00472 
00473   std::vector<int> stdvector(len);
00474 
00475   std::vector<int> stdv_dest;
00476 
00477   int* stdvptr = &(stdvector[0]);
00478 
00479   for(int i=0; i<len; ++i) {
00480     stdvptr[i] = i*2;
00481   }
00482 
00483   FEI_COUT << FEI_ENDL << "time to perform " << n
00484            << " binary-searches and inserts on an std::vector" << FEI_ENDL
00485      << " of length " << len << ": " << FEI_ENDL;
00486 
00487   double start_time = fei::utils::cpu_time();
00488 
00489   stdvector.reserve(n*2);
00490 
00491   std::vector<int>::iterator
00492     v_iter,
00493     v_beg = stdvector.begin(),
00494     v_end = stdvector.end();
00495 
00496   for(int k=0; k<n; ++k) {
00497     v_iter = std::lower_bound(v_beg, v_end, k*2);
00498     stdvector.insert(v_iter, k*2-1);
00499     v_beg = stdvector.begin();
00500     v_end = stdvector.end();
00501   }
00502 
00503   double elapsed_time = fei::utils::cpu_time() - start_time;
00504 
00505   FEI_COUT << elapsed_time << FEI_ENDL;
00506 
00507   return(0);
00508 }
00509 
00510 int test_benchmarks::test4()
00511 {
00512   return(0);
00513 }
00514 
00515 int test_benchmarks::test5()
00516 {
00517   return(0);
00518 }
00519 
00520 int test_benchmarks::test6()
00521 {
00522   return(0);
00523 }
00524 
00525 int test_benchmarks::test7()
00526 {
00527   return(0);
00528 }
00529 
00530 int test_benchmarks::test8()
00531 {
00532   return(0);
00533 }
00534 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends