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 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 
47 #include <map>
48 #include <iostream> // for basic_ostream, etc
49 #include <utility> // for pair
50 #include "Teuchos_FancyOStream.hpp" // for basic_FancyOStream, etc
51 #include "Teuchos_RCP.hpp" // for RCP::operator->, etc
52 #include "Teuchos_TestForException.hpp" // for TEUCHOS_TEST_FOR_EXCEPTION
53 #include "Teuchos_Time.hpp"
54 #include "Teuchos_TimeMonitor.hpp"
55 #include "MueLu_ConfigDefs.hpp"
56 #include "MueLu_Exceptions.hpp"
57 #include "MueLu_BaseClass.hpp"
58 #include "MueLu_VerbosityLevel.hpp" // for MsgType::Debug, etc
60 #include "MueLu_FactoryBase.hpp"
61 #include "MueLu_Level.hpp"
62 
63 namespace MueLu {
64 
65 std::map<std::string, std::string> myParent_;
66 
67 template <class TagName>
68 MutuallyExclusiveTime<TagName>::MutuallyExclusiveTime(const std::string& name, bool startFlag)
69  : name_(name)
70  , timer_(rcp(new Teuchos::Time(name, false)))
71  , // second argument is false in any case, because if start==true,
72  // timer has to be started by MutuallyExclusiveTime::start() instead of Teuchos::Time::start().
73  isPaused_(false) {
74  if (startFlag == true) timer_->start();
75 }
76 
77 template <class TagName>
79  // This timer can only be destroyed if it is not in the stack
80  if (isPaused()) {
81  // error message because cannot throw an exception in destructor
82  GetOStream(Errors) << "MutuallyExclusiveTime::~MutuallyExclusiveTime(): Error: destructor called on a paused timer." << std::endl;
83  // TODO: Even if timing results will be wrong, the timer can be removed from the stack to avoid a segmentation fault.
84  }
85 
86  stop(); // if isRunning(), remove from the stack, resume previous timer
87 }
88 
89 template <class TagName>
91  TEUCHOS_TEST_FOR_EXCEPTION(isPaused(), Exceptions::RuntimeError, "MueLu::MutuallyExclusiveTime::start(): timer is paused. Use resume().");
92 
93  if (isRunning()) {
94  return;
95  } // If timer is already running, do not pause/push-in-the-stack/start the timer.
96  // Otherwise, something bad will happen when this.stop() will be called
97 
98  // pause currently running timer
99  if (!timerStack_.empty()) {
100  GetOStream(Debug) << "pausing parent timer " << timerStack_.top()->name_ << std::endl;
101  timerStack_.top()->pause();
102  GetOStream(Debug) << "starting child timer " << this->name_ << std::endl;
103  myParent_[this->name_] = timerStack_.top()->name_;
104  } else {
105  GetOStream(Debug) << "starting orphan timer " << this->name_ << std::endl;
106  myParent_[this->name_] = "no parent";
107  }
108 
109  // start this timer
110  timer_->start(reset);
111  timerStack_.push(this);
112 }
113 
114 template <class TagName>
116  if (isPaused())
117  GetOStream(Errors) << "MueLu::MutuallyExclusiveTime::stop(): timer is paused. Use resume()" << std::endl;
118 
119  if (!isRunning()) {
120  return timer_->stop();
121  } // stop() can be called on stopped timer
122 
123  // Here, timer is running, so it is the head of the stack
124  TopOfTheStack();
125 
126  timerStack_.pop();
127  double r = timer_->stop();
128 
129  if (!timerStack_.empty()) {
130  GetOStream(Debug) << "resuming timer " << timerStack_.top()->name_ << std::endl;
131  timerStack_.top()->resume();
132  }
133 
134  return r;
135 }
136 
137 template <class TagName>
139  if (isPaused()) // calling twice pause() is allowed
140  return;
141 
142  TopOfTheStack();
143 
144  timer_->stop();
145  isPaused_ = true;
146 }
147 
148 template <class TagName>
150  TopOfTheStack();
151 
152  // no 'shortcut' test necessary:
153  // - if timer is stop, it is in pause (cannot be stop and not in pause because this timer is the head of the stack).
154  // - if timer is running, nothing is changed by this function.
155 
156  timer_->start(false);
157  isPaused_ = false;
158 }
159 
160 template <class TagName>
162  if (timer_->isRunning()) {
163  // TEUCHOS_TEST_FOR_EXCEPTION(timerStack_.top() != this, Exceptions::RuntimeError,
164  // "MueLu::MutuallyExclusiveTime::isRunning(): this timer is active so it is supposed to be the head of the stack");
165  }
166  return timer_->isRunning();
167 }
168 
169 template <class TagName>
171  TEUCHOS_TEST_FOR_EXCEPTION(isPaused_ && timer_->isRunning(), Exceptions::RuntimeError, "");
172  return isPaused_;
173 }
174 
175 template <class TagName>
178  timer->name_ = name;
179  return timer;
180 }
181 
182 template <class TagName>
183 void MutuallyExclusiveTime<TagName>::incrementNumCalls() { timer_->incrementNumCalls(); }
184 
185 template <class TagName>
187  // key is child, value is parent
188  RCP<Teuchos::FancyOStream> fos = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
189  fos->setOutputToRootOnly(0);
190  *fos << "Parent Child Map" << std::endl;
191  std::map<std::string, std::string>::const_iterator iter;
192  for (iter = ::MueLu::myParent_.begin(); iter != ::MueLu::myParent_.end(); ++iter) {
193  *fos << "Key: " << iter->first << " Value: " << iter->second << std::endl;
194  }
195 }
196 
197 template <class TagName>
199  : timer_(timer)
200  , isPaused_(false) {}
201 
202 template <class TagName>
204  TEUCHOS_TEST_FOR_EXCEPTION(timerStack_.empty(), Exceptions::RuntimeError, "MueLu::MutuallyExclusiveTime::TopOfTheStack(): timer is not the head of the stack (stack is empty).");
205  // TEUCHOS_TEST_FOR_EXCEPTION(timerStack_.top() != this, Exceptions::RuntimeError, "MueLu::MutuallyExclusiveTime::TopOfTheStack(): timer is not the head of the stack.");
206  TEUCHOS_TEST_FOR_EXCEPTION(!(isRunning() || isPaused()), Exceptions::RuntimeError, "MueLu::MutuallyExclusiveTime::TopOfTheStack(): head of the stack timer is neither active nor paused.");
207 }
208 
209 template <class TagName>
210 std::stack<MutuallyExclusiveTime<TagName>*> MutuallyExclusiveTime<TagName>::timerStack_;
211 
212 // FIXME: move this:
214 template class MutuallyExclusiveTime<Level>;
215 template class MutuallyExclusiveTime<BaseClass>;
216 
217 } // 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.