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