From b5a8c179373d2fd87d10af08702c3ea91f71e699 Mon Sep 17 00:00:00 2001 From: Ian Hinder Date: Fri, 26 Oct 2012 00:56:32 +0200 Subject: Support more than one hierarchy of timers * Introduce a TimerTree class which contains a pointer to the root and current TimerNodes of that tree * Adapt TimerNode and Timer classes to use TimerTrees rather than static variables * Declare a main_timer_tree variable, which is the default tree to use if you don't specify one in Timer timer("timername") --- Carpet/Carpet/src/CarpetStartup.cc | 4 ++- Carpet/Carpet/src/Evolve.cc | 3 +- Carpet/Carpet/src/Initialise.cc | 3 +- Carpet/Carpet/src/Shutdown.cc | 5 ++-- Carpet/Carpet/src/TimerNode.cc | 57 ++++++++++++++------------------------ Carpet/Carpet/src/TimerNode.hh | 23 +++++++++++---- Carpet/Carpet/src/Timers.cc | 15 ++++++---- Carpet/Carpet/src/Timers.hh | 3 ++ Carpet/Carpet/src/variables.cc | 1 + Carpet/Carpet/src/variables.hh | 3 +- 10 files changed, 61 insertions(+), 56 deletions(-) diff --git a/Carpet/Carpet/src/CarpetStartup.cc b/Carpet/Carpet/src/CarpetStartup.cc index 93a96d5e1..caa7bd96a 100644 --- a/Carpet/Carpet/src/CarpetStartup.cc +++ b/Carpet/Carpet/src/CarpetStartup.cc @@ -66,7 +66,9 @@ namespace Carpet { CCTK_OverloadGroupDynamicData (GroupDynamicData); // This must happen before any Timer objects are created - TimerNode::getRootTimer()->start(); + main_timer_tree.root = new TimerNode(&main_timer_tree,"main"); + main_timer_tree.current = 0; // No timer has been started yet + main_timer_tree.root->start(); return 0; } diff --git a/Carpet/Carpet/src/Evolve.cc b/Carpet/Carpet/src/Evolve.cc index 936414d40..aa51efe23 100644 --- a/Carpet/Carpet/src/Evolve.cc +++ b/Carpet/Carpet/src/Evolve.cc @@ -97,8 +97,7 @@ namespace Carpet { cctkGH->cctk_iteration % output_timer_tree_every == 0 and cctkGH->cctk_iteration % do_every == 0) { - TimerNode *rt = TimerNode::getRootTimer(); - TimerNode *et = rt->getChildTimer("Evolve"); + TimerNode *et = main_timer_tree.root->getChildTimer("Evolve"); et->print(cout, et->getTime(), 0, timer_tree_threshold_percentage, timer_tree_output_precision); } timer.stop(); diff --git a/Carpet/Carpet/src/Initialise.cc b/Carpet/Carpet/src/Initialise.cc index 3f3dffd15..0690616f7 100644 --- a/Carpet/Carpet/src/Initialise.cc +++ b/Carpet/Carpet/src/Initialise.cc @@ -139,8 +139,7 @@ namespace Carpet { if (output_initialise_timer_tree) { - TimerNode *rt = TimerNode::getRootTimer(); - TimerNode *it = rt->getChildTimer("Initialise"); + TimerNode *it = main_timer_tree.root->getChildTimer("Initialise"); it->print(cout, it->getTime(), 0, timer_tree_threshold_percentage, timer_tree_output_precision); } diff --git a/Carpet/Carpet/src/Shutdown.cc b/Carpet/Carpet/src/Shutdown.cc index 1cd354188..f3da0b086 100644 --- a/Carpet/Carpet/src/Shutdown.cc +++ b/Carpet/Carpet/src/Shutdown.cc @@ -80,11 +80,10 @@ namespace Carpet { } END_REVERSE_MGLEVEL_LOOP; - TimerNode *rt = TimerNode::getRootTimer(); - rt->stop(); + main_timer_tree.root->stop(); if (output_xml_timer_tree) - rt->outputXML(out_dir,CCTK_MyProc (cctkGH)); + main_timer_tree.root->outputXML(out_dir,CCTK_MyProc (cctkGH)); // earlier checkpoint before finalising MPI Waypoint ("Done with shutdown"); diff --git a/Carpet/Carpet/src/TimerNode.cc b/Carpet/Carpet/src/TimerNode.cc index 3c632b3d3..2ef20fcfd 100644 --- a/Carpet/Carpet/src/TimerNode.cc +++ b/Carpet/Carpet/src/TimerNode.cc @@ -42,11 +42,8 @@ namespace Carpet { using namespace std; - TimerNode *TimerNode::d_current = 0; - TimerNode *TimerNode::root_timer = 0; - - TimerNode::TimerNode(string name): d_name(name), d_parent(0), - d_running(false), timer(0) + TimerNode::TimerNode(TimerTree *tree, string name): d_name(name), d_parent(0), + timer(0), d_tree(tree), d_running(0) { } @@ -63,6 +60,7 @@ namespace Carpet { string TimerNode::pathName() const { + assert(d_parent != this); if (d_parent) return d_parent->pathName() + string("/") + getName(); else @@ -72,29 +70,24 @@ namespace Carpet { void TimerNode::instantiate() { assert(!d_running); - d_parent = d_current; - d_current = this; + d_parent = d_tree->current; + d_tree->current = this; if (timer == 0) timer = new CactusTimer(pathName()); - d_current = d_parent; + d_tree->current = d_parent; } void TimerNode::start() { - if (!d_running) - { - d_running = true; - d_parent = d_current; - d_current = this; - if (timer == 0) - timer = new CactusTimer(pathName()); - assert(timer); - timer->start(); - } - else - { - assert(0); // Timer is already running - } + assert(!d_running); + + d_running = true; + d_parent = d_tree->current; + d_tree->current = this; + if (timer == 0) + timer = new CactusTimer(pathName()); + assert(timer); + timer->start(); } void TimerNode::stop() @@ -102,14 +95,14 @@ namespace Carpet { if (d_running) { // A timer can only be stopped if it is the current timer - if(this != d_current) + if(this != d_tree->current) CCTK_VWarn (0, __LINE__, __FILE__, CCTK_THORNSTRING, "Tried to stop non-current timer '%s'", getName().c_str()); timer->stop(); d_running = false; - d_current = d_parent; + d_tree->current = d_parent; } else { @@ -124,18 +117,10 @@ namespace Carpet { return d_name; } - /// Get the current timer - TimerNode* TimerNode::getCurrentTimer() - { - return d_current; - } - - /// Get the root of the timer tree - TimerNode* TimerNode::getRootTimer() + /// Determine if the timer is running + bool TimerNode::isRunning() const { - if (root_timer == 0) - root_timer = new TimerNode("main"); - return root_timer; + return d_running; } /// Find the child timer that matches the name provided. If it is @@ -147,7 +132,7 @@ namespace Carpet { // If the pointer is null then allocate it if(child == 0) - d_children[name] = child = new TimerNode(name); + d_children[name] = child = new TimerNode(d_tree, name); return child; } diff --git a/Carpet/Carpet/src/TimerNode.hh b/Carpet/Carpet/src/TimerNode.hh index be932be07..9658fd275 100644 --- a/Carpet/Carpet/src/TimerNode.hh +++ b/Carpet/Carpet/src/TimerNode.hh @@ -46,6 +46,20 @@ namespace Carpet { using namespace std; +class TimerNode; + +class TimerTree +{ +public: + TimerTree() + { + root = 0; + current = 0; + } + TimerNode *root; + TimerNode *current; +}; + /** The TimerNode class implements a tree structure where each node @@ -65,7 +79,7 @@ already. This ensures that the names of the child timers are unique. class TimerNode { public: - TimerNode(string name); + TimerNode(TimerTree *root, string name); ~TimerNode(); void instantiate(); @@ -75,14 +89,12 @@ public: string getName() const; string pathName() const; - static TimerNode* getCurrentTimer(); - // Finds the child timer that matches the name provided. If it is // not found then that timer is allocated. TimerNode* getChildTimer(string name); - static TimerNode* getRootTimer(); double getTime(); + bool isRunning() const; void print(ostream& out, double total, int level=0, double threshold=0.0, int precision=1); void printXML(ostream& out, int level=0); @@ -93,9 +105,8 @@ private: string d_name; std::map d_children; - static TimerNode* d_current; - static TimerNode* root_timer; TimerNode *d_parent; + TimerTree *d_tree; bool d_running; CactusTimer *timer; }; diff --git a/Carpet/Carpet/src/Timers.cc b/Carpet/Carpet/src/Timers.cc index 313d1d034..01d502aa3 100644 --- a/Carpet/Carpet/src/Timers.cc +++ b/Carpet/Carpet/src/Timers.cc @@ -16,7 +16,7 @@ #include #include - +#include "variables.hh" namespace Carpet { @@ -30,6 +30,11 @@ namespace Carpet { /// Create a timer with a given name, but do not start it, and do /// not associate it with a point in the timer hierarchy. Timer::Timer (const string &name_p) : d_name(name_p) + { + d_tree = &main_timer_tree; + } + + Timer::Timer (const string &name_p, TimerTree *tree) : d_name(name_p), d_tree(tree) { } @@ -44,7 +49,7 @@ namespace Carpet { /// never started. void Timer::instantiate () { - TimerNode *current_timer = TimerNode::getCurrentTimer(); + TimerNode *current_timer = d_tree->current; assert(current_timer); current_timer->getChildTimer(name())->instantiate(); } @@ -53,7 +58,7 @@ namespace Carpet { /// of the most recently started timer that has not been stopped. void Timer::start () { - TimerNode *current_timer = TimerNode::getCurrentTimer(); + TimerNode *current_timer = d_tree->current; assert(current_timer); current_timer->getChildTimer(name())->start(); } @@ -61,7 +66,7 @@ namespace Carpet { /// Stop the timer - it must be the most recently started timer void Timer::stop () { - TimerNode *current = TimerNode::getCurrentTimer(); + TimerNode *current = d_tree->current; if (current->getName() != name()) CCTK_VWarn (0, __LINE__, __FILE__, CCTK_THORNSTRING, "Trying to stop enclosing timer '%s' before enclosed time '%s'", @@ -78,6 +83,6 @@ namespace Carpet { /// Return the current time of the timer as a double double Timer::getTime () { - return TimerNode::getCurrentTimer()->getTime(); + return d_tree->current->getTime(); } } // namespace Carpet diff --git a/Carpet/Carpet/src/Timers.hh b/Carpet/Carpet/src/Timers.hh index c3ee01c6f..fdd31773f 100644 --- a/Carpet/Carpet/src/Timers.hh +++ b/Carpet/Carpet/src/Timers.hh @@ -45,12 +45,14 @@ started timer. Doing so will generate an error. Timer objects can be allocated as "static" or not - it does not matter. */ + class TimerTree; class Timer { public: Timer (const string &name); + Timer (const string &name, TimerTree *tree); ~Timer (); void instantiate (); @@ -62,6 +64,7 @@ Timer objects can be allocated as "static" or not - it does not matter. private: string d_name; + TimerTree *d_tree; }; // Macros for using timers in a convenient manner diff --git a/Carpet/Carpet/src/variables.cc b/Carpet/Carpet/src/variables.cc index 1e1b31b06..e06881339 100644 --- a/Carpet/Carpet/src/variables.cc +++ b/Carpet/Carpet/src/variables.cc @@ -27,6 +27,7 @@ namespace Carpet { int maxtimereflevelfact; vect maxspacereflevelfact; + TimerTree main_timer_tree; // Base multigrid level int basemglevel; diff --git a/Carpet/Carpet/src/variables.hh b/Carpet/Carpet/src/variables.hh index 707e6f1ae..c673b1699 100644 --- a/Carpet/Carpet/src/variables.hh +++ b/Carpet/Carpet/src/variables.hh @@ -32,7 +32,7 @@ #include #include "carpet_public.h" - +#include "TimerNode.hh" namespace Carpet { @@ -94,6 +94,7 @@ namespace Carpet { extern int timereflevelfact; extern vect spacereflevelfact; + extern TimerTree main_timer_tree; // Current multigrid factor extern int mglevelfact; -- cgit v1.2.3