MueLu Version of the Day
Loading...
Searching...
No Matches
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
26namespace MueLu {
27
28std::map<std::string, std::string> myParent_;
29
30template <class TagName>
31MutuallyExclusiveTime<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
40template <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
52template <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
77template <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
100template <class TagName>
102 if (isPaused()) // calling twice pause() is allowed
103 return;
104
105 TopOfTheStack();
106
107 timer_->stop();
108 isPaused_ = true;
109}
110
111template <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
123template <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
132template <class TagName>
134 TEUCHOS_TEST_FOR_EXCEPTION(isPaused_ && timer_->isRunning(), Exceptions::RuntimeError, "");
135 return isPaused_;
136}
137
138template <class TagName>
139RCP<MutuallyExclusiveTime<TagName> > MutuallyExclusiveTime<TagName>::getNewTimer(const std::string& name) {
140 RCP<MutuallyExclusiveTime<TagName> > timer = rcp(new MutuallyExclusiveTime<TagName>(Teuchos::TimeMonitor::getNewTimer(name)));
141 timer->name_ = name;
142 return timer;
143}
144
145template <class TagName>
146void MutuallyExclusiveTime<TagName>::incrementNumCalls() { timer_->incrementNumCalls(); }
147
148template <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
160template <class TagName>
162 : timer_(timer)
163 , isPaused_(false) {}
164
165template <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
172template <class TagName>
173std::stack<MutuallyExclusiveTime<TagName>*> MutuallyExclusiveTime<TagName>::timerStack_;
174
175// FIXME: move this:
177template class MutuallyExclusiveTime<Level>;
179
180} // 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.
std::map< std::string, std::string > myParent_