Teuchos - Trilinos Tools Package  Version of the Day
Teuchos_StackedTimer.hpp
1 // @HEADER BEGIN
2 // @HEADER END
3 
4 #ifndef TEUCHOS_STACKED_TIMER_HPP
5 #define TEUCHOS_STACKED_TIMER_HPP
6 
7 #include "Teuchos_ConfigDefs.hpp"
8 #include "Teuchos_Comm.hpp"
9 #include "Teuchos_DefaultComm.hpp"
10 #include "Teuchos_CommHelpers.hpp"
11 #include "Teuchos_RCP.hpp"
12 #include "Teuchos_Array.hpp"
14 #include <string>
15 #include <vector>
16 #include <cassert>
17 #include <chrono>
18 #include <climits>
19 
20 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOSCORE)
21 namespace Kokkos {
22 namespace Profiling {
23 extern void pushRegion (const std::string&);
24 extern void popRegion ();
25 } // namespace Profiling
26 } // namespace Kokkos
27 #endif
28 
29 
30 namespace Teuchos {
31 
33 void error_out(const std::string& msg, const bool fail_all = false);
34 
44 class BaseTimer {
45 
46 public:
47 
48  using Clock = std::chrono::high_resolution_clock;
49 
50  BaseTimer() : accumulation_(0.0), count_started_(0), count_updates_(0), running_(false) {}
51 
53  void start(){
54  if (running_)
55  error_out("Base_Timer:start Failed timer already running");
56  start_time_ = Clock::now();
57 
58  count_started_++;
59  running_ = true;
60  }
61 
63  void stop(){
64  if (!running_)
65  error_out("Base_Timer:stop Failed timer not running");
66  accumulation_ += std::chrono::duration_cast<std::chrono::duration<double>>(Clock::now() - start_time_).count();
67  running_ = false;
68  }
69 
71  unsigned long incrementCount(unsigned long count=1) {count_updates_ += count; return count_updates_;}
72 
74  double accumulatedTime() const {return accumulation_;}
75 
77  void setAccumulatedTime(double accum=0) {accumulation_=accum;}
78  double accumulatedTimePerUpdate()const {
88  if (count_updates_ > 0) {
89  return accumulation_/count_updates_;
90  } else {
91  return 0;
92  }
93  }
94 
95 
104  if (count_started_> 0) {
105  return accumulation_/count_started_;
106  } else {
107  return 0;
108  }
109  }
110 
117  double difference(const BaseTimer &from) const {
118  return accumulation_ - from.accumulation_;
119  }
120 
122  void reset() {
123  if (running_)
124  error_out("BaseTimer, cannot reset a running timer");
125  accumulation_=0.0;
126  count_started_ = count_updates_ = 0;
127  }
128 
129  unsigned long totalUpdates()const {return count_updates_;}
130 
131  bool running() const { return running_;}
132 
133  struct TimeInfo {
134  TimeInfo():time(0.0), count(0), updates(0), running(false){}
135  TimeInfo(BaseTimer* t): time(t->accumulation_), count(t->count_started_), updates(t->count_updates_), running(t->running()) {}
136  double time;
137  unsigned long count;
138  unsigned long long updates;
139  bool running;
140  };
141 
142 protected:
143  double accumulation_; // total time
144  unsigned long count_started_; // Number of times this timer has been started
145  unsigned long long count_updates_; // Total count of items updated during this timer
146  Clock::time_point start_time_;
147  bool running_;
148 
149  friend struct TimeInfo;
150 };
151 
170 {
171 protected:
172 
181  class LevelTimer : public BaseTimer {
182  protected:
183 
184  // TODO: implement operator=
185 
186  unsigned level_;
187  std::string name_;
188  LevelTimer *parent_;
189  std::vector<LevelTimer> sub_timers_;
190  public:
192  LevelTimer();
193 
201  LevelTimer(int level,
202  const char* name = "RootTimer",
203  LevelTimer *parent=NULL,
204  bool start_timer=true) :
205  BaseTimer(),
206  level_(level),
207  name_(name),
208  parent_(parent)
209  {
210  if ( start_timer )
212 
213  }
214 
216  LevelTimer(const LevelTimer &src) :
217  BaseTimer(src), level_(src.level_), name_(src.name_),parent_(src.parent_), sub_timers_(src.sub_timers_)
218  {
219  for (unsigned i=0;i<sub_timers_.size();++i)
220  sub_timers_[i].parent_ = this;
221  }
222 
228  LevelTimer* start(const char* sub_name) {
229  for (unsigned i=0;i<sub_timers_.size();i++ )
230  if (sub_name == sub_timers_[i].name_ ) {
231  sub_timers_[i].BaseTimer::start();
232  return &sub_timers_[i];
233  }
234  sub_timers_.push_back(LevelTimer(level_+1,sub_name,this,true));
235  return &sub_timers_[sub_timers_.size()-1];
236  }
237 
245  LevelTimer* stop(const std::string &name = "RootTimer") {
246  if (name != name_)
247  error_out("Stopping timer "+name+" But top level running timer is "+name_);
248  BaseTimer::stop();
249  return parent_;
250  }
251 
252 
257  std::string get_full_name() {
258  std::string parent_name("");
259  if ((parent_ != NULL) && (parent_->level_ > 0))
260  parent_name = parent_->get_full_name() + "@";
261 
262  std::string my_name(name_);
263 
264  std::string full_name = parent_name + my_name;
265  return full_name;
266  }
267 
273  int countTimers() {
274  int count=1;
275  for (unsigned i=0;i<sub_timers_.size(); ++i)
276  count += sub_timers_[i].countTimers();
277  return count;
278  }
279 
280  void addTimerNames(Array<std::string> &names, unsigned &pos) {
281  names[pos++] = get_full_name();
282  for (unsigned i=0;i<sub_timers_.size(); ++i)
283  sub_timers_[i].addTimerNames(names, pos);
284  }
285 
291  double accumulatedTime(const std::string &locate_name="") {
292 
293  if (locate_name == "")
295 
296  std::string first_name,second_name;
297 
298  size_t i = locate_name.find_first_of('@');
299  if ( i >= locate_name.size() ) {
300  first_name = locate_name;
301  second_name = "";
302  } else {
303  first_name.assign(locate_name,0,i);
304  second_name.assign(locate_name,i+1,locate_name.size()-i-1);
305  }
306  for (unsigned j=0;j<sub_timers_.size();++j)
307  if ( first_name == sub_timers_[j].name_)
308  return sub_timers_[j].accumulatedTime(second_name);
309  return 0;
310  }
311 
312  protected:
319  void splitString(const std::string &locate_name, std::string &first_name, std::string &second_name) {
320  size_t i = locate_name.find_first_of('@');
321  if ( i >= locate_name.size() ) {
322  first_name = locate_name;
323  second_name = "";
324  } else {
325  first_name.assign(locate_name,0,i);
326  second_name.assign(locate_name,i+1,locate_name.size()-i-1);
327  }
328  }
329 
330  public:
336  double accumulatedTimePerUpdate(const std::string &locate_name="") {
337 
338  if (locate_name == "")
340 
341  std::string first_name,second_name;
342  splitString(locate_name, first_name, second_name);
343 
344  for (unsigned j=0;j<sub_timers_.size();j++)
345  if ( first_name == sub_timers_[j].name_)
346  return sub_timers_[j].accumulatedTimePerUpdate(second_name);
347  return 0;
348  }
349 
355  double accumulatedTimePerTimerCall(const std::string &locate_name="") {
356 
357  if (locate_name == "")
359 
360  std::string first_name,second_name;
361  splitString(locate_name, first_name, second_name);
362 
363  for (unsigned j=0;j<sub_timers_.size();j++)
364  if ( first_name == sub_timers_[j].name_)
365  return sub_timers_[j].accumulatedTimePerTimerCall(second_name);
366  return 0;
367  }
368 
372  void pack();
373 
379  LevelTimer* unpack(unsigned from);
380 
385  void report(std::ostream &os);
386 
393  BaseTimer::TimeInfo findTimer(const std::string &name,bool& found);
394 
395  protected:
396 
397 
398  }; // LevelTimer
399 
400 
401 
402 
403 public:
408  explicit StackedTimer(const char *name) :timer_(0,name,NULL,true) {top_ = &timer_;}
409  // ~StackedTimer();
413  void start() {
414  timer_.BaseTimer::start();
415 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOSCORE)
416  ::Kokkos::Profiling::pushRegion("ANONYMOUS");
417 #endif
418 }
423  void start(const std::string name) {
424  if (top_ == NULL)
425  top_ = timer_.start(name.c_str());
426  else
427  top_ = top_->start(name.c_str());
428 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOSCORE)
429  ::Kokkos::Profiling::pushRegion(name);
430 #endif
431  }
432 
436  void stop(const std::string &name = "RootTimer") {
437  if (top_)
438  top_ = top_->stop(name);
439  else
440  timer_.BaseTimer::stop( );
441 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOSCORE)
442  ::Kokkos::Profiling::popRegion();
443 #endif
444  }
445 
450  void incrementCount(int i) {
451  top_->incrementCount(i);
452  }
453 
459  double accumulatedTime(const std::string &name=""){
460  if (top_) // Top is null for the head node when nothing is running
461  return top_->accumulatedTime(name);
462  else
463  return timer_.accumulatedTime(name);
464  }
465 
471  double accumulatedTimePerUpdate(const std::string &name="") {
472  if (top_) // Top is null for the head node when nothing is running
473  return top_->accumulatedTimePerUpdate(name);
474  else
475  return timer_.accumulatedTimePerUpdate(name);
476  }
482  double accumulatedTimePerTimerCall(const std::string &name="") {
483  if (top_) // Top is null for the head node when nothing is running
484  return top_->accumulatedTimePerTimerCall(name);
485  else
486  return timer_.accumulatedTimePerTimerCall(name);
487  }
488 
494  BaseTimer::TimeInfo findTimer(const std::string &name) {
495  bool foundTimer = false;
496  const auto timeInfo = timer_.findTimer(name,foundTimer);
497  TEUCHOS_TEST_FOR_EXCEPTION(!foundTimer, std::runtime_error,
498  "StackedTimer::findTimer() failed to find a timer named \"" << name << "\"!\n");
499  return timeInfo;
500  }
501 
502  void report(std::ostream &os) {
503  timer_.report(os);
504  }
505 
507  struct OutputOptions {
508  OutputOptions() : output_fraction(false), output_total_updates(false), output_histogram(false),
509  output_minmax(false), num_histogram(10), max_levels(INT_MAX),
510  print_warnings(true) {}
511  bool output_fraction;
512  bool output_total_updates;
513  bool output_histogram;
514  bool output_minmax;
515  int num_histogram;
516  int max_levels;
517  bool print_warnings;
518  };
519 
525  void report(std::ostream &os, Teuchos::RCP<const Teuchos::Comm<int> > comm, OutputOptions options = OutputOptions());
526 
527 
528 protected:
533 
534  Array<std::string> flat_names_;
535  Array<double> min_;
536  Array<double> max_;
537  Array<double> sum_;
538  Array<double> sum_sq_;
539  Array<Array<int>> hist_;
540  Array<unsigned long> count_;
541  Array<unsigned long long> updates_;
542  Array<int> active_;
543 
547  void flatten();
548 
553  void merge(Teuchos::RCP<const Teuchos::Comm<int> > comm);
554 
558  void collectRemoteData(Teuchos::RCP<const Teuchos::Comm<int> > comm, const OutputOptions &options );
559 
563  double printLevel(std::string prefix, int level, std::ostream &os, std::vector<bool> &printed,
564  double parent_time, const OutputOptions &options);
565 
566 }; //StackedTimer
567 
568 
569 } //namespace Teuchos
570 
571 #endif /* TEUCHOS_STACKED_TIMER_HPP */
Teuchos_RCP.hpp
Reference-counted pointer class and non-member templated function implementations.
Teuchos::StackedTimer::LevelTimer
Timer info at a given level and all the children.
Definition: Teuchos_StackedTimer.hpp:181
Teuchos::BaseTimer
the basic timer used elsewhere, uses MPI_Wtime for time
Definition: Teuchos_StackedTimer.hpp:44
Teuchos::StackedTimer::LevelTimer::start
LevelTimer * start(const char *sub_name)
Definition: Teuchos_StackedTimer.hpp:228
Teuchos::StackedTimer::top_
LevelTimer * top_
Current level running.
Definition: Teuchos_StackedTimer.hpp:530
Teuchos::StackedTimer::LevelTimer::stop
LevelTimer * stop(const std::string &name="RootTimer")
Definition: Teuchos_StackedTimer.hpp:245
Teuchos::BaseTimer::setAccumulatedTime
void setAccumulatedTime(double accum=0)
Setter for accumulated time.
Definition: Teuchos_StackedTimer.hpp:77
Teuchos_PerformanceMonitorBase.hpp
Provides common capabilities for collecting and reporting performance data across processors.
Teuchos::BaseTimer::difference
double difference(const BaseTimer &from) const
Return the difference between two timers in seconds,.
Definition: Teuchos_StackedTimer.hpp:117
Teuchos::StackedTimer::printLevel
double printLevel(std::string prefix, int level, std::ostream &os, std::vector< bool > &printed, double parent_time, const OutputOptions &options)
Definition: Teuchos_StackedTimer.cpp:167
Teuchos::StackedTimer::incrementCount
void incrementCount(int i)
Definition: Teuchos_StackedTimer.hpp:450
Teuchos::StackedTimer::LevelTimer::LevelTimer
LevelTimer()
Default constructor, shouldn't be used but needed for std::vector.
Definition: Teuchos_StackedTimer.cpp:11
Teuchos::StackedTimer::start
void start()
Definition: Teuchos_StackedTimer.hpp:413
Teuchos_Array.hpp
Templated array class derived from the STL std::vector.
Teuchos::StackedTimer::LevelTimer::countTimers
int countTimers()
Definition: Teuchos_StackedTimer.hpp:273
Teuchos::StackedTimer::LevelTimer::accumulatedTimePerUpdate
double accumulatedTimePerUpdate(const std::string &locate_name="")
Definition: Teuchos_StackedTimer.hpp:336
Teuchos::StackedTimer::merge
void merge(Teuchos::RCP< const Teuchos::Comm< int > > comm)
Definition: Teuchos_StackedTimer.cpp:65
Teuchos::StackedTimer::StackedTimer
StackedTimer(const char *name)
Definition: Teuchos_StackedTimer.hpp:408
Teuchos::StackedTimer::accumulatedTimePerUpdate
double accumulatedTimePerUpdate(const std::string &name="")
Definition: Teuchos_StackedTimer.hpp:471
Teuchos::StackedTimer::start
void start(const std::string name)
Definition: Teuchos_StackedTimer.hpp:423
Teuchos::RCP
Smart reference counting pointer class for automatic garbage collection.
Definition: Teuchos_RCPDecl.hpp:429
Teuchos::BaseTimer::stop
void stop()
Stop a current running timer and accumulate time difference.
Definition: Teuchos_StackedTimer.hpp:63
Teuchos::Array< std::string >
Teuchos::StackedTimer::LevelTimer::get_full_name
std::string get_full_name()
Definition: Teuchos_StackedTimer.hpp:257
Teuchos::BaseTimer::accumulatedTimePerTimerCall
double accumulatedTimePerTimerCall() const
return the average time per timer start/stop
Definition: Teuchos_StackedTimer.hpp:103
Teuchos::StackedTimer::timer_
LevelTimer timer_
Base timer.
Definition: Teuchos_StackedTimer.hpp:532
Teuchos::BaseTimer::reset
void reset()
Reset all the timer stats, throws if it is already running.
Definition: Teuchos_StackedTimer.hpp:122
Teuchos::error_out
void error_out(const std::string &msg, const bool)
Error reporting function for stacked timer.
Definition: Teuchos_StackedTimer.cpp:15
Teuchos::StackedTimer::stop
void stop(const std::string &name="RootTimer")
Definition: Teuchos_StackedTimer.hpp:436
Teuchos::BaseTimer::incrementCount
unsigned long incrementCount(unsigned long count=1)
Increment the total number of items updated between a start stop.
Definition: Teuchos_StackedTimer.hpp:71
Teuchos::StackedTimer::LevelTimer::splitString
void splitString(const std::string &locate_name, std::string &first_name, std::string &second_name)
split a string into two parts split by a '@' if no '@' first gets the full string
Definition: Teuchos_StackedTimer.hpp:319
Teuchos::StackedTimer::LevelTimer::LevelTimer
LevelTimer(int level, const char *name="RootTimer", LevelTimer *parent=NULL, bool start_timer=true)
Definition: Teuchos_StackedTimer.hpp:201
Teuchos::StackedTimer::accumulatedTime
double accumulatedTime(const std::string &name="")
Definition: Teuchos_StackedTimer.hpp:459
Teuchos_ConfigDefs.hpp
Teuchos header file which uses auto-configuration information to include necessary C++ headers.
Teuchos::BaseTimer::accumulatedTime
double accumulatedTime() const
Get the total accumulated time since last reset or construction when the timer is running.
Definition: Teuchos_StackedTimer.hpp:74
Teuchos::StackedTimer::collectRemoteData
void collectRemoteData(Teuchos::RCP< const Teuchos::Comm< int > > comm, const OutputOptions &options)
Definition: Teuchos_StackedTimer.cpp:72
Teuchos::StackedTimer::OutputOptions
Struct for controlling output options like histograms.
Definition: Teuchos_StackedTimer.hpp:507
Teuchos::StackedTimer
This class allows one to push and pop timers on and off a stack.
Definition: Teuchos_StackedTimer.hpp:169
Teuchos::StackedTimer::flatten
void flatten()
Definition: Teuchos_StackedTimer.cpp:57
Teuchos::StackedTimer::LevelTimer::pack
void pack()
Teuchos::StackedTimer::LevelTimer::unpack
LevelTimer * unpack(unsigned from)
Teuchos::StackedTimer::LevelTimer::report
void report(std::ostream &os)
Definition: Teuchos_StackedTimer.cpp:22
Teuchos::Comm
Abstract interface for distributed-memory communication.
Definition: Teuchos_Comm.hpp:85
Teuchos::StackedTimer::LevelTimer::findTimer
BaseTimer::TimeInfo findTimer(const std::string &name, bool &found)
Definition: Teuchos_StackedTimer.cpp:40
Teuchos
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...
Teuchos::StackedTimer::LevelTimer::LevelTimer
LevelTimer(const LevelTimer &src)
Copy constructor.
Definition: Teuchos_StackedTimer.hpp:216
Teuchos::StackedTimer::LevelTimer::accumulatedTime
double accumulatedTime(const std::string &locate_name="")
Definition: Teuchos_StackedTimer.hpp:291
TEUCHOS_TEST_FOR_EXCEPTION
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
Definition: Teuchos_TestForException.hpp:170
Teuchos::BaseTimer::start
void start()
Start a currently stopped timer.
Definition: Teuchos_StackedTimer.hpp:53
Teuchos::StackedTimer::accumulatedTimePerTimerCall
double accumulatedTimePerTimerCall(const std::string &name="")
Definition: Teuchos_StackedTimer.hpp:482
Teuchos::BaseTimer::accumulatedTimePerUpdate
double accumulatedTimePerUpdate() const
return the average time per item updated
Definition: Teuchos_StackedTimer.hpp:87
Teuchos::StackedTimer::LevelTimer::accumulatedTimePerTimerCall
double accumulatedTimePerTimerCall(const std::string &locate_name="")
Definition: Teuchos_StackedTimer.hpp:355
Teuchos::StackedTimer::findTimer
BaseTimer::TimeInfo findTimer(const std::string &name)
Definition: Teuchos_StackedTimer.hpp:494