MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_MutuallyExclusiveTime.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // MueLu: A package for multigrid based preconditioning
4 //
5 // Copyright 2012 NTESS and the MueLu contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #include <map>
11 #include <iostream> // for basic_ostream, etc
12 #include <utility> // for pair
13 #include "Teuchos_FancyOStream.hpp" // for basic_FancyOStream, etc
14 #include "Teuchos_RCP.hpp" // for RCP::operator->, etc
15 #include "Teuchos_TestForException.hpp" // for TEUCHOS_TEST_FOR_EXCEPTION
16 #include "Teuchos_Time.hpp"
17 #include "Teuchos_TimeMonitor.hpp"
18 #include "MueLu_ConfigDefs.hpp"
19 #include "MueLu_Exceptions.hpp"
20 #include "MueLu_BaseClass.hpp"
21 #include "MueLu_VerbosityLevel.hpp" // for MsgType::Debug, etc
23 #include "MueLu_FactoryBase.hpp"
24 #include "MueLu_Level.hpp"
25 
26 namespace MueLu {
27 
28 std::map<std::string, std::string> myParent_;
29 
30 template <class TagName>
31 MutuallyExclusiveTime<TagName>::MutuallyExclusiveTime(const std::string& name, bool startFlag)
32  : name_(name)
33  , timer_(rcp(new Teuchos::Time(name, false)))
34  , // second argument is false in any case, because if start==true,
35  // timer has to be started by MutuallyExclusiveTime::start() instead of Teuchos::Time::start().
36  isPaused_(false) {
37  if (startFlag == true) timer_->start();
38 }
39 
40 template <class TagName>
42  // This timer can only be destroyed if it is not in the stack
43  if (isPaused()) {
44  // error message because cannot throw an exception in destructor
45  GetOStream(Errors) << "MutuallyExclusiveTime::~MutuallyExclusiveTime(): Error: destructor called on a paused timer." << std::endl;
46  // TODO: Even if timing results will be wrong, the timer can be removed from the stack to avoid a segmentation fault.
47  }
48 
49  stop(); // if isRunning(), remove from the stack, resume previous timer
50 }
51 
52 template <class TagName>
54  TEUCHOS_TEST_FOR_EXCEPTION(isPaused(), Exceptions::RuntimeError, "MueLu::MutuallyExclusiveTime::start(): timer is paused. Use resume().");
55 
56  if (isRunning()) {
57  return;
58  } // If timer is already running, do not pause/push-in-the-stack/start the timer.
59  // Otherwise, something bad will happen when this.stop() will be called
60 
61  // pause currently running timer
62  if (!timerStack_.empty()) {
63  GetOStream(Debug) << "pausing parent timer " << timerStack_.top()->name_ << std::endl;
64  timerStack_.top()->pause();
65  GetOStream(Debug) << "starting child timer " << this->name_ << std::endl;
66  myParent_[this->name_] = timerStack_.top()->name_;
67  } else {
68  GetOStream(Debug) << "starting orphan timer " << this->name_ << std::endl;
69  myParent_[this->name_] = "no parent";
70  }
71 
72  // start this timer
73  timer_->start(reset);
74  timerStack_.push(this);
75 }
76 
77 template <class TagName>
79  if (isPaused())
80  GetOStream(Errors) << "MueLu::MutuallyExclusiveTime::stop(): timer is paused. Use resume()" << std::endl;
81 
82  if (!isRunning()) {
83  return timer_->stop();
84  } // stop() can be called on stopped timer
85 
86  // Here, timer is running, so it is the head of the stack
87  TopOfTheStack();
88 
89  timerStack_.pop();
90  double r = timer_->stop();
91 
92  if (!timerStack_.empty()) {
93  GetOStream(Debug) << "resuming timer " << timerStack_.top()->name_ << std::endl;
94  timerStack_.top()->resume();
95  }
96 
97  return r;
98 }
99 
100 template <class TagName>
102  if (isPaused()) // calling twice pause() is allowed
103  return;
104 
105  TopOfTheStack();
106 
107  timer_->stop();
108  isPaused_ = true;
109 }
110 
111 template <class TagName>
113  TopOfTheStack();
114 
115  // no 'shortcut' test necessary:
116  // - if timer is stop, it is in pause (cannot be stop and not in pause because this timer is the head of the stack).
117  // - if timer is running, nothing is changed by this function.
118 
119  timer_->start(false);
120  isPaused_ = false;
121 }
122 
123 template <class TagName>
125  if (timer_->isRunning()) {
126  // TEUCHOS_TEST_FOR_EXCEPTION(timerStack_.top() != this, Exceptions::RuntimeError,
127  // "MueLu::MutuallyExclusiveTime::isRunning(): this timer is active so it is supposed to be the head of the stack");
128  }
129  return timer_->isRunning();
130 }
131 
132 template <class TagName>
134  TEUCHOS_TEST_FOR_EXCEPTION(isPaused_ && timer_->isRunning(), Exceptions::RuntimeError, "");
135  return isPaused_;
136 }
137 
138 template <class TagName>
141  timer->name_ = name;
142  return timer;
143 }
144 
145 template <class TagName>
146 void MutuallyExclusiveTime<TagName>::incrementNumCalls() { timer_->incrementNumCalls(); }
147 
148 template <class TagName>
150  // key is child, value is parent
151  RCP<Teuchos::FancyOStream> fos = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
152  fos->setOutputToRootOnly(0);
153  *fos << "Parent Child Map" << std::endl;
154  std::map<std::string, std::string>::const_iterator iter;
155  for (iter = ::MueLu::myParent_.begin(); iter != ::MueLu::myParent_.end(); ++iter) {
156  *fos << "Key: " << iter->first << " Value: " << iter->second << std::endl;
157  }
158 }
159 
160 template <class TagName>
162  : timer_(timer)
163  , isPaused_(false) {}
164 
165 template <class TagName>
167  TEUCHOS_TEST_FOR_EXCEPTION(timerStack_.empty(), Exceptions::RuntimeError, "MueLu::MutuallyExclusiveTime::TopOfTheStack(): timer is not the head of the stack (stack is empty).");
168  // TEUCHOS_TEST_FOR_EXCEPTION(timerStack_.top() != this, Exceptions::RuntimeError, "MueLu::MutuallyExclusiveTime::TopOfTheStack(): timer is not the head of the stack.");
169  TEUCHOS_TEST_FOR_EXCEPTION(!(isRunning() || isPaused()), Exceptions::RuntimeError, "MueLu::MutuallyExclusiveTime::TopOfTheStack(): head of the stack timer is neither active nor paused.");
170 }
171 
172 template <class TagName>
173 std::stack<MutuallyExclusiveTime<TagName>*> MutuallyExclusiveTime<TagName>::timerStack_;
174 
175 // FIXME: move this:
177 template class MutuallyExclusiveTime<Level>;
178 template class MutuallyExclusiveTime<BaseClass>;
179 
180 } // namespace MueLu
void TopOfTheStack()
Check if &#39;this&#39; is the head of the stack.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Print additional debugging information.
static RCP< MutuallyExclusiveTime< TagName > > getNewTimer(const std::string &name)
Return a new MutuallyExclusiveTime that is registered with the Teuchos::TimeMonitor (for timer summar...
static void PrintParentChildPairs()
Print std::map of (child,parent) pairs for post-run analysis.
void start(bool reset=false)
Starts the timer. If a MutuallyExclusiveTime timer is running, it will be stopped.
static RCP< Time > getNewTimer(const std::string &name)
double stop()
Stops the timer. The previous MutuallyExclusiveTime that has been paused when this timer was started ...
void start(bool reset=false)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void incrementNumCalls()
Increment the number of times this timer has been called.
RCP< Teuchos::Time > timer_
Using an RCP allows to use Teuchos::TimeMonitor to keep track of the timer.
std::map< std::string, std::string > myParent_
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
void pause()
Pause running timer. Used internally by start().
TransListIter iter
void resume()
Resume paused timer. Used internally by stop(). Timer is not reset.
This class wraps a Teuchos::Time and maintains a mutually exclusive property between wrapped timers...
Exception throws to report errors in the internal logical of the program.
void stop()
MutuallyExclusiveTime(const std::string &name, bool startFlag=false)
Constructor.