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))), // second argument is false in any case, because if start==true,
71  // timer has to be started by MutuallyExclusiveTime::start() instead of Teuchos::Time::start().
72  isPaused_(false)
73  {
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()) { return; } // If timer is already running, do not pause/push-in-the-stack/start the timer.
94  // Otherwise, something bad will happen when this.stop() will be called
95 
96  // pause currently running timer
97  if (!timerStack_.empty()) {
98  GetOStream(Debug) << "pausing parent timer " << timerStack_.top()->name_ << std::endl;
99  timerStack_.top()->pause();
100  GetOStream(Debug) << "starting child timer " << this->name_ << std::endl;
101  myParent_[this->name_] = timerStack_.top()->name_;
102  } else {
103  GetOStream(Debug) << "starting orphan timer " << this->name_ << std::endl;
104  myParent_[this->name_] = "no parent";
105  }
106 
107  // start this timer
108  timer_->start(reset);
109  timerStack_.push(this);
110  }
111 
112  template <class TagName>
114  if(isPaused())
115  GetOStream(Errors) << "MueLu::MutuallyExclusiveTime::stop(): timer is paused. Use resume()" << std::endl;
116 
117  if (!isRunning()) { return timer_->stop(); } // stop() can be called on stopped timer
118 
119  // Here, timer is running, so it is the head of the stack
120  TopOfTheStack();
121 
122  timerStack_.pop();
123  double r = timer_->stop();
124 
125  if (!timerStack_.empty()) {
126  GetOStream(Debug) << "resuming timer " << timerStack_.top()->name_ << std::endl;
127  timerStack_.top()->resume();
128  }
129 
130  return r;
131  }
132 
133  template <class TagName>
135  if (isPaused()) // calling twice pause() is allowed
136  return;
137 
138  TopOfTheStack();
139 
140  timer_->stop();
141  isPaused_ = true;
142  }
143 
144  template <class TagName>
146  TopOfTheStack();
147 
148  // no 'shortcut' test necessary:
149  // - if timer is stop, it is in pause (cannot be stop and not in pause because this timer is the head of the stack).
150  // - if timer is running, nothing is changed by this function.
151 
152  timer_->start(false);
153  isPaused_ = false;
154  }
155 
156  template <class TagName>
158  if (timer_->isRunning()) {
159  // TEUCHOS_TEST_FOR_EXCEPTION(timerStack_.top() != this, Exceptions::RuntimeError,
160  // "MueLu::MutuallyExclusiveTime::isRunning(): this timer is active so it is supposed to be the head of the stack");
161  }
162  return timer_->isRunning();
163  }
164 
165  template <class TagName>
167  TEUCHOS_TEST_FOR_EXCEPTION(isPaused_ && timer_->isRunning(), Exceptions::RuntimeError, "");
168  return isPaused_;
169  }
170 
171  template <class TagName>
174  timer->name_ = name;
175  return timer;
176  }
177 
178  template <class TagName>
179  void MutuallyExclusiveTime<TagName>::incrementNumCalls() { timer_->incrementNumCalls(); }
180 
181  template <class TagName>
183  //key is child, value is parent
184  RCP<Teuchos::FancyOStream> fos = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout)); fos->setOutputToRootOnly(0);
185  *fos << "Parent Child Map" << std::endl;
186  std::map<std::string, std::string >::const_iterator iter;
187  for (iter = ::MueLu::myParent_.begin(); iter != ::MueLu::myParent_.end(); ++iter) {
188  *fos << "Key: " << iter->first << " Value: " << iter->second << std::endl;
189  }
190  }
191 
192  template <class TagName>
194  : timer_(timer), isPaused_(false)
195  { }
196 
197  template <class TagName>
199  TEUCHOS_TEST_FOR_EXCEPTION(timerStack_.empty(), Exceptions::RuntimeError, "MueLu::MutuallyExclusiveTime::TopOfTheStack(): timer is not the head of the stack (stack is empty).");
200  // TEUCHOS_TEST_FOR_EXCEPTION(timerStack_.top() != this, Exceptions::RuntimeError, "MueLu::MutuallyExclusiveTime::TopOfTheStack(): timer is not the head of the stack.");
201  TEUCHOS_TEST_FOR_EXCEPTION(!(isRunning() || isPaused()), Exceptions::RuntimeError, "MueLu::MutuallyExclusiveTime::TopOfTheStack(): head of the stack timer is neither active nor paused.");
202  }
203 
204  template <class TagName>
205  std::stack<MutuallyExclusiveTime<TagName>*> MutuallyExclusiveTime<TagName>::timerStack_;
206 
207  //FIXME: move this:
208  template class MutuallyExclusiveTime<FactoryBase>;
209  template class MutuallyExclusiveTime<Level>;
210  template class MutuallyExclusiveTime<BaseClass>;
211 
212 } // namespace MueLu
void TopOfTheStack()
Check if &#39;this&#39; is the head of the stack.
std::map< std::string, std::string > myParent_
#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.
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.
MutuallyExclusiveTime(const std::string &name, bool startFlag=false)
Constructor.