Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
Teuchos_StackedTimer.hpp
Go to the documentation of this file.
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"
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 
51 
53  void start(){
54  if (running_)
55  error_out("Base_Timer:start Failed timer already running");
56  start_time_ = Clock::now();
57 
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) {
90  } else {
91  return 0;
92  }
93  }
94 
95 
104  if (count_started_> 0) {
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;
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){}
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_;
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) :
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 {
509  output_minmax(false), num_histogram(10), max_levels(INT_MAX),
510  print_warnings(true) {}
518  };
519 
525  void report(std::ostream &os, Teuchos::RCP<const Teuchos::Comm<int> > comm, OutputOptions options = OutputOptions());
526 
527 
528 protected:
533 
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 */
void setAccumulatedTime(double accum=0)
Setter for accumulated time.
double accumulatedTimePerTimerCall(const std::string &name="")
Clock::time_point start_time_
void splitString(const std::string &locate_name, std::string &first_name, std::string &second_name)
split a string into two parts split by a &#39;@&#39; if no &#39;@&#39; first gets the full string ...
void addTimerNames(Array< std::string > &names, unsigned &pos)
double accumulatedTimePerUpdate() const
return the average time per item updated
void merge(Teuchos::RCP< const Teuchos::Comm< int > > comm)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
Teuchos header file which uses auto-configuration information to include necessary C++ headers...
double accumulatedTime() const
Get the total accumulated time since last reset or construction when the timer is running...
void start()
Start a currently stopped timer.
StackedTimer(const char *name)
LevelTimer * top_
Current level running.
unsigned long incrementCount(unsigned long count=1)
Increment the total number of items updated between a start stop.
double accumulatedTimePerUpdate(const std::string &name="")
BaseTimer::TimeInfo findTimer(const std::string &name, bool &found)
double printLevel(std::string prefix, int level, std::ostream &os, std::vector< bool > &printed, double parent_time, const OutputOptions &options)
unsigned long totalUpdates() const
LevelTimer * unpack(unsigned from)
double accumulatedTime(const std::string &name="")
double accumulatedTime(const std::string &locate_name="")
the basic timer used elsewhere, uses MPI_Wtime for time
void start(const std::string name)
double difference(const BaseTimer &from) const
Return the difference between two timers in seconds,.
Array< Array< int > > hist_
double accumulatedTimePerTimerCall() const
return the average time per timer start/stop
void collectRemoteData(Teuchos::RCP< const Teuchos::Comm< int > > comm, const OutputOptions &options)
std::chrono::high_resolution_clock Clock
LevelTimer(const LevelTimer &src)
Copy constructor.
Array< unsigned long long > updates_
Timer info at a given level and all the children.
double accumulatedTimePerUpdate(const std::string &locate_name="")
LevelTimer timer_
Base timer.
double accumulatedTimePerTimerCall(const std::string &locate_name="")
Templated array class derived from the STL std::vector.
void stop(const std::string &name="RootTimer")
void error_out(const std::string &msg, const bool)
Error reporting function for stacked timer.
Abstract interface for distributed-memory communication.
LevelTimer * stop(const std::string &name="RootTimer")
void reset()
Reset all the timer stats, throws if it is already running.
Array< std::string > flat_names_
void stop()
Stop a current running timer and accumulate time difference.
void report(std::ostream &os)
LevelTimer()
Default constructor, shouldn&#39;t be used but needed for std::vector.
unsigned long long count_updates_
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.
Provides common capabilities for collecting and reporting performance data across processors...
Array< unsigned long > count_
LevelTimer(int level, const char *name="RootTimer", LevelTimer *parent=NULL, bool start_timer=true)
Struct for controlling output options like histograms.
Reference-counted pointer class and non-member templated function implementations.
LevelTimer * start(const char *sub_name)