Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
stacked_timer.cpp
Go to the documentation of this file.
1 // @HEADER
2 // @HEADER
3 
10 #include "Teuchos_DefaultComm.hpp"
11 #include <sstream>
12 #include <thread> // std::this_thread::sleep_for;
13 #include <tuple>
14 #include <regex>
15 #include <iterator>
16 #include <limits>
17 
18 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
19 #include "Kokkos_Core.hpp"
20 #endif
21 
22 TEUCHOS_UNIT_TEST(PerformanceMonitorBase, UnsortedMergeUnion) {
23 
25 
26  Teuchos::Array<std::string> a,b, tmp_a, tmp_b;
27 
28  a.push_back("foo");
29  a.push_back("bar");
30  a.push_back("car");
31 
32  b.push_back("car");
33  b.push_back("bar");
34  b.push_back("cat");
35 
36 
37  tmp_a=a;
38  tmp_b=b;
40  TEST_EQUALITY(tmp_b.size(),4);
41  TEST_EQUALITY(tmp_b[0], "car");
42  TEST_EQUALITY(tmp_b[1], "bar");
43  TEST_EQUALITY(tmp_b[2], "cat");
44  TEST_EQUALITY(tmp_b[3], "foo");
45 }
46 
47 TEUCHOS_UNIT_TEST(PerformanceMonitorBase, UnsortedMergeIntersection) {
48 
50 
51  Teuchos::Array<std::string> a,b, tmp_a, tmp_b;
52 
53  a.push_back("foo");
54  a.push_back("bar");
55  a.push_back("car");
56 
57  b.push_back("car");
58  b.push_back("bar");
59  b.push_back("cat");
60 
61 
62  tmp_a=a;
63  tmp_b=b;
65  TEST_EQUALITY(tmp_b.size(),2);
66  TEST_EQUALITY(tmp_b[0], "car");
67  TEST_EQUALITY(tmp_b[1], "bar");
68 }
69 
70 TEUCHOS_UNIT_TEST(StackedTimer, Basic)
71 {
73  const int myRank = Teuchos::rank(*comm);
74 
75  Teuchos::StackedTimer timer("My New Timer");
76  timer.enableVerbose(true);
77  timer.setVerboseOstream(Teuchos::rcpFromRef(std::cout));
78  timer.start("Total Time");
79  {
80  for (int i=0; i < 10; ++i) {
81 
82  timer.start("Assembly");
83  std::this_thread::sleep_for(std::chrono::milliseconds{100});
84  timer.stop("Assembly");
85 
86  timer.start("Solve");
87  {
88  timer.start("Prec");
89  std::this_thread::sleep_for(std::chrono::milliseconds{50});
90  timer.stop("Prec");
91 
92  // Test different timers on different mpi processes
93  if (myRank == 0 ) {
94  const std::string label = "Rank 0 ONLY";
95  timer.start(label);
96  std::this_thread::sleep_for(std::chrono::milliseconds{50});
97  TEST_ASSERT((timer.findTimer("My New Timer@Total Time@Solve@Rank 0 ONLY")).running);
98  timer.stop(label);
99  TEST_ASSERT(!(timer.findTimer("My New Timer@Total Time@Solve@Rank 0 ONLY")).running);
100  } else {
101  timer.start("Not Rank 0");
102  std::this_thread::sleep_for(std::chrono::milliseconds{50});
103  TEST_ASSERT((timer.findTimer("My New Timer@Total Time@Solve@Not Rank 0")).running);
104  timer.stop("Not Rank 0");
105  TEST_ASSERT(!(timer.findTimer("My New Timer@Total Time@Solve@Not Rank 0")).running);
106  }
107  }
108  timer.stop("Solve");
109 
110  }
111  }
112  timer.stop("Total Time");
113  timer.stopBaseTimer();
114 
115  TEST_EQUALITY((timer.findTimer("My New Timer@Total Time")).count, 1);
116  TEST_EQUALITY((timer.findTimer("My New Timer@Total Time@Assembly")).count, 10);
117  TEST_EQUALITY((timer.findTimer("My New Timer@Total Time@Solve")).count, 10);
118  TEST_EQUALITY((timer.findTimer("My New Timer@Total Time@Solve@Prec")).count, 10);
119 
120  // Test for exception for bad timer name
121  TEST_THROW(timer.findTimer("Testing misspelled timer name!"),std::runtime_error);
122 
123  // Pre-aggregation
124  if (myRank == 0) {
125  TEST_EQUALITY((timer.findTimer("My New Timer@Total Time@Solve@Rank 0 ONLY")).count, 10);
126  }
127  else {
128  TEST_EQUALITY((timer.findTimer("My New Timer@Total Time@Solve@Not Rank 0")).count, 10);
129  }
130 
132  options.output_histogram=true;
133  options.num_histogram=3;
134  options.print_warnings=false;
135 
136  // Get the report
137  std::stringstream sout1;
138  timer.report(sout1, comm, options);
139 
140  // Make sure can call report() multiple times, i.e. aggregation
141  // resets correctly for each call report()
142  std::stringstream sout2;
143  timer.report(sout2, comm, options);
144  TEST_EQUALITY(sout1.str(),sout2.str());
145 
146  // Gold file results (timer name,expected runtime,number of calls)
147  std::vector<std::tuple<std::string,double,unsigned long>> lineChecks;
148  lineChecks.push_back(std::make_tuple("My New Timer:",2.0,1));
149  lineChecks.push_back(std::make_tuple("Total Time:",2.0,1));
150  lineChecks.push_back(std::make_tuple("Assembly:",1.0,10));
151  lineChecks.push_back(std::make_tuple("Solve:",1.0,10));
152  lineChecks.push_back(std::make_tuple("Prec:",0.5,10));
153 
154  // Check the report() output. Read the first few lines and parse the
155  // expected timer label, the runtime and the counts.
156  //
157  // * NOTE: The report only combines values to a single MPI process, so
158  // only check on that process.
159  // * NOTE: regex not supported in gcc until 4.9. Can drop this check
160  // when Trilinos drops support for gcc 4.8.
161 #if !defined(__GNUC__) \
162  || ( defined(__GNUC__) && (__GNUC__ > 4) ) \
163  || ( defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC__MINOR__ > 8) )
164 
165  if (myRank == 0) {
166  const double timerTolerance = 0.25; // +- 0.25 seconds
167  std::istringstream is(sout1.str());
168  for (const auto& check : lineChecks) {
169 
170  std::string line;
171  std::getline(is,line);
172  std::smatch regexSMatch;
173  std::regex timerName(std::get<0>(check));
174  std::regex_search(line,regexSMatch,timerName);
175  TEST_ASSERT(!regexSMatch.empty());
176 
177  // Split string to get time and count
178  std::regex delimiter(":\\s|\\s\\[|\\]\\s");
179  std::sregex_token_iterator tok(line.begin(), line.end(),delimiter,-1);
180 
181  const std::string timeAsString = (++tok)->str();
182  const double time = std::stod(timeAsString);
183  TEST_FLOATING_EQUALITY(time,std::get<1>(check),timerTolerance);
184 
185  const std::string countAsString = (++tok)->str();
186  const unsigned long count = std::stoul(countAsString);
187  TEST_EQUALITY(count,std::get<2>(check));
188  }
189  }
190 #endif
191 
192  // Print to screen
193  out << "\n### Printing default report ###" << std::endl;
195  timer.report(out, comm, defaultOptions);
196 
197  // Test some options
198  out << "\n### Printing aligned_column with timers names on left ###" << std::endl;
199  options.output_fraction = true;
200  options.output_total_updates = true;
201  options.output_minmax = true;
202  options.output_histogram = true;
203  options.num_histogram = 3;
204  options.align_columns = true;
205  timer.report(out, comm, options);
206 
207  // Toggle names before values
209  out << "\n### Printing aligned_column with timers names on right ###" << std::endl;
210  options.print_names_before_values = false;
211  // Make sure neither report() nor reportXML() have side effects that change the output:
212  // calling them any number of times with no new starts/stops and the same OutputOptions
213  // should produce identical output.
214  //
215  // This is very important as performance tests will
216  // typically call both report() and reportWatchrXML().
217  std::string reportOut;
218  {
219  std::ostringstream reportOut1;
220  timer.report(reportOut1, comm, options);
221  std::ostringstream reportOut2;
222  timer.report(reportOut2, comm, options);
223  reportOut = reportOut1.str();
224  TEST_EQUALITY(reportOut, reportOut2.str());
225  }
226  std::string reportXmlOut;
227  {
228  std::ostringstream reportOut1;
229  timer.reportXML(reportOut1, "2020_01_01", "2020-01-01T01:02:03", comm);
230  std::ostringstream reportOut2;
231  timer.reportXML(reportOut2, "2020_01_01", "2020-01-01T01:02:03", comm);
232  reportXmlOut = reportOut1.str();
233  TEST_EQUALITY(reportXmlOut, reportOut2.str());
234  }
235  out << reportOut << '\n';
236  out << reportXmlOut << '\n';
237 }
238 
239 TEUCHOS_UNIT_TEST(StackedTimer, UnitTestSupport)
240 {
242  const int myRank = Teuchos::rank(*comm);
243 
244  const auto timeMonitorDefaultStackedTimer = Teuchos::TimeMonitor::getStackedTimer();
245  const auto timer = Teuchos::rcp(new Teuchos::StackedTimer("Total Time", false));
246  timer->startBaseTimer();
247  for (int i=0; i < 10; ++i) {
248  timer-> start("Subtask");
249  timer->incrementUpdates();
250  timer->incrementUpdates(2);
251  timer-> stop("Subtask");
252  }
253  timer->stopBaseTimer();
254 
255  // If users want to set timer values for unit testing, force them to
256  // const_cast the timer by returning a const Timer object.
257  auto top_timer = const_cast<Teuchos::BaseTimer*>(timer->findBaseTimer("Total Time"));
258  auto sub_timer = const_cast<Teuchos::BaseTimer*>(timer->findBaseTimer("Total Time@Subtask"));
259  TEST_ASSERT(top_timer != nullptr);
260  TEST_ASSERT(sub_timer != nullptr);
261 
262  // Test for exception for bad timer name
263  TEST_THROW(timer->findBaseTimer("Testing misspelled timer name!"),std::runtime_error);
264 
265  {
266  TEST_EQUALITY(top_timer->numCalls(),1);
267  TEST_EQUALITY(top_timer->numUpdates(),0);
268  TEST_EQUALITY(sub_timer->numCalls(),10);
269  TEST_EQUALITY(sub_timer->numUpdates(),30);
270  }
271 
272  // Test the serial version of report
273  if (myRank == 0)
274  timer->report(out);
275 
276  // Override timers for unit testing
277  top_timer->setAccumulatedTime(5000.0);
278  top_timer->overrideNumCallsForUnitTesting(2);
279  top_timer->overrideNumUpdatesForUnitTesting(3);
280  sub_timer->setAccumulatedTime(4000.0);
281  sub_timer->overrideNumCallsForUnitTesting(4);
282  sub_timer->overrideNumUpdatesForUnitTesting(5);
283  {
284  const double timerTolerance = 100.0 * std::numeric_limits<double>::epsilon();
285  TEST_FLOATING_EQUALITY(5000.0,top_timer->accumulatedTime(),timerTolerance);
286  TEST_EQUALITY(top_timer->numCalls(),2);
287  TEST_EQUALITY(top_timer->numUpdates(),3);
288  TEST_FLOATING_EQUALITY(4000.0,sub_timer->accumulatedTime(),timerTolerance);
289  TEST_EQUALITY(sub_timer->numCalls(),4);
290  TEST_EQUALITY(sub_timer->numUpdates(),5);
291  }
292 
293  if (myRank == 0)
294  timer->report(out);
295 }
296 
297 TEUCHOS_UNIT_TEST(StackedTimer, TimeMonitorInteroperability)
298 {
300 
301  const auto diffTimer = Teuchos::TimeMonitor::getNewTimer("Diffusion Term");
302  const auto rxnTimer = Teuchos::TimeMonitor::getNewTimer("Reaction Term");
303  const auto precTimer = Teuchos::TimeMonitor::getNewTimer("Prec");
304  const auto gmresTimer = Teuchos::TimeMonitor::getNewTimer("GMRES");
305 
306  // Test the set and get stacked timer methods on TimeMonitor
307  const auto timeMonitorDefaultStackedTimer = Teuchos::TimeMonitor::getStackedTimer();
308  const auto timer = Teuchos::rcp(new Teuchos::StackedTimer("TM:Interoperability"));
309  TEST_ASSERT(nonnull(timeMonitorDefaultStackedTimer));
310  TEST_ASSERT(nonnull(timer));
311  TEST_ASSERT(timeMonitorDefaultStackedTimer != timer);
314 
315  timer->start("Total Time");
316  {
317  for (int i=0; i < 10; ++i) {
318 
319  timer->start("Assembly");
320  {
321  {
322  Teuchos::TimeMonitor tm(*diffTimer);
323  std::this_thread::sleep_for(std::chrono::milliseconds{25});
324  }
325  {
326  Teuchos::TimeMonitor tm(*rxnTimer);
327  std::this_thread::sleep_for(std::chrono::milliseconds{75});
328  }
329  // Remainder
330  std::this_thread::sleep_for(std::chrono::milliseconds{100});
331  }
332  timer->stop("Assembly");
333  timer->start("Solve");
334  {
335  {
336  Teuchos::TimeMonitor tm(*precTimer);
337  std::this_thread::sleep_for(std::chrono::milliseconds{50});
338  }
339  {
340  Teuchos::TimeMonitor tm(*gmresTimer);
341  std::this_thread::sleep_for(std::chrono::milliseconds{50});
342  }
343  // Remainder
344  std::this_thread::sleep_for(std::chrono::milliseconds{100});
345  }
346  timer->stop("Solve");
347  std::this_thread::sleep_for(std::chrono::milliseconds{100});
348  }
349  }
350  timer->stop("Total Time");
351  timer->stopBaseTimer();
352 
353  assert(size(*comm)>0);
354 
355  TEST_EQUALITY((timer->findTimer("TM:Interoperability@Total Time")).count, 1);
356  TEST_EQUALITY((timer->findTimer("TM:Interoperability@Total Time@Assembly")).count, 10);
357 
358  // Make sure the TimeMonitor added the timers
359 #ifdef HAVE_TEUCHOS_ADD_TIME_MONITOR_TO_STACKED_TIMER
360  TEST_EQUALITY((timer->findTimer("TM:Interoperability@Total Time@Solve@Prec")).count, 10);
361  TEST_EQUALITY((timer->findTimer("TM:Interoperability@Total Time@Solve@GMRES")).count, 10);
362 #endif
363 
365  out << "\n### Printing default report ###" << std::endl;
366  options.output_histogram=true;
367  options.num_histogram=3;
368  options.output_fraction=true;
369  timer->report(out, comm, options);
370 
371  out << "\n### Printing aligned_column with timers names on left ###" << std::endl;
372  options.align_columns = true;
373  timer->report(out, comm, options);
374 
375  out << "\n### Printing aligned_column with timers names on right ###" << std::endl;
376  // options.print_names_before_values=false requires that
377  // options.align_output=true. The code will automatically fix this
378  // and print a warning if warnings are enabled. Testing this here by
379  // specifying the incorrect logic.
380  options.align_columns = false;
381  options.print_names_before_values = false;
382  timer->report(out, comm, options);
383 
384  //Testing limited number of levels in printing
385  out << "\n### Printing with max_levels=2 ###" << std::endl;
386  options.max_levels=2;
387  options.align_columns = true;
388  options.print_names_before_values = true;
389  timer->report(out, comm, options);
390 }
391 
392 TEUCHOS_UNIT_TEST(StackedTimer, drop_time)
393 {
394 
395  Teuchos::StackedTimer timer("L0");
396  timer.start("L1a");
397  timer.start("L2a");
398  timer.stop("L2a");
399  timer.start("L2b");
400  timer.stop("L2b");
401  timer.stop("L1a");
402  timer.start("L1b");
403  timer.start("L2c");
404  timer.stop("L2c");
405  timer.start("L2d");
406  timer.stop("L2d");
407  timer.stop("L1b");
408  timer.stopBaseTimer();
409 
410  const_cast<Teuchos::BaseTimer*>(timer.findBaseTimer("L0"))->setAccumulatedTime(5.0);
411  const_cast<Teuchos::BaseTimer*>(timer.findBaseTimer("L0@L1a"))->setAccumulatedTime(3.0);
412  const_cast<Teuchos::BaseTimer*>(timer.findBaseTimer("L0@L1a@L2a"))->setAccumulatedTime(0.4);
413  const_cast<Teuchos::BaseTimer*>(timer.findBaseTimer("L0@L1a@L2b"))->setAccumulatedTime(1.01);
414  const_cast<Teuchos::BaseTimer*>(timer.findBaseTimer("L0@L1b"))->setAccumulatedTime(0.1);
415  const_cast<Teuchos::BaseTimer*>(timer.findBaseTimer("L0@L1b@L2c"))->setAccumulatedTime(0.05);
416  const_cast<Teuchos::BaseTimer*>(timer.findBaseTimer("L0@L1b@L2d"))->setAccumulatedTime(0.04);
417 
419  const int myRank = Teuchos::rank(*comm);
421  options.drop_time = 1.0;
422 
423  out << "\n### Printing default report ###" << std::endl;
424  options.output_histogram=true;
425  options.num_histogram=3;
426  options.output_fraction=true;
427  timer.report(out, comm, options);
428  {
429  std::ostringstream os;
430  timer.report(os, comm, options);
431  if (myRank == 0) {
432  TEST_ASSERT(os.str().find("L2a") == std::string::npos); // should be dropped
433  TEST_ASSERT(os.str().find("L2b") != std::string::npos); // should be printed
434  TEST_ASSERT(os.str().find("L1b") == std::string::npos); // should be dropped
435  }
436  }
437 
438  out << "\n### Printing aligned_column with timers names on left ###" << std::endl;
439  options.align_columns = true;
440  timer.report(out, comm, options);
441  {
442  std::ostringstream os;
443  timer.report(os, comm, options);
444  if (myRank == 0) {
445  TEST_ASSERT(os.str().find("L2a") == std::string::npos); // should be dropped
446  TEST_ASSERT(os.str().find("L2b") != std::string::npos); // should be printed
447  TEST_ASSERT(os.str().find("L1b") == std::string::npos); // should be dropped
448  }
449  }
450 
451  out << "\n### Printing aligned_column with timers names on right ###" << std::endl;
452  options.align_columns = false;
453  options.print_names_before_values = false;
454  timer.report(out, comm, options);
455  {
456  std::ostringstream os;
457  timer.report(os, comm, options);
458  if (myRank == 0) {
459  TEST_ASSERT(os.str().find("L2a") == std::string::npos); // should be dropped
460  TEST_ASSERT(os.str().find("L2b") != std::string::npos); // should be printed
461  TEST_ASSERT(os.str().find("L1b") == std::string::npos); // should be dropped
462  }
463  }
464 }
465 
466 TEUCHOS_UNIT_TEST(StackedTimer, proc_minmax)
467 {
468 
469  Teuchos::StackedTimer timer("L0");
470  timer.stopBaseTimer();
471 
473  if (comm->getSize() < 2)
474  return;
475  const int myRank = Teuchos::rank(*comm);
476 
477  if (myRank == 0)
478  const_cast<Teuchos::BaseTimer*>(timer.findBaseTimer("L0"))->setAccumulatedTime(1.0);
479  else if (myRank == 1)
480  const_cast<Teuchos::BaseTimer*>(timer.findBaseTimer("L0"))->setAccumulatedTime(5.0);
481  else
482  const_cast<Teuchos::BaseTimer*>(timer.findBaseTimer("L0"))->setAccumulatedTime(2.0);
483 
485 
486  out << "\n### Printing default report ###" << std::endl;
487  options.output_minmax=true;
488  options.output_proc_minmax=true;
489  options.output_histogram=true;
490  options.num_histogram=3;
491  options.output_fraction=true;
492  timer.report(out, comm, options);
493  {
494  std::ostringstream os;
495  timer.report(os, comm, options);
496  if (myRank == 0) {
497  TEST_ASSERT(os.str().find("proc min=0") != std::string::npos);
498  TEST_ASSERT(os.str().find("proc max=1") != std::string::npos);
499  }
500  }
501 }
502 
503 
504 // Overlapping timers are not allowed in a StackedTimer, but are in
505 // TimeMonitor. Since StackedTimer is automatically used in
506 // TimeMonitor by default, we have seen this error - a throw from the
507 // stacked timer. In every instance so far, the intention was not to
508 // actually overlap but a constructor/destructor ordering issue
509 // (usually involving RCPs). To prevent tests from failing,
510 // StackedTimer now automatically shuts itself off if it detects
511 // overlaped timers in a TimeMonitor instance, reports a warning on
512 // how to fix and allows the code to continue runnning. Where this has
513 // occurred in Trilinos is when a TimeMonitor object is stored in an
514 // RCP and then the RCP is reassigned to a new timer. The intention
515 // was to stop one and start another. But the destruction of one and
516 // the creation of the new one occurs in the wrong order. This test
517 // demonstrates the issue.
518 TEUCHOS_UNIT_TEST(StackedTimer, OverlappingTimersException)
519 {
520  Teuchos::StackedTimer timer("My Timer");
521  timer.start("Outer");
522  timer.start("Inner");
523  // Should stop inner before outer
524  TEST_THROW(timer.stop("Outer"),std::runtime_error);
525  timer.stop("Inner");
526  timer.stop("Outer");
527  timer.stopBaseTimer();
528 }
529 
530 
531 #ifdef HAVE_TEUCHOS_ADD_TIME_MONITOR_TO_STACKED_TIMER
532 TEUCHOS_UNIT_TEST(StackedTimer, OverlappingTimersViaRCP)
533 {
534  const auto precTimer = Teuchos::TimeMonitor::getNewTimer("Prec");
535  const auto gmresTimer = Teuchos::TimeMonitor::getNewTimer("GMRES");
536 
538  timer = Teuchos::rcp(new Teuchos::TimeMonitor(*gmresTimer));
539 
541 }
542 #endif
543 
544 // Use our own main to initialize kokkos before calling
545 // runUnitTestsFromMain(). The kokkos space_time_stack profiler seg
546 // faults due to inconsistent push/pop of timers in the teuchos unit
547 // test startup code. By calling initialize here we can use the
548 // space_time_stack profiler with this unit test.
549 int main( int argc, char* argv[] )
550 {
551  // Note that the dtor for GlobalMPISession will call
552  // Kokkos::finalize().
553  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
554 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
555  Kokkos::initialize(argc,argv);
556 #endif
557  {
558  Teuchos::FancyOStream out(Teuchos::rcpFromRef(std::cout));
559  out.setOutputToRootOnly(0);
560  }
562 
563  auto return_val = Teuchos::UnitTestRepository::runUnitTestsFromMain(argc, argv);
564 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
565  if (Kokkos::is_initialized())
566  Kokkos::finalize();
567 #endif
568  return return_val;
569 }
570 
571 // gcc 4.X is incomplete in c++11 standard - missing
572 // std::put_time. We'll disable this feature for gcc 4.
573 #if !defined(__GNUC__) || ( defined(__GNUC__) && (__GNUC__ > 4) )
574 TEUCHOS_UNIT_TEST(StackedTimer, VerboseTimestamps) {
575 
576  Teuchos::StackedTimer timer("My Timer");
577 
578  timer.enableVerbose(true);
579  timer.enableVerboseTimestamps(2);
580  std::ostringstream os;
581  timer.setVerboseOstream(Teuchos::rcpFromRef(os));
582 
583  timer.start("L1");
584  timer.start("L2");
585  timer.start("L3");
586  timer.stop("L3");
587  timer.stop("L2");
588  timer.stop("L1");
589  timer.stopBaseTimer();
590 
591  out << os.str() << std::endl;
592 
593  TEST_ASSERT(os.str().find("TIMESTAMP:"));
594 
595  // Printing restricted to first two levels, thrid level should not
596  // be printed.
597  TEST_ASSERT(os.str().find("L1") != std::string::npos);
598  TEST_ASSERT(os.str().find("L2") != std::string::npos);
599  TEST_ASSERT(os.str().find("L3") == std::string::npos);
600 }
601 #endif
602 
603 // Tests that we can turn off timers for regions of asychronous
604 // execution.
605 TEUCHOS_UNIT_TEST(StackedTimer, DisableTimers)
606 {
607  Teuchos::StackedTimer timer("My New Timer");
608  timer.start("Total Time");
609  {
610  for (int i=0; i < 10; ++i) {
611 
612  timer.start("Assembly");
613  timer.stop("Assembly");
614 
615  // Async execution means the timers will stop out of order. Out
616  // of order timers causes exception to be thrown.
617 
618  timer.disableTimers(); // Stop recording timers
619  timer.start("Solve");
620  {
621  timer.start("Prec");
622 
623  // This stop() is out of order and would trigger an exception
624  // if we did not disable the timers above.
625  timer.stop("Solve");
626 
627  timer.stop("Prec");
628  }
629  timer.enableTimers(); // Start recording timers
630 
631  // Make sure the timers are reenabled
632  timer.start("Restarted");
633  timer.stop("Restarted");
634  }
635  }
636  timer.stop("Total Time");
637  timer.stopBaseTimer();
638 
639  TEST_EQUALITY((timer.findTimer("My New Timer@Total Time")).count, 1);
640  TEST_EQUALITY((timer.findTimer("My New Timer@Total Time@Assembly")).count, 10);
641  TEST_EQUALITY((timer.findTimer("My New Timer@Total Time@Restarted")).count, 10);
642  // Should not exist since we disabled the timers
643  TEST_THROW(timer.findTimer("My New Timer@Total Time@Solve"),std::runtime_error);
644  TEST_THROW(timer.findTimer("My New Timer@Total Time@Solve@Prec"),std::runtime_error);
645 }
void setVerboseOstream(const Teuchos::RCP< std::ostream > &os)
Set the ostream for verbose mode(defaults to std::cout).
static Teuchos::RCP< Teuchos::StackedTimer > getStackedTimer()
The StackedTimer used by the TimeMonitor.
#define TEST_ASSERT(v1)
Assert the given statement is true.
void stop(const std::string &name, const bool pop_kokkos_profiling_region=true)
void enableVerboseTimestamps(const unsigned levels)
Enable timestamps in verbose mode for the number of levels specified.
void enableVerbose(const bool enable_verbose)
If set to true, print timer start/stop to verbose ostream.
#define TEST_EQUALITY(v1, v2)
Assert the equality of v1 and v2.
#define TEST_THROW(code, ExceptType)
Assert that the statement &#39;code&#39; throws the exception &#39;ExceptType&#39; (otherwise the test fails)...
#define TEUCHOS_UNIT_TEST(TEST_GROUP, TEST_NAME)
Macro for defining a (non-templated) unit test.
static Teuchos::RCP< const Comm< OrdinalType > > getComm()
Return the default global communicator.
Initialize, finalize, and query the global MPI session.
bool is_null(const ArrayRCP< T > &p)
Returns true if p.get()==NULL.
static RCP< Time > getNewTimer(const std::string &name)
Return a new timer with the given name (class method).
Unit testing support.
static int runUnitTestsFromMain(int argc, char *argv[])
Run the unit tests from main() passing in (argc, argv).
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
void start(const std::string name, const bool push_kokkos_profiling_region=true)
std::ostream subclass that performs the magic of indenting data sent to an std::ostream object among ...
The basic timer used internally, uses std::chrono::high_resolution_clock.
Unit testing support.
void reportXML(std::ostream &os, const std::string &datestamp, const std::string &timestamp, Teuchos::RCP< const Teuchos::Comm< int > > comm)
static void setStackedTimer(const Teuchos::RCP< Teuchos::StackedTimer > &t)
Sets the StackedTimer into which the TimeMonitor will insert timings.
static void setGloballyReduceTestResult(const bool globallyReduceUnitTestResult)
Set if the unit tests should reduce pass/fail across processes.
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
Set the stream to print only on the (MPI) process with the given rank.
int size(const Comm< Ordinal > &comm)
Get the number of processes in the communicator.
const BaseTimer * findBaseTimer(const std::string &name) const
void unsortedMergePair(const Array< std::string > &localNames, Array< std::string > &globalNames, const ECounterSetOp setOp)
#define TEST_FLOATING_EQUALITY(v1, v2, tol)
Assert the relative floating-point equality of rel_error(v1,v2) &lt;= tol.
int main(int argc, char *argv[])
void push_back(const value_type &x)
A MPI utilities class, providing methods for initializing, finalizing, and querying the global MPI se...
void report(std::ostream &os)
size_type size() const
Scope guard for Teuchos::Time, with MPI collective timer reporting.
Smart reference counting pointer class for automatic garbage collection.
BaseTimer::TimeInfo findTimer(const std::string &name)
This class allows one to push and pop timers on and off a stack.
Common capabilities for collecting and reporting performance data collectively across MPI processes...
Scope guard for Time, that can compute MPI collective timer statistics.
bool nonnull(const ArrayRCP< T > &p)
Returns true if p.get()!=NULL.