FEI  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
test_benchmarks.cpp
1 /*--------------------------------------------------------------------*/
2 /* Copyright 2005 Sandia Corporation. */
3 /* Under the terms of Contract DE-AC04-94AL85000, there is a */
4 /* non-exclusive license for use of this work by or on behalf */
5 /* of the U.S. Government. Export of this program may require */
6 /* a license from the United States Government. */
7 /*--------------------------------------------------------------------*/
8 
9 #include <fei_macros.hpp>
10 #include <fei_utils.hpp>
11 #include <test_utils/fei_test_utils.hpp>
12 #include <test_utils/test_benchmarks.hpp>
13 #include <snl_fei_Utils.hpp>
14 #include <fei_ctg_set.hpp>
15 #include <snl_fei_RaggedTable.hpp>
16 #include <snl_fei_RaggedTable_specialize.hpp>
17 #include <test_utils/HexBeam.hpp>
18 
19 #undef fei_file
20 #define fei_file "test_benchmarks.cpp"
21 
22 #include <fei_ErrMacros.hpp>
23 
24 test_benchmarks::test_benchmarks(MPI_Comm comm)
25  : tester(comm)
26 {
27 }
28 
29 test_benchmarks::~test_benchmarks()
30 {
31 }
32 
33 template<typename MAP_TYPE, typename SET_TYPE>
34 double time_raggedtable_insert(int len)
35 {
36  double start_time = fei::utils::cpu_time();
37 
38  HexBeam hexcube(10, len, 1, HexBeam::OneD, 1, 0);
39 
40  snl_fei::RaggedTable<MAP_TYPE,SET_TYPE> table(0, hexcube.numLocalNodes());
41 
42  int numIndices = hexcube.numNodesPerElem();
43 
44  int* indices = new int[numIndices];
45 
46  int first = hexcube.firstLocalElem();
47 
48  for(int n=0; n<hexcube.numLocalElems(); ++n) {
49  int elem = first+n;
50 
51  hexcube.getElemConnectivity(elem, indices);
52 
53  table.addIndices(numIndices, indices, numIndices, indices);
54  }
55 
56  delete [] indices;
57 
58  double elapsed_time = fei::utils::cpu_time() - start_time;
59  return(elapsed_time);
60 }
61 
62 template<typename MAP_TYPE, typename SET_TYPE>
63 double benchmark_raggedtable()
64 {
65  int len = 80;
66 
67  //first find a len such that time_taken is at least 1 second
68  double time_taken = time_raggedtable_insert<MAP_TYPE,SET_TYPE>(len);
69  while(time_taken < 1.0) {
70  len *= 2;
71  time_taken = time_raggedtable_insert<MAP_TYPE,SET_TYPE>(len);
72  }
73 
74  //now repeat until time_taken passes 5 seconds
75  time_taken = 0.0;
76  int i=0;
77  while(time_taken<5.0) {
78  time_taken += time_raggedtable_insert<MAP_TYPE,SET_TYPE>(len);
79  ++i;
80  }
81 
82  return((double)(i*len)/time_taken);
83 }
84 
85 void print_benchmark_banner()
86 {
87 
88  FEI_COUT.width(38);
89  FEI_COUT << " Benchmark name ";
90  FEI_COUT.width(10);
91  FEI_COUT << "Value ";
92  FEI_COUT.width(12);
93  FEI_COUT << "gold-copy";
94  FEI_COUT.width(10);
95  FEI_COUT <<" Result "<<FEI_ENDL;
96 
97  FEI_COUT.width(38);
98  FEI_COUT << " -----------------------";
99  FEI_COUT.width(10);
100  FEI_COUT << "----- ";
101  FEI_COUT.width(12);
102  FEI_COUT << "---------";
103  FEI_COUT.width(10);
104  FEI_COUT <<" ------ "<<FEI_ENDL;
105 }
106 
107 void print_benchmark_line(const char* name,
108  double value,
109  double goldvalue,
110  const char* passfail)
111 {
112  FEI_COUT.setf(IOS_FIXED, IOS_FLOATFIELD);
113  FEI_COUT.precision(1);
114 
115  FEI_COUT.width(38);
116  FEI_COUT << name;
117  FEI_COUT.width(10);
118  FEI_COUT << value;
119  FEI_COUT.width(12);
120  if (goldvalue < 0.0) FEI_COUT << "n/a";
121  else FEI_COUT << goldvalue;
122  FEI_COUT.width(10);
123  FEI_COUT << passfail << FEI_ENDL;
124 }
125 
126 std::string add_macro_values(const char* name)
127 {
128  FEI_OSTRINGSTREAM osstr;
129  osstr << name;
130 
131 #if defined(FEI_PLATFORM) && defined(FEI_OPT_LEVEL)
132  osstr << "_" << FEI_PLATFORM << "_" << FEI_OPT_LEVEL;
133 #else
134  osstr << "_unknown_unknown";
135 #endif
136 
137  return(osstr.str());
138 }
139 
140 int test_benchmarks::runtests()
141 {
142  if (numProcs_ > 1) return(0);
143 
144  //CHK_ERR( test3() );
145 
146  FEI_COUT << FEI_ENDL
147  << " ***** Benchmarks pass if within 10% of 'gold-copy' *****"
148  <<FEI_ENDL<<FEI_ENDL;
149 
150 #if defined(FEI_PLATFORM) && defined(FEI_OPT_LEVEL)
151  FEI_COUT << " FEI_PLATFORM: "<<FEI_PLATFORM
152  <<", FEI_OPT_LEVEL: "<<FEI_OPT_LEVEL
153  <<FEI_ENDL<<FEI_ENDL;
154  FEI_COUT << " 'gold-copy' benchmark values will be searched for in ./fei_utest_timings.txt"<<FEI_ENDL;
155  FEI_COUT <<FEI_ENDL;
156 #else
157  FEI_COUT << " preprocessor macros FEI_PLATFORM and FEI_OPT_LEVEL aren't defined, so"<<FEI_ENDL;
158  FEI_COUT << " ./fei_utest_timings.txt will not be searched for 'gold-copy' benchmark values"<<FEI_ENDL<<FEI_ENDL;
159 #endif
160 
161  CHK_ERR( test1() );
162  CHK_ERR( test2() );
163  CHK_ERR( test4() );
164  CHK_ERR( test5() );
165  CHK_ERR( test6() );
166  CHK_ERR( test7() );
167  CHK_ERR( test8() );
168 
169  return(0);
170 }
171 
172 int test_benchmarks::test1()
173 {
174  FEI_COUT << "Following group of benchmarks inserts integers into ragged tables"
175  << " (simulating"<<FEI_ENDL
176  << "matrix-graph construction) using various data structures."<<FEI_ENDL
177  << "A higher number is better, indicating more insertions"
178  << " in fixed amount of time." << FEI_ENDL<<FEI_ENDL;
179 
180  print_benchmark_banner();
181 
182  int returnValue = 0;
183  double value, goldvalue;
184  std::string passfail;
185  std::string testname;
186 
187  value = benchmark_raggedtable<std::map<int,std::set<int>*>,std::set<int> >();
188  goldvalue = -1.0;
189  passfail = " ";
190  print_benchmark_line("std::map<std::set>", value, goldvalue, passfail.c_str());
191 
192  testname = add_macro_values("std::map<fei::ctg_set>");
193  value = benchmark_raggedtable<std::map<int,fei::ctg_set<int>*>,fei::ctg_set<int> >();
194  try {
195  goldvalue = fei_test_utils::get_file_benchmark("./fei_utest_timings.txt",
196  testname.c_str());
197  passfail = fei_test_utils::check_test_result(value, goldvalue, 10);
198  if (passfail != "passed") returnValue = -1;
199  }
200  catch(...) {
201  goldvalue = -1.0;
202  passfail = " ";
203  }
204 
205  print_benchmark_line("std::map<fei::ctg_set>", value, goldvalue, passfail.c_str());
206 
207 
208 
209  testname = add_macro_values("snl_fei::MapContig<fei::ctg_set>");
210  value = benchmark_raggedtable<snl_fei::MapContig<fei::ctg_set<int>*>,fei::ctg_set<int> >();
211  try {
212  goldvalue = fei_test_utils::get_file_benchmark("./fei_utest_timings.txt",
213  testname.c_str());
214  passfail = fei_test_utils::check_test_result(value, goldvalue, 10);
215  if (passfail != "passed") returnValue = -1;
216  }
217  catch(...) {
218  goldvalue = -1.0;
219  passfail = " ";
220  }
221 
222  print_benchmark_line("snl_fei::MapContig<fei::ctg_set>", value, goldvalue, passfail.c_str());
223 
224 
225 
226 #ifdef FEI_HASH_MAP
227  value = benchmark_raggedtable<FEI_HASH_MAP<int,FEI_HASH_SET<int>*>,FEI_HASH_SET<int> >();
228  goldvalue = -1.0;
229  passfail = " ";
230  print_benchmark_line("hash_map<hash_set>", value, goldvalue, passfail.c_str());
231 
232 
233 #endif
234 
235 
236  FEI_COUT << FEI_ENDL;
237  if (returnValue != 0) {
238  FEI_COUT << "at least 1 benchmark failed."<< FEI_ENDL << FEI_ENDL;
239  }
240  return(returnValue);
241 }
242 
243 template<typename SET_TYPE>
244 double time_set_insert(int len)
245 {
246  double start_time = fei::utils::cpu_time();
247 
248  SET_TYPE* set_objs = new SET_TYPE[len];
249 
250  int inner = 24;
251  int outer = 8;
252 
253  int first = 9000;
254  int inner_2 = inner/2;
255 
256  for(int n=0; n<len; ++n) {
257  int col_n = first+n;
258  SET_TYPE& set_ref = set_objs[n];
259 
260  for(int i=0; i<outer; ++i) {
261  int col_i = col_n+i*outer;
262 
263  for(int j=0; j<inner_2; ++j) {
264  set_ref.insert(col_i+j);
265  set_ref.insert(col_i+j+inner_2);
266  }
267  }
268  }
269 
270  delete [] set_objs;
271 
272  double elapsed_time = fei::utils::cpu_time() - start_time;
273  return(elapsed_time);
274 }
275 
276 template<typename SET_TYPE>
277 double time_set_insert2(int len)
278 {
279  double start_time = fei::utils::cpu_time();
280 
281  SET_TYPE* set_objs = new SET_TYPE[len];
282 
283  int inner = 24;
284  int outer = 8;
285 
286  int first = 9000;
287 
288  for(int n=0; n<len; ++n) {
289  int col_n = first+n;
290  SET_TYPE& set_ref = set_objs[n];
291 
292  for(int i=0; i<outer; ++i) {
293  int col_i = col_n+i*outer;
294 
295  for(int j=0; j<inner/2; ++j) {
296  set_ref.insert2(col_i+j);
297  set_ref.insert2(col_i+j+inner/2);
298  }
299  }
300  }
301 
302  delete [] set_objs;
303 
304  double elapsed_time = fei::utils::cpu_time() - start_time;
305  return(elapsed_time);
306 }
307 
308 template<typename SET_TYPE>
309 double benchmark_set()
310 {
311  int len = 1200;
312 
313  //first find a len such that time_taken is at least 1 second
314  double time_taken = time_set_insert<SET_TYPE>(len);
315  while(time_taken < 1.0) {
316  len *= 2;
317  time_taken = time_set_insert<SET_TYPE>(len);
318  }
319 
320  //now repeat until time_taken passes 5 seconds
321  time_taken = 0.0;
322  int i=0;
323  while(time_taken<5.0) {
324  time_taken += time_set_insert<SET_TYPE>(len);
325  ++i;
326  }
327 
328  return((double)(i*len)/time_taken);
329 }
330 
331 template<typename SET_TYPE>
332 double benchmark_set2()
333 {
334  int len = 1200;
335 
336  //first find a len such that time_taken is at least 1 second
337  double time_taken = time_set_insert2<SET_TYPE>(len);
338  while(time_taken < 1.0) {
339  len *= 2;
340  time_taken = time_set_insert2<SET_TYPE>(len);
341  }
342 
343  //now repeat until time_taken passes 5 seconds
344  time_taken = 0.0;
345  int i=0;
346  while(time_taken<5.0) {
347  time_taken += time_set_insert2<SET_TYPE>(len);
348  ++i;
349  }
350 
351  return((double)(i*len)/time_taken);
352 }
353 
354 
355 int test_benchmarks::test2()
356 {
357  int returnValue = 0;
358 
359  FEI_COUT<<FEI_ENDL;
360  FEI_COUT << "Following group of benchmarks inserts integers into sorted lists"
361  << " (actually"<<FEI_ENDL
362  << "sets), which is a sub-task of the ragged-table benchmarks..."<<FEI_ENDL
363  << "A higher number is better."<<FEI_ENDL<<FEI_ENDL;
364 
365  print_benchmark_banner();
366 
367  double value, goldvalue;
368  std::string passfail;
369  std::string testname;
370 
371 
372  value = benchmark_set<fei::ctg_set<int> >();
373  testname = add_macro_values("fei::ctg_set");
374  try {
375  goldvalue = fei_test_utils::get_file_benchmark("./fei_utest_timings.txt",
376  testname.c_str());
377  passfail = fei_test_utils::check_test_result(value, goldvalue, 10);
378  if (passfail != "passed") returnValue = -1;
379  }
380  catch(...) {
381  goldvalue = -1.0;
382  passfail = " ";
383  }
384 
385  print_benchmark_line("fei::ctg_set::insert", value, goldvalue, passfail.c_str());
386 
387 
388 #ifndef FEI_NO_STL_SET
389 
390  value = benchmark_set<std::set<int> >();
391  goldvalue = -1.0;
392  passfail = " ";
393  print_benchmark_line("std::set::insert", value, goldvalue, passfail.c_str());
394 
395 #endif
396 
397 #ifdef FEI_HASH_SET
398 
399  value = benchmark_set<FEI_HASH_SET<int> >();
400  goldvalue = -1.0;
401  passfail = " ";
402  print_benchmark_line("hash_set::insert", value, goldvalue, passfail.c_str());
403 
404 #endif
405  FEI_COUT << FEI_ENDL;
406  FEI_COUT << "More list/set insertions..." << FEI_ENDL << FEI_ENDL;
407 
408  print_benchmark_banner();
409 
410 
411  value = benchmark_set2<fei::ctg_set<int> >();
412  testname = add_macro_values("fei::ctg_set2");
413  try {
414  goldvalue = fei_test_utils::get_file_benchmark("./fei_utest_timings.txt",
415  testname.c_str());
416  passfail = fei_test_utils::check_test_result(value, goldvalue, 10);
417  if (passfail != "passed") returnValue = -1;
418  }
419  catch(...) {
420  goldvalue = -1.0;
421  passfail = " ";
422  }
423 
424  print_benchmark_line("fei::ctg_set::insert2", value, goldvalue, passfail.c_str());
425 
426  FEI_COUT << FEI_ENDL;
427  if (returnValue != 0) {
428  FEI_COUT << "at least 1 benchmark failed."<< FEI_ENDL << FEI_ENDL;
429  }
430 
431  return(returnValue);
432 }
433 
434 int test_benchmarks::test3()
435 {
436  int len = 100000;
437  int n = 100000;
438 
439  std::vector<int> stdvector(len);
440 
441  std::vector<int> stdv_dest;
442 
443  int* stdvptr = &(stdvector[0]);
444 
445  for(int i=0; i<len; ++i) {
446  stdvptr[i] = i*2;
447  }
448 
449  FEI_COUT << FEI_ENDL << "time to perform " << n
450  << " binary-searches and inserts on an std::vector" << FEI_ENDL
451  << " of length " << len << ": " << FEI_ENDL;
452 
453  double start_time = fei::utils::cpu_time();
454 
455  stdvector.reserve(n*2);
456 
457  std::vector<int>::iterator
458  v_iter,
459  v_beg = stdvector.begin(),
460  v_end = stdvector.end();
461 
462  for(int k=0; k<n; ++k) {
463  v_iter = std::lower_bound(v_beg, v_end, k*2);
464  stdvector.insert(v_iter, k*2-1);
465  v_beg = stdvector.begin();
466  v_end = stdvector.end();
467  }
468 
469  double elapsed_time = fei::utils::cpu_time() - start_time;
470 
471  FEI_COUT << elapsed_time << FEI_ENDL;
472 
473  return(0);
474 }
475 
476 int test_benchmarks::test4()
477 {
478  return(0);
479 }
480 
481 int test_benchmarks::test5()
482 {
483  return(0);
484 }
485 
486 int test_benchmarks::test6()
487 {
488  return(0);
489 }
490 
491 int test_benchmarks::test7()
492 {
493  return(0);
494 }
495 
496 int test_benchmarks::test8()
497 {
498  return(0);
499 }
500 
const std::string passfail(const bool result)
double get_file_benchmark(const char *filename, const char *testname)
double cpu_time()
Definition: fei_utils.cpp:46
void addIndices(int row, int numIndices, const int *indices)