MueLu  Version of the Day
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>
172  RCP<MutuallyExclusiveTime<TagName> > MutuallyExclusiveTime<TagName>::getNewTimer(const std::string& name) {
173  RCP<MutuallyExclusiveTime<TagName> > timer = rcp(new MutuallyExclusiveTime<TagName>(Teuchos::TimeMonitor::getNewTimer(name)));
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_
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...
Namespace for MueLu classes and methods.
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.
double stop()
Stops the timer. The previous MutuallyExclusiveTime that has been paused when this timer was started ...
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.
void pause()
Pause running timer. Used internally by start().
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.