MueLu Version of the Day
Loading...
Searching...
No Matches
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
63namespace 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:
209 template class MutuallyExclusiveTime<Level>;
211
212} // namespace MueLu
Exception throws to report errors in the internal logical of the program.
This class wraps a Teuchos::Time and maintains a mutually exclusive property between wrapped timers.
void pause()
Pause running timer. Used internally by start().
void resume()
Resume paused timer. Used internally by stop(). Timer is not reset.
MutuallyExclusiveTime(const std::string &name, bool startFlag=false)
Constructor.
void TopOfTheStack()
Check if 'this' is the head of the stack.
double stop()
Stops the timer. The previous MutuallyExclusiveTime that has been paused when this timer was started ...
static void PrintParentChildPairs()
Print std::map of (child,parent) pairs for post-run analysis.
static RCP< MutuallyExclusiveTime< TagName > > getNewTimer(const std::string &name)
Return a new MutuallyExclusiveTime that is registered with the Teuchos::TimeMonitor (for timer summar...
void incrementNumCalls()
Increment the number of times this timer has been called.
void start(bool reset=false)
Starts the timer. If a MutuallyExclusiveTime timer is running, it will be stopped.
RCP< Teuchos::Time > timer_
Using an RCP allows to use Teuchos::TimeMonitor to keep track of the timer.
Namespace for MueLu classes and methods.
@ Debug
Print additional debugging information.
@ Errors
Errors.
std::map< std::string, std::string > myParent_