From 77e61bb9a06ef271348c96d762935442c7439f0c Mon Sep 17 00:00:00 2001 From: Erik Schnetter Date: Wed, 7 Aug 2013 18:33:48 -0400 Subject: Timers: Move all timer-related code into a new thorn Timers --- Carpet/Carpet/configuration.ccl | 2 +- Carpet/Carpet/interface.ccl | 6 +- Carpet/Carpet/param.ccl | 18 - Carpet/Carpet/src/CactusTimer.cc | 253 -------------- Carpet/Carpet/src/CactusTimer.hh | 75 ---- Carpet/Carpet/src/CallFunction.cc | 27 +- Carpet/Carpet/src/CarpetStartup.cc | 10 - Carpet/Carpet/src/Checksum.cc | 5 +- Carpet/Carpet/src/Comm.cc | 27 +- Carpet/Carpet/src/Cycle.cc | 5 +- Carpet/Carpet/src/Evolve.cc | 38 +-- Carpet/Carpet/src/Initialise.cc | 50 ++- .../LoadBalanceReal/splitregions_recursively.cc | 3 +- Carpet/Carpet/src/OutputGH.cc | 9 +- Carpet/Carpet/src/Poison.cc | 7 +- Carpet/Carpet/src/Recompose.cc | 15 +- Carpet/Carpet/src/Restrict.cc | 17 +- Carpet/Carpet/src/SetupGH.cc | 18 +- Carpet/Carpet/src/Shutdown.cc | 25 +- Carpet/Carpet/src/TimerNode.cc | 373 -------------------- Carpet/Carpet/src/TimerNode.hh | 119 ------- Carpet/Carpet/src/TimerSet.cc | 190 ----------- Carpet/Carpet/src/TimerSet.hh | 69 ---- Carpet/Carpet/src/Timers.cc | 90 ----- Carpet/Carpet/src/Timers.hh | 84 ----- Carpet/Carpet/src/make.code.defn | 6 +- Carpet/Carpet/src/modes.cc | 108 +++--- Carpet/Carpet/src/variables.cc | 3 - Carpet/Carpet/src/variables.hh | 5 +- Carpet/CarpetIOASCII/interface.ccl | 3 +- Carpet/CarpetIOASCII/src/ioascii.cc | 13 +- Carpet/CarpetIOBasic/interface.ccl | 3 +- Carpet/CarpetIOBasic/src/iobasic.cc | 12 +- Carpet/CarpetIOHDF5/interface.ccl | 3 +- Carpet/CarpetIOHDF5/src/CarpetIOHDF5.cc | 14 +- Carpet/CarpetIOHDF5/src/OutputSlice.cc | 8 +- Carpet/CarpetIOScalar/interface.ccl | 3 +- Carpet/CarpetIOScalar/src/ioscalar.cc | 14 +- Carpet/CarpetLib/interface.ccl | 2 +- Carpet/CarpetLib/src/defs.cc | 2 - Carpet/CarpetLib/src/dh.cc | 66 ++-- Carpet/CarpetLib/src/ggf.cc | 12 +- Carpet/CarpetLib/src/gh.cc | 4 +- Carpet/CarpetRegrid2/interface.ccl | 3 +- Carpet/CarpetRegrid2/src/regrid.cc | 7 +- Carpet/Timers/README | 14 + Carpet/Timers/configuration.ccl | 8 + Carpet/Timers/doc/documentation.tex | 144 ++++++++ Carpet/Timers/interface.ccl | 14 + Carpet/Timers/param.ccl | 29 ++ Carpet/Timers/schedule.ccl | 11 + Carpet/Timers/src/CactusTimer.cc | 254 ++++++++++++++ Carpet/Timers/src/CactusTimer.hh | 69 ++++ Carpet/Timers/src/CactusTimerSet.cc | 179 ++++++++++ Carpet/Timers/src/CactusTimerSet.hh | 62 ++++ Carpet/Timers/src/Timer.cc | 135 ++++++++ Carpet/Timers/src/Timer.hh | 89 +++++ Carpet/Timers/src/TimerTree.cc | 378 +++++++++++++++++++++ Carpet/Timers/src/TimerTree.hh | 121 +++++++ Carpet/Timers/src/make.code.defn | 7 + 60 files changed, 1777 insertions(+), 1563 deletions(-) delete mode 100644 Carpet/Carpet/src/CactusTimer.cc delete mode 100644 Carpet/Carpet/src/CactusTimer.hh delete mode 100644 Carpet/Carpet/src/TimerNode.cc delete mode 100644 Carpet/Carpet/src/TimerNode.hh delete mode 100644 Carpet/Carpet/src/TimerSet.cc delete mode 100644 Carpet/Carpet/src/TimerSet.hh delete mode 100644 Carpet/Carpet/src/Timers.cc delete mode 100644 Carpet/Carpet/src/Timers.hh create mode 100644 Carpet/Timers/README create mode 100644 Carpet/Timers/configuration.ccl create mode 100644 Carpet/Timers/doc/documentation.tex create mode 100644 Carpet/Timers/interface.ccl create mode 100644 Carpet/Timers/param.ccl create mode 100644 Carpet/Timers/schedule.ccl create mode 100644 Carpet/Timers/src/CactusTimer.cc create mode 100644 Carpet/Timers/src/CactusTimer.hh create mode 100644 Carpet/Timers/src/CactusTimerSet.cc create mode 100644 Carpet/Timers/src/CactusTimerSet.hh create mode 100644 Carpet/Timers/src/Timer.cc create mode 100644 Carpet/Timers/src/Timer.hh create mode 100644 Carpet/Timers/src/TimerTree.cc create mode 100644 Carpet/Timers/src/TimerTree.hh create mode 100644 Carpet/Timers/src/make.code.defn diff --git a/Carpet/Carpet/configuration.ccl b/Carpet/Carpet/configuration.ccl index d41eb1ae1..caae10cf3 100644 --- a/Carpet/Carpet/configuration.ccl +++ b/Carpet/Carpet/configuration.ccl @@ -4,7 +4,7 @@ PROVIDES Carpet { } -REQUIRES IOUtil CarpetLib MPI +REQUIRES CarpetLib IOUtil MPI Timers OPTIONAL LoopControl { diff --git a/Carpet/Carpet/interface.ccl b/Carpet/Carpet/interface.ccl index fe5c91d10..4a096666e 100644 --- a/Carpet/Carpet/interface.ccl +++ b/Carpet/Carpet/interface.ccl @@ -5,14 +5,16 @@ IMPLEMENTS: Driver include header: carpet_public.hh in carpet.hh include header: carpet_public.h in carpet.h -include header: Timers.hh in CarpetTimers.hh - uses include header: Requirements.hh uses include header: nompi.h uses include header: loopcontrol.h +uses include header: CactusTimerSet.hh +uses include header: Timer.hh +uses include header: TimerTree.hh + uses include header: mpi_string.hh uses include header: cacheinfo.hh diff --git a/Carpet/Carpet/param.ccl b/Carpet/Carpet/param.ccl index 8db365016..90ad98b81 100644 --- a/Carpet/Carpet/param.ccl +++ b/Carpet/Carpet/param.ccl @@ -409,15 +409,6 @@ STRING timer_file "File name in which detailed timing statistics are collected" "^.+$" :: "file name" } "carpet-timing-statistics" -BOOLEAN timers_verbose "Output (debug) messages when a timer is started or stopped" STEERABLE=always -{ -} "no" - -STRING timer_xml_clock "Which clock to use in the XML timer output file" STEERABLE=always -{ - ".*" :: "must be a legal clock name" -} "gettimeofday" - BOOLEAN output_initialise_timer_tree "Output timing information in tree form to standard output for Initialise" { } "no" @@ -440,15 +431,6 @@ BOOLEAN include_local_mode_in_mode_timer_tree "Include a node for the time spen { } "no" -CCTK_REAL timer_tree_threshold_percentage "The percentage of the root timer below which timers are omitted" STEERABLE=always -{ - 0:* :: "" -} 1.0 - -INT timer_tree_output_precision "Number of decimal places to use in standard output for timer tree" STEERABLE=always -{ - 1:* :: "number of decimal places" -} 1 BOOLEAN recompose_verbose "Output debug information during recomposing" STEERABLE=ALWAYS diff --git a/Carpet/Carpet/src/CactusTimer.cc b/Carpet/Carpet/src/CactusTimer.cc deleted file mode 100644 index a4250f6ee..000000000 --- a/Carpet/Carpet/src/CactusTimer.cc +++ /dev/null @@ -1,253 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#if HAVE_UNISTD_H -# include -# include -#endif - -#include - -#include "CactusTimer.hh" -#include "TimerSet.hh" - -namespace Carpet -{ - using namespace std; - - // Create a new Cactus timer with the given name - CactusTimer::CactusTimer (const string &timername) - : running (false) - { -// cout << "CactusTimer::CactusTimer(): name = " << timername << endl; - handle = CCTK_TimerCreate (timername.c_str()); - assert (handle >= 0); - - timerSet.add (this); - } - - // Destroy a timer - CactusTimer::~CactusTimer () - { - timerSet.remove (this); - check (not CCTK_TimerDestroyI (handle)); - } - - // Start the timer - void CactusTimer::start () - { - msgStart (); -// cout << "CactusTimer::start this = " << this << endl; - running = true; - CCTK_TimerStartI (handle); - } - - // Stop the timer - void CactusTimer::stop () - { - CCTK_TimerStopI (handle); - running = false; - msgStop (); - } - - // Reset the timer - void CactusTimer::reset () - { - CCTK_TimerResetI (handle); - } - - // Timer name - string CactusTimer::name () const - { - char const * const timername = CCTK_TimerName (handle); - assert (timername); - return string(timername); - } - - double CactusTimer::getTime() - { - DECLARE_CCTK_PARAMETERS; - - static cTimerData * timer = 0; - if (not timer) timer = CCTK_TimerCreateData (); - assert (timer); - CCTK_TimerI (handle, timer); - - bool const was_running = running; - if (was_running) stop(); - const cTimerVal * tv = CCTK_GetClockValue(timer_xml_clock, timer); - if (was_running) start(); - - if (not tv) { - CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING, - "Clock \"%s\" not found for timer #%d \"%s\"", - timer_xml_clock, handle, CCTK_TimerName(handle)); - return -1.0; - } - - return CCTK_TimerClockSeconds(tv); - } - - void CactusTimer::getGlobalTime(double& avg, double& max) - { - const cGH *const cctkGH = 0; - - int ierr; - - static int op_sum = -1; - static int op_max = -1; - if (op_sum<0) op_sum = CCTK_ReductionArrayHandle("sum"); - if (op_max<0) op_max = CCTK_ReductionArrayHandle("maximum"); - - const double val = getTime(); - const CCTK_REAL val1 = val; - - CCTK_REAL sum1; - ierr = CCTK_ReduceLocScalar(cctkGH, -1, op_sum, - &val1, &sum1, CCTK_VARIABLE_REAL); - if (ierr) { - CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING, - "Error in sum reduction"); - } - avg = sum1 / CCTK_nProcs(cctkGH); - - CCTK_REAL max1; - ierr = CCTK_ReduceLocScalar(cctkGH, -1, op_max, - &val1, &max1, CCTK_VARIABLE_REAL); - if (ierr) { - CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING, - "Error in maximum reduction"); - } - max = max1; - } - - vector > CactusTimer::getAllTimerNames() const - { - DECLARE_CCTK_PARAMETERS; - - static cTimerData *timer = NULL; - if (not timer) timer = CCTK_TimerCreateData(); - assert(timer); - - CCTK_TimerI(handle, timer); - - vector > names(timer->n_vals); - for (int i=0; in_vals; ++i) { - names[i].first = timer->vals[i].heading; - names[i].second = timer->vals[i].units; - } - - return names; - } - - vector CactusTimer::getAllTimerValues() - { - DECLARE_CCTK_PARAMETERS; - - bool const was_running = running; - if (was_running) stop(); - - static cTimerData *timer = NULL; - if (not timer) timer = CCTK_TimerCreateData(); - assert(timer); - - CCTK_TimerI(handle, timer); - - vector vals(timer->n_vals); - for (int i=0; in_vals; ++i) { - switch (timer->vals[i].type) { - case val_int: vals[i] = timer->vals[i].val.i; break; - case val_long: vals[i] = timer->vals[i].val.l; break; - case val_double: vals[i] = timer->vals[i].val.d; break; - default: CCTK_BUILTIN_UNREACHABLE(); - } - } - - if (was_running) start(); - - return vals; - } - - // Print timer data - void CactusTimer::printData () - { - bool const was_running = running; - if (was_running) stop(); - -#if 0 - check (not CCTK_TimerPrintDataI (handle, -1)); // -1 means: all clocks -#endif - - static cTimerData * timer = 0; - if (not timer) timer = CCTK_TimerCreateData (); - assert (timer); - CCTK_TimerI (handle, timer); - - static bool firsttime = true; - if (firsttime) { - printf ("# 1: timer name"); - for (int i=0; in_vals; ++i) { - printf (" %d: %s [%s]", - i+2, timer->vals[i].heading, timer->vals[i].units); - } - printf ("\n"); - firsttime = false; - } - - printf ("%s:", name().c_str()); - for (int i=0; in_vals; ++i) { - switch (timer->vals[i].type) { - case val_int: - printf (" %d", timer->vals[i].val.i); - break; - case val_long: - printf (" %ld", timer->vals[i].val.l); - break; - case val_double: - printf (" %g", timer->vals[i].val.d); - break; - case val_none: - break; - default: - assert (0); - } - } - printf ("\n"); - - if (was_running) start(); - } - - // Output (debug) messages that a timer is starting or stopping - void CactusTimer::msgStart () const - { - DECLARE_CCTK_PARAMETERS; - if (timers_verbose) { - CCTK_VInfo (CCTK_THORNSTRING, "Timer \"%s\" starting", name().c_str()); - } - } - - void CactusTimer::msgStop () const - { - DECLARE_CCTK_PARAMETERS; - if (timers_verbose) { - CCTK_VInfo (CCTK_THORNSTRING, "Timer \"%s\" stopping", name().c_str()); - } - } - - ostream& CactusTimer::serialise(ostream &os) - { - os << scientific << setprecision(19) << getTime() << " " << name(); - return os; - } - -} // namespace Carpet diff --git a/Carpet/Carpet/src/CactusTimer.hh b/Carpet/Carpet/src/CactusTimer.hh deleted file mode 100644 index cab4c592a..000000000 --- a/Carpet/Carpet/src/CactusTimer.hh +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef CACTUSTIMER_HH -#define CACTUSTIMER_HH - -#include - -#include -#include -#include -#include -#include - -namespace Carpet { - - using namespace std; - -/** The CactusTimer class wraps the Cactus timer mechanism. All times - are returned as doubles for now. */ - - class CactusTimer - { - int handle; - bool running; - - public: - - /// Create a new Cactus timer with the given name - CactusTimer (const string &timername); - - /// Destroy a timer - ~CactusTimer (); - - /// Start the timer - void start (); - - /// Stop the timer - void stop (); - - /// Reset the timer - void reset (); - - /// Timer name - string name () const; - - /// Return the current time of the timer in seconds as a double - double getTime(); - - /// Return the average and maximum current time over all MPI processes - void getGlobalTime(double& avg, double& max); - - /// Return all clock names and their units - vector > getAllTimerNames() const; - - /// Return all clock values of the timer as double - vector getAllTimerValues(); - - /// Print timer data - void printData (); - - ostream& serialise(ostream &os); - - private: - - // Output (debug) messages that a timer is starting or stopping - void - msgStart () - const; - - void - msgStop () - const; - - }; -} // namespace Carpet - -#endif // CACTUSTIMER_HH diff --git a/Carpet/Carpet/src/CallFunction.cc b/Carpet/Carpet/src/CallFunction.cc index 5b209270b..935fe2e4d 100644 --- a/Carpet/Carpet/src/CallFunction.cc +++ b/Carpet/Carpet/src/CallFunction.cc @@ -12,10 +12,11 @@ #include +#include + #include #include -#include #include "adler32.hh" @@ -32,12 +33,12 @@ namespace Carpet { void * function, cFunctionData * attribute, void * data, - Timer & user_timer); + Timers::Timer & user_timer); static void SyncGroupsInScheduleBlock (cFunctionData * attribute, cGH * cctkGH, vector const & sync_groups, - Timer & sync_timer); + Timers::Timer & sync_timer); /// Traverse one function on all components of one refinement level /// of one multigrid level. @@ -47,9 +48,9 @@ namespace Carpet { { DECLARE_CCTK_PARAMETERS; - static Timer total_timer ("CallFunction"); - static Timer user_timer ("thorns"); - static Timer sync_timer ("syncs"); + static Timers::Timer total_timer ("CallFunction"); + static Timers::Timer user_timer ("thorns"); + static Timers::Timer sync_timer ("syncs"); total_timer.start(); @@ -322,7 +323,7 @@ namespace Carpet { buf << attribute->routine << "\n"; string const str = buf.str(); int const id = adler32(str.c_str(), str.length()); - static Timer barrier_timer ("barrier"); + static Timers::Timer barrier_timer ("barrier"); barrier_timer.start(); Carpet::NamedBarrier (NULL, id, "Carpet::CallFunction"); barrier_timer.stop(); @@ -344,7 +345,7 @@ namespace Carpet { void * const function, cFunctionData * const attribute, void * const data, - Timer & user_timer) + Timers::Timer & user_timer) { cGH const * const cctkGH = static_cast (data); Checkpoint ("%s call at %s to %s::%s", @@ -353,7 +354,7 @@ namespace Carpet { attribute->thorn, attribute->routine); int const skip = CallBeforeRoutines (cctkGH, function, attribute, data); if (not skip) { - Timer timer(attribute->routine); + Timers::Timer timer(attribute->routine); // Save the time step size CCTK_REAL const saved_cctk_delta_time = cctkGH->cctk_delta_time; @@ -366,7 +367,7 @@ namespace Carpet { #endif timer.start(); if (CCTK_IsFunctionAliased("Accelerator_PreCallFunction")) { - Timer pre_timer("PreCall"); + Timers::Timer pre_timer("PreCall"); pre_timer.start(); Accelerator_PreCallFunction(cctkGH, attribute); pre_timer.stop(); @@ -374,7 +375,7 @@ namespace Carpet { int const res = CCTK_CallFunction (function, attribute, data); assert (res==0); if (CCTK_IsFunctionAliased("Accelerator_PostCallFunction")) { - Timer post_timer("PostCall"); + Timers::Timer post_timer("PostCall"); post_timer.start(); Accelerator_PostCallFunction(cctkGH, attribute); post_timer.stop(); @@ -430,7 +431,7 @@ namespace Carpet { void SyncGroupsInScheduleBlock (cFunctionData* attribute, cGH* cctkGH, vector const & sync_groups, - Timer & sync_timer) + Timers::Timer & sync_timer) { DECLARE_CCTK_PARAMETERS; @@ -453,7 +454,7 @@ namespace Carpet { buf << attribute->routine << " sync\n"; string const str = buf.str(); int const id = adler32(str.c_str(), str.length()); - static Timer barrier_timer ("sync_barrier"); + static Timers::Timer barrier_timer ("sync_barrier"); barrier_timer.start(); Carpet::NamedBarrier (NULL, id, "Carpet::Sync"); barrier_timer.stop(); diff --git a/Carpet/Carpet/src/CarpetStartup.cc b/Carpet/Carpet/src/CarpetStartup.cc index 96d061f50..7314cda43 100644 --- a/Carpet/Carpet/src/CarpetStartup.cc +++ b/Carpet/Carpet/src/CarpetStartup.cc @@ -9,7 +9,6 @@ #include #include -#include @@ -65,15 +64,6 @@ namespace Carpet { CCTK_OverloadQueryGroupStorageB (QueryGroupStorageB); CCTK_OverloadGroupDynamicData (GroupDynamicData); - // This must happen before any Timer objects are created - 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(); - - mode_timer_tree.root = new TimerNode(&mode_timer_tree,"meta mode"); - mode_timer_tree.current = 0; // No timer has been started yet - mode_timer_tree.root->start(); - return 0; } diff --git a/Carpet/Carpet/src/Checksum.cc b/Carpet/Carpet/src/Checksum.cc index 877b1d209..b96282f64 100644 --- a/Carpet/Carpet/src/Checksum.cc +++ b/Carpet/Carpet/src/Checksum.cc @@ -7,10 +7,11 @@ #include #include +#include + #include #include -#include "Timers.hh" namespace Carpet { @@ -68,7 +69,7 @@ namespace Carpet { if (! checksum_timelevels) return; - Timer timer("CalculateChecksums"); + Timers::Timer timer("CalculateChecksums"); timer.start(); Checkpoint ("CalculateChecksums"); diff --git a/Carpet/Carpet/src/Comm.cc b/Carpet/Carpet/src/Comm.cc index 040ed64fe..b1c5cf2ab 100644 --- a/Carpet/Carpet/src/Comm.cc +++ b/Carpet/Carpet/src/Comm.cc @@ -10,11 +10,12 @@ #include +#include + #include #include #include -#include @@ -145,7 +146,7 @@ namespace Carpet { // prolongate boundaries bool const local_do_prolongate = do_prolongate and not do_taper; if (local_do_prolongate) { - static Timer timer ("Prolongate"); + static Timers::Timer timer ("Prolongate"); timer.start(); ProlongateGroupBoundaries (cctkGH, goodgroups); timer.stop(); @@ -165,7 +166,7 @@ namespace Carpet { // synchronise ghostzones if (sync_during_time_integration or local_do_prolongate) { - static Timer timer ("Sync"); + static Timers::Timer timer ("Sync"); timer.start(); SyncGroups (cctkGH, goodgroups); timer.stop(); @@ -191,9 +192,9 @@ namespace Carpet { // use the current time here (which may be modified by the user) const CCTK_REAL time = cctkGH->cctk_time; - static vector timers; + static vector timers; if (timers.empty()) { - timers.push_back(new Timer("comm_state[0].create")); + timers.push_back(new Timers::Timer("comm_state[0].create")); for (astate state = static_cast(0); state != state_done; state = static_cast(static_cast(state)+1)) @@ -201,15 +202,15 @@ namespace Carpet { ostringstream name1; name1 << "comm_state[" << timers.size() << "]" << "." << tostring(state) << ".user"; - timers.push_back(new Timer(name1.str())); + timers.push_back(new Timers::Timer(name1.str())); ostringstream name2; name2 << "comm_state[" << timers.size() << "]" << "." << tostring(state) << ".step"; - timers.push_back(new Timer(name2.str())); + timers.push_back(new Timers::Timer(name2.str())); } } - vector::iterator ti = timers.begin(); + vector::iterator ti = timers.begin(); (*ti)->start(); for (comm_state state; not state.done(); state.step()) { (*ti)->stop(); ++ti; (*ti)->start(); @@ -253,9 +254,9 @@ namespace Carpet { Accelerator_PreSync(cctkGH, &groups.front(), groups.size()); } - static vector timers; + static vector timers; if (timers.empty()) { - timers.push_back(new Timer("comm_state[0].create")); + timers.push_back(new Timers::Timer("comm_state[0].create")); for (astate state = static_cast(0); state != state_done; state = static_cast(static_cast(state)+1)) @@ -263,15 +264,15 @@ namespace Carpet { ostringstream name1; name1 << "comm_state[" << timers.size() << "]" << "." << tostring(state) << ".user"; - timers.push_back(new Timer(name1.str())); + timers.push_back(new Timers::Timer(name1.str())); ostringstream name2; name2 << "comm_state[" << timers.size() << "]" << "." << tostring(state) << ".step"; - timers.push_back(new Timer(name2.str())); + timers.push_back(new Timers::Timer(name2.str())); } } - vector::iterator ti = timers.begin(); + vector::iterator ti = timers.begin(); (*ti)->start(); for (comm_state state; not state.done(); state.step()) { (*ti)->stop(); ++ti; (*ti)->start(); diff --git a/Carpet/Carpet/src/Cycle.cc b/Carpet/Carpet/src/Cycle.cc index 5210d7f48..cff3235de 100644 --- a/Carpet/Carpet/src/Cycle.cc +++ b/Carpet/Carpet/src/Cycle.cc @@ -6,11 +6,12 @@ #include +#include + #include #include #include -#include @@ -24,7 +25,7 @@ namespace Carpet { { DECLARE_CCTK_PARAMETERS; - Timer timer("CycleTimeLevels"); + Timers::Timer timer("CycleTimeLevels"); timer.start(); Checkpoint ("CycleTimeLevels"); diff --git a/Carpet/Carpet/src/Evolve.cc b/Carpet/Carpet/src/Evolve.cc index 0a959b48c..24d4cbbb2 100644 --- a/Carpet/Carpet/src/Evolve.cc +++ b/Carpet/Carpet/src/Evolve.cc @@ -12,18 +12,17 @@ #include #include #include +#include #include -#include +#include +#include #include #include #include -#include -#include -#include @@ -61,7 +60,7 @@ namespace Carpet { // Main loop BeginTimingEvolution (cctkGH); - static Timer timer ("Evolve"); + static Timers::Timer timer ("Evolve"); timer.start(); while (not do_terminate (cctkGH)) { @@ -83,33 +82,28 @@ namespace Carpet { // Print timer values { - Timer timer("PrintTimers"); + Timers::Timer timer("PrintTimers"); timer.start(); int const do_every = maxtimereflevelfact / timereffacts.AT(reflevels-1); if (output_timers_every > 0 and cctkGH->cctk_iteration % output_timers_every == 0 and cctkGH->cctk_iteration % do_every == 0) { - Carpet::TimerSet::writeData (cctkGH, timer_file); + Timers::CactusTimerSet::writeData (cctkGH, timer_file); } if (output_timer_tree_every > 0 and cctkGH->cctk_iteration % output_timer_tree_every == 0 and cctkGH->cctk_iteration % do_every == 0) { - TimerNode *et = main_timer_tree.root->getChildTimer("Evolve"); - double total_avg, total_max; - et->getGlobalTime(total_avg, total_max); - et->print(cout, total_max, 0, timer_tree_threshold_percentage, timer_tree_output_precision); - mode_timer_tree.root->getGlobalTime(total_avg, total_max); - mode_timer_tree.root->print(cout, total_max, 0, timer_tree_threshold_percentage, timer_tree_output_precision); + Timers::Timer::outputTree("Evolve"); } timer.stop(); } // Ensure that all levels have consistent times { - Timer timer("CheckLevelTimes"); + Timers::Timer timer("CheckLevelTimes"); timer.start(); CCTK_REAL const eps = pow(numeric_limits::epsilon(), CCTK_REAL(0.75)); @@ -144,7 +138,7 @@ namespace Carpet { { DECLARE_CCTK_PARAMETERS; - static Timer timer ("DoTerminate"); + static Timers::Timer timer ("DoTerminate"); timer.start(); bool term; @@ -228,7 +222,7 @@ namespace Carpet { { DECLARE_CCTK_PARAMETERS; - static Timer timer ("AdvanceTime"); + static Timers::Timer timer ("AdvanceTime"); timer.start(); Checkpoint ("AdvanceTime"); @@ -264,7 +258,7 @@ namespace Carpet { DECLARE_CCTK_PARAMETERS; char const * const where = "CallRegrid"; - static Timer timer (where); + static Timers::Timer timer (where); timer.start(); assert (is_level_mode()); @@ -404,7 +398,7 @@ namespace Carpet { DECLARE_CCTK_PARAMETERS; char const * const where = "CallEvol"; - static Timer timer (where); + static Timers::Timer timer (where); timer.start(); for (int ml=mglevels-1; ml>=0; --ml) { @@ -492,7 +486,7 @@ namespace Carpet { DECLARE_CCTK_PARAMETERS; char const * const where = "Evolve::CallRestrict"; - static Timer timer ("CallRestrict"); + static Timers::Timer timer ("CallRestrict"); timer.start(); for (int ml=mglevels-1; ml>=0; --ml) { @@ -595,7 +589,7 @@ namespace Carpet { DECLARE_CCTK_PARAMETERS; char const * const where = "CallAnalysis"; - static Timer timer (where); + static Timers::Timer timer (where); timer.start(); for (int ml=mglevels-1; ml>=0; --ml) { @@ -727,7 +721,7 @@ namespace Carpet { void ScheduleTraverse (char const * const where, char const * const name, cGH * const cctkGH) { - Timer timer(name); + Timers::Timer timer(name); timer.start(); ostringstream infobuf; infobuf << "Scheduling " << name; @@ -739,7 +733,7 @@ namespace Carpet { void OutputGH (char const * const where, cGH * const cctkGH) { - static Timer timer("OutputGH"); + static Timers::Timer timer("OutputGH"); timer.start(); CCTK_OutputGH (cctkGH); timer.stop(); diff --git a/Carpet/Carpet/src/Initialise.cc b/Carpet/Carpet/src/Initialise.cc index 7440b5cdc..388f35c9b 100644 --- a/Carpet/Carpet/src/Initialise.cc +++ b/Carpet/Carpet/src/Initialise.cc @@ -15,10 +15,10 @@ #include +#include +#include + #include -#include -#include -#include @@ -84,7 +84,7 @@ namespace Carpet { cctkGH->cctk_time = global_time; cctkGH->cctk_delta_time = delta_time; - static Timer timer ("Initialise"); + static Timers::Timer timer ("Initialise"); timer.start(); // Delay checkpoint until MPI has been initialised @@ -134,15 +134,11 @@ namespace Carpet { timer.stop(); if (output_timers_every > 0) { - TimerSet::writeData (cctkGH, timer_file); + Timers::CactusTimerSet::writeData (cctkGH, timer_file); } - if (output_initialise_timer_tree) - { - TimerNode *it = main_timer_tree.root->getChildTimer("Initialise"); - double total_avg, total_max; - it->getGlobalTime(total_avg, total_max); - it->print(cout, total_max, 0, timer_tree_threshold_percentage, timer_tree_output_precision); + if (output_initialise_timer_tree) { + Timers::Timer::outputTree("Initialise"); } Waypoint ("Done with initialisation"); @@ -162,7 +158,7 @@ namespace Carpet { CallSetup (cGH * const cctkGH) { char const * const where = "CallSetup"; - static Timer timer (where); + static Timers::Timer timer (where); timer.start(); BEGIN_MGLEVEL_LOOP(cctkGH) { @@ -206,7 +202,7 @@ namespace Carpet { CallRecoverVariables (cGH * const cctkGH) { char const * const where = "CallRecoverVariables"; - static Timer timer (where); + static Timers::Timer timer (where); timer.start(); DECLARE_CCTK_PARAMETERS; @@ -273,7 +269,7 @@ namespace Carpet { DECLARE_CCTK_PARAMETERS; char const * const where = "CallPostRecoverVariables"; - static Timer timer (where); + static Timers::Timer timer (where); timer.start(); for (int rl=0; rl=0; --ml) { @@ -546,7 +542,7 @@ namespace Carpet { CallPostInitial (cGH * const cctkGH) { char const * const where = "CallPostInitial"; - static Timer timer (where); + static Timers::Timer timer (where); timer.start(); for (int rl=0; rl + #include #include @@ -38,7 +40,6 @@ #include #include #include -#include diff --git a/Carpet/Carpet/src/OutputGH.cc b/Carpet/Carpet/src/OutputGH.cc index 6c2c4c311..8c9d8c4ac 100644 --- a/Carpet/Carpet/src/OutputGH.cc +++ b/Carpet/Carpet/src/OutputGH.cc @@ -6,10 +6,11 @@ #include #include +#include + #include #include -#include @@ -23,7 +24,7 @@ namespace Carpet { { DECLARE_CCTK_PARAMETERS; - static Timer timer ("OutputGH"); + static Timers::Timer timer ("OutputGH"); timer.start(); Checkpoint ("OutputGH"); @@ -34,7 +35,7 @@ namespace Carpet { return -1; } - static vector timers; + static vector timers; timers.resize (num_methods, NULL); int num_vars = 0; @@ -48,7 +49,7 @@ namespace Carpet { buf << method->implementation << "::" << method->name << " [" << handle << "]"; - timers.AT(handle) = new Timer (buf.str().c_str()); + timers.AT(handle) = new Timers::Timer (buf.str().c_str()); } timers.AT(handle)->start(); diff --git a/Carpet/Carpet/src/Poison.cc b/Carpet/Carpet/src/Poison.cc index 19c51d363..21310e82e 100644 --- a/Carpet/Carpet/src/Poison.cc +++ b/Carpet/Carpet/src/Poison.cc @@ -7,11 +7,12 @@ #include #include +#include + #include #include #include -#include "Timers.hh" namespace Carpet { @@ -33,7 +34,7 @@ namespace Carpet { if (not poison_new_timelevels) return; - Timer timer("Poison"); + Timers::Timer timer("Poison"); timer.start(); for (int group=0; group + #include #include @@ -39,7 +41,6 @@ #include #include #include -#include @@ -92,7 +93,7 @@ namespace Carpet { CheckRegions (gh::mregs const & regsss) { char const * const where = "CheckRegions"; - static Timer timer (where); + static Timers::Timer timer (where); timer.start(); // At least one multigrid level @@ -150,7 +151,7 @@ namespace Carpet { DECLARE_CCTK_PARAMETERS; char const * const where = "Regrid"; - static Timer timer (where); + static Timers::Timer timer (where); timer.start(); Checkpoint ("Regridding level %d...", reflevel); @@ -267,7 +268,7 @@ namespace Carpet { DECLARE_CCTK_PARAMETERS; char const * const where = "RegridMap"; - static Timer timer (where); + static Timers::Timer timer (where); timer.start(); Waypoint ("Regridding map %d...", m); @@ -327,7 +328,7 @@ namespace Carpet { DECLARE_CCTK_PARAMETERS; char const * const where = "PostRegrid"; - static Timer timer (where); + static Timers::Timer timer (where); timer.start(); // Calculate new number of levels @@ -390,7 +391,7 @@ namespace Carpet { bool const do_init) { char const * const where = "Recompose"; - static Timer timer (where); + static Timers::Timer timer (where); timer.start(); bool did_recompose = false; @@ -422,7 +423,7 @@ namespace Carpet { bool const do_init) { char const * const where = "RegridFree"; - static Timer timer (where); + static Timers::Timer timer (where); timer.start(); Checkpoint ("Freeing after regridding level %d...", reflevel); diff --git a/Carpet/Carpet/src/Restrict.cc b/Carpet/Carpet/src/Restrict.cc index 6dc040c23..3598000f8 100644 --- a/Carpet/Carpet/src/Restrict.cc +++ b/Carpet/Carpet/src/Restrict.cc @@ -7,11 +7,12 @@ #include +#include + #include #include #include -#include @@ -63,7 +64,7 @@ namespace Carpet { // Restrict { - static Timer timer ("Restrict"); + static Timers::Timer timer ("Restrict"); timer.start(); RestrictGroups (cctkGH, groups); timer.stop(); @@ -75,7 +76,7 @@ namespace Carpet { // be necessary. #if 0 { - static Timer timer ("RestrictSync"); + static Timers::Timer timer ("RestrictSync"); timer.start(); SyncGroups (cctkGH, groups); timer.stop(); @@ -88,9 +89,9 @@ namespace Carpet { static void RestrictGroups (const cGH* cctkGH, const vector& groups) { DECLARE_CCTK_PARAMETERS; - static vector timers; + static vector timers; if (timers.empty()) { - timers.push_back(new Timer("comm_state[0].create")); + timers.push_back(new Timers::Timer("comm_state[0].create")); for (astate state = static_cast(0); state != state_done; state = static_cast(static_cast(state)+1)) @@ -98,15 +99,15 @@ namespace Carpet { ostringstream name1; name1 << "comm_state[" << timers.size() << "]" << "." << tostring(state) << ".user"; - timers.push_back(new Timer(name1.str())); + timers.push_back(new Timers::Timer(name1.str())); ostringstream name2; name2 << "comm_state[" << timers.size() << "]" << "." << tostring(state) << ".step"; - timers.push_back(new Timer(name2.str())); + timers.push_back(new Timers::Timer(name2.str())); } } - vector::iterator ti = timers.begin(); + vector::iterator ti = timers.begin(); (*ti)->start(); for (comm_state state; not state.done(); state.step()) { (*ti)->stop(); ++ti; (*ti)->start(); diff --git a/Carpet/Carpet/src/SetupGH.cc b/Carpet/Carpet/src/SetupGH.cc index f984f50eb..dfbf05fa1 100644 --- a/Carpet/Carpet/src/SetupGH.cc +++ b/Carpet/Carpet/src/SetupGH.cc @@ -27,6 +27,8 @@ #include +#include + #include #include #include @@ -37,7 +39,6 @@ #include #include -#include "Timers.hh" @@ -546,7 +547,7 @@ namespace Carpet { // Say hello - Timer timer("CarpetStartup"); + Timers::Timer timer("CarpetStartup"); timer.start(); Waypoint ("Setting up the grid hierarchy"); @@ -823,7 +824,7 @@ namespace Carpet { // Allocate grid hierarchy - Timer timer("AllocateGridHierarchy"); + Timers::Timer timer("AllocateGridHierarchy"); timer.start(); vhh.resize(maps); vhh.AT(m) = new gh (spacereffacts, refcentering, @@ -1368,6 +1369,8 @@ namespace Carpet { void set_state (cGH * const cctkGH) { + DECLARE_CCTK_PARAMETERS; + // // Allocate level times // leveltimes.resize (mglevels); // for (int ml=0; ml #include +#include +#include + #include #include -#include -#include -#include @@ -28,7 +28,7 @@ namespace Carpet { const int convlev = 0; cGH* cctkGH = fc->GH[convlev]; - static Timer timer ("Shutdown"); + static Timers::Timer timer ("Shutdown"); timer.start(); for (int rl=reflevels-1; rl>=0; --rl) { BEGIN_REVERSE_MGLEVEL_LOOP(cctkGH) { @@ -62,7 +62,7 @@ namespace Carpet { assert (not ierr); timer.stop(); if (output_timers_every > 0) { - TimerSet::writeData (cctkGH, timer_file); + Timers::CactusTimerSet::writeData (cctkGH, timer_file); } BEGIN_REVERSE_MGLEVEL_LOOP(cctkGH) { @@ -81,27 +81,16 @@ namespace Carpet { - main_timer_tree.root->stop(); - if (output_timer_tree_every > 0) { - TimerNode *et = main_timer_tree.root->getChildTimer("Evolve"); - double total_avg, total_max; - et->getGlobalTime(total_avg, total_max); - et->print(cout, total_max, 0, timer_tree_threshold_percentage, timer_tree_output_precision); - mode_timer_tree.root->getGlobalTime(total_avg, total_max); - mode_timer_tree.root->print(cout, total_max, 0, timer_tree_threshold_percentage, timer_tree_output_precision); + Timers::Timer::outputTree("Evolve"); } if (output_xml_timer_tree) { - main_timer_tree.root->outputXML(out_dir,CCTK_MyProc (cctkGH)); + Timers::Timer::outputTreeXML(); } - // Delete timer tree - delete main_timer_tree.root; main_timer_tree.root = 0; - delete mode_timer_tree.root; mode_timer_tree.root = 0; - // Free all memory, call all destructors for (size_t gi=0; gi -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "TimerNode.hh" - -namespace Carpet { - - using namespace std; - - TimerNode::TimerNode(TimerTree *tree, string name): - d_name(name), d_parent(0), d_tree(tree), d_running(0), timer(0) - { - } - - TimerNode::~TimerNode() - { - for(map::iterator iter=d_children.begin(); - iter!=d_children.end(); ++iter) - { - delete iter->second; - } - d_children.clear(); - delete timer; - } - - string TimerNode::pathName() const - { - assert(d_parent != this); - if (d_parent) - return d_parent->pathName() + string("/") + getName(); - else - return getName(); - } - - void TimerNode::instantiate() - { - assert(!d_running); - d_parent = d_tree->current; - d_tree->current = this; - if (timer == 0) - timer = new CactusTimer(pathName()); - d_tree->current = d_parent; - } - - void TimerNode::start() - { - 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() - { - assert(d_running); - - // A timer can only be stopped if it is the current timer - if(this != d_tree->current) - CCTK_VError (__LINE__, __FILE__, CCTK_THORNSTRING, - "Tried to stop non-current timer '%s'", getName().c_str()); - - timer->stop(); - - d_running = false; - d_tree->current = d_parent; - } - - /// Get the name of the timer - string TimerNode::getName() const - { - assert(d_name.length() > 0); - return d_name; - } - - /// Determine if the timer is running - bool TimerNode::isRunning() const - { - return d_running; - } - - /// Find the child timer that matches the name provided. If it is - /// not found then a new timer with that name is allocated. - TimerNode* TimerNode::getChildTimer(string name) - { - // Find child - TimerNode *child=d_children[name]; - - // If the pointer is null then allocate it - if(child == 0) - d_children[name] = child = new TimerNode(d_tree, name); - - return child; - } - - /// Get the time measured by this timer - double TimerNode::getTime() - { - return timer->getTime(); - } - - /// Get the global time measured by this timer - void TimerNode::getGlobalTime(double& avg, double& max) - { - return timer->getGlobalTime(avg, max); - } - - /// Get the names of all clocks of this timer - vector > TimerNode::getAllTimerNames() const - { - return timer->getAllTimerNames(); - } - - /// Get the values of all clocks of this timer - vector TimerNode::getAllTimerValues() - { - return timer->getAllTimerValues(); - } - - /// Print this node and its children as an ASCII tree - void TimerNode::print(ostream& out, double total, int level, - double threshold, int precision) - { - string space; - - // Compute the level of indentation for this depth - for(int i=0;i values = getAllTimerValues(); - const string hyphens = string(precision-1, '-'); - const string spaces = string(precision-1, ' '); - - if (level == 0) - { - const vector > names = getAllTimerNames(); - - out << "--------" << hyphens - << "--------" << hyphens - << "--------" << hyphens - << "--" << string(tnw, '-'); - for (size_t i=0; i::iterator iter = d_children.begin(); - iter != d_children.end(); iter++) - { - const string timername = iter->first; - const string root_timername = - CarpetLib::broadcast_string(dist::comm(), 0, timername); - if (timername != root_timername) { - CCTK_VError(__LINE__, __FILE__, CCTK_THORNSTRING, - "Timers are inconsistent across processes: root process expects timer %s, this process has timer %s instead", - root_timername.c_str(), timername.c_str()); - } - double child_avg, child_max; - iter->second->getGlobalTime(child_avg, child_max); - if (child_max * 100.0 / total > threshold) { - iter->second->print(out,total,level+1,threshold,precision); - printed_children = true; - } - //children_time += iter->second->getTime(); - children_tavg += child_avg; - } - { - const string timername = "[done]"; - const string root_timername = - CarpetLib::broadcast_string(dist::comm(), 0, timername); - if (timername != root_timername) { - CCTK_VError(__LINE__, __FILE__, CCTK_THORNSTRING, - "Timers are inconsistent across processes: root process expects timer %s, this process has timer %s instead", - root_timername.c_str(), timername.c_str()); - } - } - - if (d_children.size() > 0 && printed_children) { - //const double untimed = t - children_time; - const double untimed = tavg - children_tavg; - - if (100.0 * untimed / total > threshold) { - // Print the untimed portion - out << fixed << setw(pcw) << setprecision(1) - << 100.0 * untimed / total << "%" - << " " << fixed << setw(tw) << setprecision(1) << untimed - << " " - << " | " << space << "untimed" << "\n"; - } - } - out.precision (oldprecision); - out.setf (oldflags); - - if (level == 0) { - out << "--------" << hyphens - << "--------" << hyphens - << "--------" << hyphens - << "--" << string(tnw, '-'); - for (size_t i=0; i "; - out << getTime() << " "; - - // For compactness, only use multiple lines if there are children - if (d_children.size() != 0) - { - out << "\n"; - - // Recursively print the children - for(map::iterator iter=d_children.begin();iter!=d_children.end();++iter) - iter->second->printXML(out,level+1); - out << space; - } - - out << "" << "\n"; - } - - /// Make a string suitable for inclusion in an XML file - string TimerNode::escapeForXML(const string &s) const - { - // XML attributes cannot contain unescaped angle-brackets. As a - // simple solution to this, replace them with | characters. - - string s2(s); - using std::string; - using std::replace; - - replace(s2.begin(), s2.end(), '<', '|'); - replace(s2.begin(), s2.end(), '>', '|'); - replace(s2.begin(), s2.end(), '&', '|'); - - return s2; - } -} diff --git a/Carpet/Carpet/src/TimerNode.hh b/Carpet/Carpet/src/TimerNode.hh deleted file mode 100644 index 5852e8379..000000000 --- a/Carpet/Carpet/src/TimerNode.hh +++ /dev/null @@ -1,119 +0,0 @@ -/* - * - * The MIT License - * - * Copyright (c) 1997-2010 Center for the Simulation of Accidental Fires and - * Explosions (CSAFE), and Scientific Computing and Imaging Institute (SCI), - * University of Utah. - * - * License for the specific language governing rights and limitations under - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * */ - -/* This class was originally written by Justin Luitjens and - subsequently integrated with Cactus/Carpet by Ian Hinder and - heavily modified. */ - -#ifndef TIMERNODE_HH -#define TIMERNODE_HH - -#include -#include -#include -#include -#include -#include - -#include "CactusTimer.hh" - -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 -represents a timer, implemented as a CactusTimer. Each node of the -tree can have zero of more children, where the names of the child -nodes are unique within a single parent, but not necessarily unique -within the entire tree. A tree formed of TimerNode objects represents -the execution profile of the program, inasmuch as it is instrumented -by timers. - -Child nodes of a given name are accessed using the getChildTimer -method, where a node is created with the given name if none exists -already. This ensures that the names of the child timers are unique. - -*/ - -class TimerNode -{ -public: - TimerNode(TimerTree *root, string name); - ~TimerNode(); - - void instantiate(); - void start(); - void stop(); - - string getName() const; - string pathName() const; - - // Finds the child timer that matches the name provided. If it is - // not found then that timer is allocated. - TimerNode* getChildTimer(string name); - - double getTime(); - void getGlobalTime(double& avg, double &max); - vector > getAllTimerNames() const; - vector getAllTimerValues(); - 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); - void outputXML(const string &out_dir, int proc); - -private: - string escapeForXML(const string &s) const; - - string d_name; - std::map d_children; - TimerNode *d_parent; - TimerTree *d_tree; - bool d_running; - CactusTimer *timer; -}; -} - -#endif // TIMERNODE_HH diff --git a/Carpet/Carpet/src/TimerSet.cc b/Carpet/Carpet/src/TimerSet.cc deleted file mode 100644 index 20b81caa6..000000000 --- a/Carpet/Carpet/src/TimerSet.cc +++ /dev/null @@ -1,190 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -#if HAVE_UNISTD_H -# include -# include -#endif - -#include - -#include -#include -#include -#include - -namespace Carpet { - - using namespace std; - - // A global timer set - TimerSet timerSet; - - // Add a timer - void - TimerSet::add (CactusTimer * const timer) - { - timers.push_back (timer); - } - - // Remove a timer - void - TimerSet::remove (CactusTimer * const timer) - { - timers.remove (timer); - } - - // Print all timer names - void - TimerSet::printNames () - const - { - printf ("Timer names:\n"); - int n = 0; - for (list ::const_iterator - itimer = timers.begin(); itimer != timers.end(); ++ itimer) - { - printf (" [%4d] %s\n", n, (* itimer)->name().c_str()); - ++ n; - } - } - - // Print all timer data - void - TimerSet::printData () - { - for (list ::const_iterator - itimer = timers.begin(); itimer != timers.end(); ++ itimer) - { - (* itimer)->printData (); - } - printf ("\n"); - } - - // Print all timer data - void - TimerSet::writeData (cGH const * const cctkGH, - char const * const filename) - { - int const oldfd = redirect (cctkGH, filename); -#if 0 - printf ("********************************************************************************\n"); -#endif - printf ("# Carpet timing information at iteration %d time %g:\n", - cctkGH->cctk_iteration, (double) cctkGH->cctk_time); - timerSet.printData (); - unredirect (oldfd); - } - - // If filename is not empty, then redirect stdout to a file - int - TimerSet::redirect (cGH const * const cctkGH, - char const * const filename) - { - DECLARE_CCTK_PARAMETERS; - - if (CCTK_EQUALS (filename, "")) { - return -1; - } - -#ifndef HAVE_UNISTD_H - CCTK_WARN (1, "Cannot redirect timer output to a file; the operating system does not support this"); - return -1; -#else - - int const myproc = CCTK_MyProc (cctkGH); - char fullname [10000]; - Util_snprintf (fullname, sizeof fullname, - "%s/%s.%04d.txt", out_dir, filename, myproc); - - int flags = O_WRONLY | O_CREAT | O_APPEND; // append - static bool first_time = true; - if (first_time) { - first_time = false; - if (IO_TruncateOutputFiles (cctkGH)) { - flags = O_WRONLY | O_CREAT | O_TRUNC; // truncate - } - } - - // Temporarily redirect stdout - fflush (stdout); - int const oldfd = dup (1); // fd 1 is stdout - int const mode = 0644; // rw-r--r--, or a+r u+w - int const fdfile = open (fullname, flags, mode); - if (fdfile < 0) { - CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, - "Could not open timer output file \"%s\"", fullname); - close (oldfd); - return -1; - } - // close (1); - // int const fd = dup (fdfile); // dup to 1, i.e., stdout again - int const fd = dup2 (fdfile, 1); // dup to 1, i.e., stdout again - assert (fd == 1); - close (fdfile); - return oldfd; -#endif - } - - // Redirect stdout back - void - TimerSet::unredirect (int const oldfd) - { - if (oldfd < 0) return; - -#ifdef HAVE_UNISTD_H - fflush (stdout); - // close (1); - // int const fd = dup (oldfd); - int const fd = dup2 (oldfd, 1); - if (not (fd == 1)) { - fprintf(stderr, "oldfd=%d fd=%d\n", oldfd, fd); - } - assert (fd == 1); - close (oldfd); -#endif - } - - - /// Reduce each timers in the set across all processes and update - /// each timer with the reduction information. - void TimerSet::reduce() - { - // Collect timer names that each process has - - // Construct union of all timer names, sort canonically and assign - // integer identifiers - - // For each timer, identify which processes have that timer - - // Reduce the timer across all those processes (return to root proc only) - - serialise(cout); - } - - ostream& TimerSet::serialise(ostream &os) - { - for (list ::const_iterator - itimer = timers.begin(); itimer != timers.end(); ++ itimer) - { - (*itimer)->serialise(os); - os << endl; - } - return os; - } - -/* - - -Each process has a list of (string,real) pairs. I want to return a -list of these where the reals have been reduced using a reduction -operator. Not all processes have the same strings present. - */ - -} // namespace Carpet diff --git a/Carpet/Carpet/src/TimerSet.hh b/Carpet/Carpet/src/TimerSet.hh deleted file mode 100644 index b2d2fdd93..000000000 --- a/Carpet/Carpet/src/TimerSet.hh +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef TIMERSET_HH -#define TIMERSET_HH - -#include -#include - -#include -#include "CactusTimer.hh" - -//class Carpet::TimerSet; - -//ostream& operator <<(ostream &os, const Carpet::TimerSet &obj); - -namespace Carpet { - - class TimerSet; - extern TimerSet timerSet; - - using namespace std; - - // A set of timers - class TimerSet { - - list timers; - - public: - - // Add a timer - void - add (CactusTimer * timer); - - // Remove a timer - void - remove (CactusTimer * timer); - - // Print all timer names - void - printNames () - const; - - // Print timer data - void - printData (); - - // Write all timer data - static void writeData (cGH const * cctkGH, char const * filename); - - void reduce(); - - ostream& serialise(ostream &os); - - private: - - // If filename is not empty, then redirect stdout to a file - static - int - redirect (cGH const * cctkGH, - char const * filename); - - // Redirect stdout back - static - void - unredirect (int oldfd); - - }; // class TimerSet - -} // namespace Carpet - -#endif // TIMERSET_HH diff --git a/Carpet/Carpet/src/Timers.cc b/Carpet/Carpet/src/Timers.cc deleted file mode 100644 index f783c92de..000000000 --- a/Carpet/Carpet/src/Timers.cc +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -#if HAVE_UNISTD_H -# include -# include -#endif - -#include - -#include -#include -#include "variables.hh" - - -namespace Carpet { - - using namespace std; - -/********************************************************************* - Timer - *********************************************************************/ - - /// 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) - { - } - - /// Destroy a timer - Timer::~Timer () - { - } - - /// Insert the timer into the tree of timers as a child of the most - /// recently started timer that has not been stopped. Don't start - /// the timer. This routine ensures a timer is created even if it is - /// never started. - void Timer::instantiate () - { - TimerNode *current_timer = d_tree->current; - assert(current_timer); - current_timer->getChildTimer(name())->instantiate(); - } - - /// Start the timer and insert it into the tree of timers as a child - /// of the most recently started timer that has not been stopped. - void Timer::start () - { - TimerNode *current_timer = d_tree->current; - if (not d_tree->root) return; // do nothing if there is no root - assert(current_timer); - current_timer->getChildTimer(name())->start(); - } - - /// Stop the timer - it must be the most recently started timer - void Timer::stop () - { - TimerNode *current = d_tree->current; - if (not d_tree->root) return; // do nothing if there is no root - if (current->getName() != name()) - CCTK_VWarn (0, __LINE__, __FILE__, CCTK_THORNSTRING, - "Trying to stop enclosing timer '%s' before enclosed time '%s'", - name().c_str(), current->getName().c_str()); - current->stop(); - } - - /// Return the name of the timer - string Timer::name () const - { - return d_name; - } - - /// Return the current time of the timer as a double - double Timer::getTime () - { - return d_tree->current->getTime(); - } -} // namespace Carpet diff --git a/Carpet/Carpet/src/Timers.hh b/Carpet/Carpet/src/Timers.hh deleted file mode 100644 index fdd31773f..000000000 --- a/Carpet/Carpet/src/Timers.hh +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef TIMERS_HH -#define TIMERS_HH - -#include -#include - -#include - - - -namespace Carpet { - - using namespace std; - -/** - -This class allows the user to instrument their code with named timers -which can then be later queried to determine the amount of time spent -in the code between "start" and "end" calls. The sequence of start -and end calls of different timers determines a dynamical hierarchical -tree structure implemented by the TimerNode class. - -To use this class, create a timer object with a particular name: - - Timer timer("MyTimer") - -Now wrap the code to be timed with start() and stop() calls: - - timer.start() - - some code - - timer.stop() - -You can start and stop a timer multiple times. The timer will be -created as a child of whatever timer is current (i.e. has been started -and not stopped) at the time of the first start() call. Any timers -which are started between the start() and stop(), whether or not they -are in the same file, will be stored as children of this timer. - -Timer objects must be started and stopped in a non-overlapping manner. -Specifically, a timer cannot be stopped if it is not the most recently -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 (); - void start (); - void stop (); - string name () const; - double getTime(); - - private: - - string d_name; - TimerTree *d_tree; - }; - - // Macros for using timers in a convenient manner - -#define TIMING_BEGIN(name) \ - do { \ - static Carpet::Timer timer (name); \ - timer.start(); \ - { -#define TIMING_END \ - } \ - timer.stop(); \ - } while (0) - -} // namespace Carpet - -#endif // TIMERS_HH diff --git a/Carpet/Carpet/src/make.code.defn b/Carpet/Carpet/src/make.code.defn index 30f012897..f28c61427 100644 --- a/Carpet/Carpet/src/make.code.defn +++ b/Carpet/Carpet/src/make.code.defn @@ -1,8 +1,7 @@ # Main make.code.defn file for thorn Carpet -*-Makefile-*- # Source files in this directory -SRCS = CactusTimer.cc \ - CallFunction.cc \ +SRCS = CallFunction.cc \ CarpetBasegrid.cc \ CarpetParamCheck.cc \ CarpetStartup.cc \ @@ -21,9 +20,6 @@ SRCS = CactusTimer.cc \ SetupGH.cc \ Shutdown.cc \ Storage.cc \ - Timers.cc \ - TimerNode.cc \ - TimerSet.cc \ Timing.cc \ UnusedMask.cc \ adler32.cc \ diff --git a/Carpet/Carpet/src/modes.cc b/Carpet/Carpet/src/modes.cc index 9af0039eb..5bd57e758 100644 --- a/Carpet/Carpet/src/modes.cc +++ b/Carpet/Carpet/src/modes.cc @@ -9,6 +9,8 @@ #include #include +#include + #include #include #include @@ -16,7 +18,7 @@ #include -#include "Timers.hh" + namespace Carpet { @@ -86,9 +88,9 @@ namespace Carpet { assert (ml>=0 and mlcctk_delta_time = 0.0; @@ -295,7 +290,7 @@ namespace Carpet { mglevel = -1; mglevelfact = -deadbeef; cctkGH->cctk_convlevel = -deadbeef; - + ftimer.stop(); assert (is_meta_mode()); @@ -313,9 +308,9 @@ namespace Carpet { assert (rl>=0 and rlcctk_mode = CCTK_MODE_LEVEL; @@ -349,12 +344,12 @@ namespace Carpet { } else { tt->set_time (mglevel, reflevel, timelevel, cctkGH->cctk_time); } - + ftimer.stop(); - + ostringstream mode_s; - mode_s << "level(" << rl << ")"; - Timer timer(mode_s.str(), &mode_timer_tree); + mode_s << "level(" << reflevel << ")"; + Timers::Timer timer(mode_s.str(), 1); timer.start(); assert (is_level_mode()); @@ -370,15 +365,12 @@ namespace Carpet { Checkpoint ("Leaving level mode"); - if (mode_timer_tree.current != mode_timer_tree.root) - { - ostringstream mode_s; - mode_s << "level(" << reflevel << ")"; - Timer timer(mode_s.str(), &mode_timer_tree); - timer.stop(); - } - - Timer ftimer("leave_level_mode", &mode_timer_tree); + ostringstream mode_s; + mode_s << "level(" << reflevel << ")"; + Timers::Timer timer(mode_s.str(), 1); + timer.stop(); + + static Timers::Timer ftimer("leave_level_mode", 1); ftimer.start(); CCTK_INT const deadbeef = get_deadbeef(); @@ -440,7 +432,7 @@ namespace Carpet { or grouptype == CCTK_GF); Checkpoint ("Entering singlemap mode"); - Timer ftimer("enter_singlemap_mode", &mode_timer_tree); + static Timers::Timer ftimer("enter_singlemap_mode", 1); ftimer.start(); // Set mode @@ -486,15 +478,14 @@ namespace Carpet { } // if mc_grouptype ftimer.stop(); - - if (include_maps_in_mode_timer_tree) - { + + if (include_maps_in_mode_timer_tree) { ostringstream mode_s; mode_s << "map(" << map << ")"; - Timer timer(mode_s.str(), &mode_timer_tree); + Timers::Timer timer(mode_s.str(), 1); timer.start(); } - + assert (is_singlemap_mode()); } @@ -508,15 +499,14 @@ namespace Carpet { Checkpoint ("Leaving singlemap mode"); - if (mode_timer_tree.current != mode_timer_tree.root && include_maps_in_mode_timer_tree) - { + if (include_maps_in_mode_timer_tree) { ostringstream mode_s; mode_s << "map(" << map << ")"; - Timer timer(mode_s.str(), &mode_timer_tree); + Timers::Timer timer(mode_s.str(), 1); timer.stop(); } - - Timer ftimer("leave_singlemap_mode", &mode_timer_tree); + + static Timers::Timer ftimer("leave_singlemap_mode", 1); ftimer.start(); assert (mc_grouptype == CCTK_SCALAR or mc_grouptype == CCTK_ARRAY @@ -566,7 +556,7 @@ namespace Carpet { carpetGH.map = map = -1; ftimer.stop(); - + assert (is_level_mode()); } @@ -589,7 +579,7 @@ namespace Carpet { } Checkpoint ("Entering local mode"); - Timer ftimer("enter_local_mode", &mode_timer_tree); + static Timers::Timer ftimer("enter_local_mode", 1); ftimer.start(); // Set mode @@ -714,11 +704,8 @@ namespace Carpet { ftimer.stop(); - if (include_local_mode_in_mode_timer_tree) - { - ostringstream mode_s; - mode_s << "local"; - Timer timer(mode_s.str(), &mode_timer_tree); + if (include_local_mode_in_mode_timer_tree) { + Timers::Timer timer("local", 1); timer.start(); } @@ -735,17 +722,14 @@ namespace Carpet { Checkpoint ("Leaving local mode"); - if (mode_timer_tree.current != mode_timer_tree.root && include_local_mode_in_mode_timer_tree) - { - ostringstream mode_s; - mode_s << "local"; - Timer timer(mode_s.str(), &mode_timer_tree); + if (include_local_mode_in_mode_timer_tree) { + Timers::Timer timer("local", 1); timer.stop(); } - - Timer ftimer("leave_local_mode", &mode_timer_tree); + + static Timers::Timer ftimer("leave_local_mode", 1); ftimer.start(); - + if (mc_grouptype == CCTK_GF) { CCTK_INT const deadbeef = get_deadbeef(); @@ -810,7 +794,7 @@ namespace Carpet { local_component = -1; ftimer.stop(); - + assert (is_singlemap_mode()); } diff --git a/Carpet/Carpet/src/variables.cc b/Carpet/Carpet/src/variables.cc index 7351e4073..a75323ed9 100644 --- a/Carpet/Carpet/src/variables.cc +++ b/Carpet/Carpet/src/variables.cc @@ -26,9 +26,6 @@ namespace Carpet { // Maximum refinement factors on finest possible grid int maxtimereflevelfact; vect maxspacereflevelfact; - - TimerTree main_timer_tree; - TimerTree mode_timer_tree; // Base multigrid level int basemglevel; diff --git a/Carpet/Carpet/src/variables.hh b/Carpet/Carpet/src/variables.hh index c8eecaaf1..235874ada 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 { @@ -93,9 +93,6 @@ namespace Carpet { // Current refinement factors extern int timereflevelfact; extern vect spacereflevelfact; - - extern TimerTree main_timer_tree; - extern TimerTree mode_timer_tree; // Current multigrid factor extern int mglevelfact; diff --git a/Carpet/CarpetIOASCII/interface.ccl b/Carpet/CarpetIOASCII/interface.ccl index 1d377f38c..10ccfceff 100644 --- a/Carpet/CarpetIOASCII/interface.ccl +++ b/Carpet/CarpetIOASCII/interface.ccl @@ -2,8 +2,9 @@ IMPLEMENTS: IOASCII +uses include header: Timer.hh + uses include header: carpet.hh -uses include header: CarpetTimers.hh uses include header: dist.hh diff --git a/Carpet/CarpetIOASCII/src/ioascii.cc b/Carpet/CarpetIOASCII/src/ioascii.cc index 9c860eec5..3707b3c25 100644 --- a/Carpet/CarpetIOASCII/src/ioascii.cc +++ b/Carpet/CarpetIOASCII/src/ioascii.cc @@ -15,16 +15,17 @@ #include #include -#include "cctk.h" -#include "cctk_Parameters.h" -#include "util_Network.h" -#include "util_Table.h" +#include +#include +#include +#include + +#include #include "CactusBase/IOUtil/src/ioGH.h" #include "CactusBase/IOUtil/src/ioutil_Utils.h" #include "carpet.hh" -#include "CarpetTimers.hh" #include "typeprops.hh" @@ -232,7 +233,7 @@ namespace CarpetIOASCII { { ostringstream timer_name; timer_name << "OutputGH<" << outdim << ">"; - Carpet::Timer timer(timer_name.str()); + Timers::Timer timer(timer_name.str()); timer.start(); for (int vi=0; vi #include -#include "cctk.h" -#include "cctk_Arguments.h" -#include "cctk_Functions.h" -#include "cctk_Parameters.h" +#include +#include +#include #include "CactusBase/IOUtil/src/ioGH.h" #include "CactusBase/IOUtil/src/ioutil_Utils.h" +#include + #include "carpet.hh" -#include "CarpetTimers.hh" #include "typeprops.hh" @@ -181,7 +181,7 @@ namespace CarpetIOBasic { DECLARE_CCTK_ARGUMENTS; DECLARE_CCTK_PARAMETERS; - static Carpet::Timer timer ("OutputGH"); + static Timers::Timer timer ("OutputGH"); timer.start(); if (TimeToOutput (cctkGH)) { diff --git a/Carpet/CarpetIOHDF5/interface.ccl b/Carpet/CarpetIOHDF5/interface.ccl index 471ef0ed0..bff837764 100644 --- a/Carpet/CarpetIOHDF5/interface.ccl +++ b/Carpet/CarpetIOHDF5/interface.ccl @@ -4,8 +4,9 @@ IMPLEMENTS: IOHDF5 includes header: CarpetIOHDF5.hh in CarpetIOHDF5.hh +uses include header: Timer.hh + uses include header: carpet.hh -uses include header: CarpetTimers.hh uses include header: defs.hh diff --git a/Carpet/CarpetIOHDF5/src/CarpetIOHDF5.cc b/Carpet/CarpetIOHDF5/src/CarpetIOHDF5.cc index 4379de113..e142c9fac 100644 --- a/Carpet/CarpetIOHDF5/src/CarpetIOHDF5.cc +++ b/Carpet/CarpetIOHDF5/src/CarpetIOHDF5.cc @@ -9,16 +9,16 @@ #include #include -#include "util_Table.h" -#include "cctk.h" -#include "cctk_Arguments.h" -#include "cctk_Parameters.h" -#include "cctk_Version.h" +#include +#include +#include +#include +#include #include "CactusBase/IOUtil/src/ioGH.h" #include "CactusBase/IOUtil/src/ioutil_CheckpointRecovery.h" -#include "CarpetTimers.hh" +#include #include "CarpetIOHDF5.hh" @@ -562,7 +562,7 @@ static void CheckSteerableParameters (const cGH *const cctkGH, static int OutputGH (const cGH* const cctkGH) { - static Carpet::Timer timer ("OutputGH"); + static Timers::Timer timer ("OutputGH"); timer.start(); for (int vindex = CCTK_NumVars () - 1; vindex >= 0; vindex--) { if (TimeToOutput (cctkGH, vindex)) { diff --git a/Carpet/CarpetIOHDF5/src/OutputSlice.cc b/Carpet/CarpetIOHDF5/src/OutputSlice.cc index 2f67d031b..9a84d1ac3 100644 --- a/Carpet/CarpetIOHDF5/src/OutputSlice.cc +++ b/Carpet/CarpetIOHDF5/src/OutputSlice.cc @@ -8,12 +8,12 @@ #include #include -#include "cctk.h" -#include "util_Table.h" +#include +#include #include "CactusBase/IOUtil/src/ioGH.h" -#include "CarpetTimers.hh" +#include #include "typeprops.hh" @@ -234,7 +234,7 @@ namespace CarpetIOHDF5 { ostringstream timer_name; timer_name << "OutputGH<" << outdim << ">"; - Carpet::Timer timer(timer_name.str()); + Timers::Timer timer(timer_name.str()); timer.start(); for (int vi=0; vi #include -#include "cctk.h" -#include "cctk_Arguments.h" -#include "cctk_Functions.h" -#include "cctk_Parameters.h" -#include "util_Network.h" +#include +#include +#include +#include + +#include #include "CactusBase/IOUtil/src/ioGH.h" #include "CactusBase/IOUtil/src/ioutil_Utils.h" #include "carpet.hh" -#include "CarpetTimers.hh" #include "typeprops.hh" @@ -163,7 +163,7 @@ namespace CarpetIOScalar { int OutputGH (const cGH * const cctkGH) { - static Carpet::Timer timer ("OutputGH"); + static Timers::Timer timer ("OutputGH"); timer.start(); for (int vindex=0; vindex& v) { #include "th.hh" #include "vect.hh" -#include "CarpetTimers.hh" - template int ipow (int x, int y); template CCTK_REAL ipow (CCTK_REAL x, int y); //template vect ipow (vect x, int y); diff --git a/Carpet/CarpetLib/src/dh.cc b/Carpet/CarpetLib/src/dh.cc index 44a87c0fd..b66c80188 100644 --- a/Carpet/CarpetLib/src/dh.cc +++ b/Carpet/CarpetLib/src/dh.cc @@ -5,7 +5,7 @@ #include #include -#include "CarpetTimers.hh" +#include #include "mpi_string.hh" #include "bbox.hh" @@ -271,7 +271,7 @@ regrid (bool const do_init) { DECLARE_CCTK_PARAMETERS; - static Carpet::Timer timer ("CarpetLib::dh::regrid"); + static Timers::Timer timer ("CarpetLib::dh::regrid"); timer.start(); CHECKPOINT; @@ -323,7 +323,7 @@ regrid (bool const do_init) // Domain: - static Carpet::Timer timer_domain ("domain"); + static Timers::Timer timer_domain ("domain"); timer_domain.start(); ibbox const & domain_exterior = h.baseextent(ml,rl); @@ -348,7 +348,7 @@ regrid (bool const do_init) - static Carpet::Timer timer_region ("region"); + static Timers::Timer timer_region ("region"); timer_region.start(); for (int c = 0; c < h.components(rl); ++ c) { @@ -517,7 +517,7 @@ regrid (bool const do_init) // Conjunction of all buffer zones: - static Carpet::Timer timer_buffers ("buffers"); + static Timers::Timer timer_buffers ("buffers"); timer_buffers.start(); // Enlarge active part of domain @@ -656,7 +656,7 @@ regrid (bool const do_init) // Test constituency relations: - static Carpet::Timer timer_test ("test"); + static Timers::Timer timer_test ("test"); timer_test.start(); for (int c = 0; c < h.components(rl); ++ c) { @@ -697,14 +697,14 @@ regrid (bool const do_init) // Communication schedule: - static Carpet::Timer timer_comm ("comm"); + static Timers::Timer timer_comm ("comm"); timer_comm.start(); - static Carpet::Timer timer_comm_mgrest ("mgrest"); - static Carpet::Timer timer_comm_mgprol ("mgprol"); - static Carpet::Timer timer_comm_refprol ("refprol"); - static Carpet::Timer timer_comm_sync ("sync"); - static Carpet::Timer timer_comm_refbndprol ("refbndprol"); + static Timers::Timer timer_comm_mgrest ("mgrest"); + static Timers::Timer timer_comm_mgprol ("mgprol"); + static Timers::Timer timer_comm_refprol ("refprol"); + static Timers::Timer timer_comm_sync ("sync"); + static Timers::Timer timer_comm_refbndprol ("refbndprol"); timer_comm_mgrest.instantiate (); timer_comm_mgprol.instantiate (); timer_comm_refprol.instantiate (); @@ -1017,7 +1017,7 @@ regrid (bool const do_init) // Refinement restriction: - static Carpet::Timer timer_comm_refrest ("refrest"); + static Timers::Timer timer_comm_refrest ("refrest"); timer_comm_refrest.start(); if (rl > 0) { @@ -1120,7 +1120,7 @@ regrid (bool const do_init) // Refinement refluxing: - static Carpet::Timer timer_comm_reflux ("reflux"); + static Timers::Timer timer_comm_reflux ("reflux"); timer_comm_reflux.start(); // If there is no coarser level, do nothing @@ -1416,7 +1416,7 @@ regrid (bool const do_init) // Reduction mask: - static Carpet::Timer timer_mask ("mask"); + static Timers::Timer timer_mask ("mask"); timer_mask.start(); for (int lc=0; lc 0) { int const orl = rl - 1; fast_dboxes & fast_olevel = fast_boxes.AT(ml).AT(orl); - static Carpet::Timer timer_bcast_comm_ref_rest ("ref_rest"); + static Timers::Timer timer_bcast_comm_ref_rest ("ref_rest"); timer_bcast_comm_ref_rest.start(); broadcast_schedule (fast_level_otherprocs, fast_olevel, & fast_dboxes::fast_ref_rest_sendrecv); @@ -1944,7 +1944,7 @@ regrid (bool const do_init) if (rl > 0) { int const orl = rl - 1; fast_dboxes & fast_olevel = fast_boxes.AT(ml).AT(orl); - static Carpet::Timer timer_bcast_comm_ref_refl ("ref_refl"); + static Timers::Timer timer_bcast_comm_ref_refl ("ref_refl"); timer_bcast_comm_ref_refl.start(); for (int dir = 0; dir < dim; ++ dir) { for (int face = 0; face < 2; ++ face) { @@ -1957,7 +1957,7 @@ regrid (bool const do_init) timer_bcast_comm_ref_refl.stop(); } - static Carpet::Timer timer_bcast_comm_ref_refl_prol + static Timers::Timer timer_bcast_comm_ref_refl_prol ("ref_refl_prol"); timer_bcast_comm_ref_refl_prol.start(); for (int dir = 0; dir < dim; ++ dir) { @@ -1972,13 +1972,13 @@ regrid (bool const do_init) // TODO: Maybe broadcast old2new schedule only if do_init is // set - static Carpet::Timer timer_bcast_comm_old2new_sync ("old2new_sync"); + static Timers::Timer timer_bcast_comm_old2new_sync ("old2new_sync"); timer_bcast_comm_old2new_sync.start(); broadcast_schedule (fast_level_otherprocs, fast_level, & fast_dboxes::fast_old2new_sync_sendrecv); timer_bcast_comm_old2new_sync.stop(); - static Carpet::Timer timer_bcast_comm_old2new_ref_prol + static Timers::Timer timer_bcast_comm_old2new_ref_prol ("old2new_ref_prol"); timer_bcast_comm_old2new_ref_prol.start(); broadcast_schedule (fast_level_otherprocs, fast_level, @@ -2144,7 +2144,7 @@ broadcast_schedule (vector & fast_level_otherprocs, fast_dboxes & fast_level, srpvect fast_dboxes::* const schedule_item) { - static Carpet::Timer timer_bs1 ("CarpetLib::dh::bs1"); + static Timers::Timer timer_bs1 ("CarpetLib::dh::bs1"); timer_bs1.start(); vector send (dist::size()); for (int p=0; p & fast_level_otherprocs, } timer_bs1.stop(); - static Carpet::Timer timer_bs2 ("CarpetLib::dh::bs2"); + static Timers::Timer timer_bs2 ("CarpetLib::dh::bs2"); timer_bs2.start(); srpvect const recv = alltoallv1 (dist::comm(), send); timer_bs2.stop(); - static Carpet::Timer timer_bs3 ("CarpetLib::dh::bs3"); + static Timers::Timer timer_bs3 ("CarpetLib::dh::bs3"); timer_bs3.start(); (fast_level.*schedule_item).insert ((fast_level.*schedule_item).end(), recv.begin(), recv.end()); @@ -2197,7 +2197,7 @@ recompose (int const rl, bool const do_prolongate) assert (rl>=0 and rl::iterator f=gfs.begin(); f!=gfs.end(); ++f) { diff --git a/Carpet/CarpetLib/src/ggf.cc b/Carpet/CarpetLib/src/ggf.cc index d9fde10df..934d895e8 100644 --- a/Carpet/CarpetLib/src/ggf.cc +++ b/Carpet/CarpetLib/src/ggf.cc @@ -7,7 +7,7 @@ #include #include -#include "CarpetTimers.hh" +#include #include "defs.hh" #include "dh.hh" @@ -121,7 +121,7 @@ void ggf::set_timelevels (const int ml, const int rl, const int new_timelevels) void ggf::recompose_crop () { // Free storage that will not be needed - static Carpet::Timer timer ("CarpetLib::ggf::recompose_crop"); + static Timers::Timer timer ("CarpetLib::ggf::recompose_crop"); timer.start (); for (int ml=0; ml #include -#include "CarpetTimers.hh" +#include #include "defs.hh" #include "dh.hh" @@ -91,7 +91,7 @@ regrid (rregs const & superregs, mregs const & regs, bool const do_init) { DECLARE_CCTK_PARAMETERS; - static Carpet::Timer timer ("CarpetLib::gh::regrid"); + static Timers::Timer timer ("CarpetLib::gh::regrid"); timer.start(); superregions = superregs; diff --git a/Carpet/CarpetRegrid2/interface.ccl b/Carpet/CarpetRegrid2/interface.ccl index ee2bb307d..ceeaece5d 100644 --- a/Carpet/CarpetRegrid2/interface.ccl +++ b/Carpet/CarpetRegrid2/interface.ccl @@ -2,6 +2,8 @@ IMPLEMENTS: CarpetRegrid2 +USES INCLUDE HEADER: Timer.hh + USES INCLUDE HEADER: bbox.hh USES INCLUDE HEADER: bboxset.hh USES INCLUDE HEADER: defs.hh @@ -12,7 +14,6 @@ USES INCLUDE HEADER: region.hh USES INCLUDE HEADER: vect.hh USES INCLUDE HEADER: carpet.hh -USES INCLUDE HEADER: CarpetTimers.hh diff --git a/Carpet/CarpetRegrid2/src/regrid.cc b/Carpet/CarpetRegrid2/src/regrid.cc index f43f3f898..983a33496 100644 --- a/Carpet/CarpetRegrid2/src/regrid.cc +++ b/Carpet/CarpetRegrid2/src/regrid.cc @@ -11,6 +11,8 @@ #include #include +#include + #include #include #include @@ -20,7 +22,6 @@ #include #include -#include #include "amr.hh" #include "boundary.hh" @@ -485,7 +486,7 @@ namespace CarpetRegrid2 { DECLARE_CCTK_PARAMETERS; char const * const where = "CarpetRegrid2::Regrid"; - static Carpet::Timer timer (where); + static Timers::Timer timer (where); timer.start(); assert (is_singlemap_mode()); @@ -675,7 +676,7 @@ namespace CarpetRegrid2 { DECLARE_CCTK_PARAMETERS; char const * const where = "CarpetRegrid2::RegridMaps"; - static Carpet::Timer timer (where); + static Timers::Timer timer (where); timer.start(); assert (is_level_mode()); diff --git a/Carpet/Timers/README b/Carpet/Timers/README new file mode 100644 index 000000000..60888f344 --- /dev/null +++ b/Carpet/Timers/README @@ -0,0 +1,14 @@ +Cactus Code Thorn Timers +Author(s) : Erik Schnetter +Maintainer(s): Erik Schnetter +Licence : n/a +-------------------------------------------------------------------------- + +1. Purpose + +Provide various kinds of timers: + +CactusTimer: C++ wrapper around standard Cactus timers +CactusTimerSet: knows about all CactusTimers that were ever created +Timer: hierarchical set of CactusTimers +TimerTree: helper class for Timer diff --git a/Carpet/Timers/configuration.ccl b/Carpet/Timers/configuration.ccl new file mode 100644 index 000000000..57a129f66 --- /dev/null +++ b/Carpet/Timers/configuration.ccl @@ -0,0 +1,8 @@ +# Configuration definitions for thorn Timers + +PROVIDES Timers +{ +} + +# This is necessary for some convenient communication routines +REQUIRES CarpetLib diff --git a/Carpet/Timers/doc/documentation.tex b/Carpet/Timers/doc/documentation.tex new file mode 100644 index 000000000..41d7149be --- /dev/null +++ b/Carpet/Timers/doc/documentation.tex @@ -0,0 +1,144 @@ +% *======================================================================* +% Cactus Thorn template for ThornGuide documentation +% Author: Ian Kelley +% Date: Sun Jun 02, 2002 +% $Header$ +% +% Thorn documentation in the latex file doc/documentation.tex +% will be included in ThornGuides built with the Cactus make system. +% The scripts employed by the make system automatically include +% pages about variables, parameters and scheduling parsed from the +% relevant thorn CCL files. +% +% This template contains guidelines which help to assure that your +% documentation will be correctly added to ThornGuides. More +% information is available in the Cactus UsersGuide. +% +% Guidelines: +% - Do not change anything before the line +% % START CACTUS THORNGUIDE", +% except for filling in the title, author, date, etc. fields. +% - Each of these fields should only be on ONE line. +% - Author names should be separated with a \\ or a comma. +% - You can define your own macros, but they must appear after +% the START CACTUS THORNGUIDE line, and must not redefine standard +% latex commands. +% - To avoid name clashes with other thorns, 'labels', 'citations', +% 'references', and 'image' names should conform to the following +% convention: +% ARRANGEMENT_THORN_LABEL +% For example, an image wave.eps in the arrangement CactusWave and +% thorn WaveToyC should be renamed to CactusWave_WaveToyC_wave.eps +% - Graphics should only be included using the graphicx package. +% More specifically, with the "\includegraphics" command. Do +% not specify any graphic file extensions in your .tex file. This +% will allow us to create a PDF version of the ThornGuide +% via pdflatex. +% - References should be included with the latex "\bibitem" command. +% - Use \begin{abstract}...\end{abstract} instead of \abstract{...} +% - Do not use \appendix, instead include any appendices you need as +% standard sections. +% - For the benefit of our Perl scripts, and for future extensions, +% please use simple latex. +% +% *======================================================================* +% +% Example of including a graphic image: +% \begin{figure}[ht] +% \begin{center} +% \includegraphics[width=6cm]{MyArrangement_MyThorn_MyFigure} +% \end{center} +% \caption{Illustration of this and that} +% \label{MyArrangement_MyThorn_MyLabel} +% \end{figure} +% +% Example of using a label: +% \label{MyArrangement_MyThorn_MyLabel} +% +% Example of a citation: +% \cite{MyArrangement_MyThorn_Author99} +% +% Example of including a reference +% \bibitem{MyArrangement_MyThorn_Author99} +% {J. Author, {\em The Title of the Book, Journal, or periodical}, 1 (1999), +% 1--16. {\tt http://www.nowhere.com/}} +% +% *======================================================================* + +% If you are using CVS use this line to give version information +% $Header$ + +\documentclass{article} + +% Use the Cactus ThornGuide style file +% (Automatically used from Cactus distribution, if you have a +% thorn without the Cactus Flesh download this from the Cactus +% homepage at www.cactuscode.org) +\usepackage{../../../../doc/latex/cactus} + +\begin{document} + +% The author of the documentation +\author{Erik Schnetter \textless schnetter@gmail.com\textgreater} + +% The title of the document (not necessarily the name of the Thorn) +\title{Timers} + +% the date your document was last changed, if your document is in CVS, +% please use: +% \date{$ $Date: 2004-01-07 15:12:39 -0500 (Wed, 07 Jan 2004) $ $} +\date{August 07 2013} + +\maketitle + +% Do not delete next line +% START CACTUS THORNGUIDE + +% Add all definitions used in this documentation here +% \def\mydef etc + +% Add an abstract for this thorn's documentation +\begin{abstract} + +\end{abstract} + +% The following sections are suggestive only. +% Remove them or add your own. + +\section{Introduction} + +\section{Physical System} + +\section{Numerical Implementation} + +\section{Using This Thorn} + +\subsection{Obtaining This Thorn} + +\subsection{Basic Usage} + +\subsection{Special Behaviour} + +\subsection{Interaction With Other Thorns} + +\subsection{Examples} + +\subsection{Support and Feedback} + +\section{History} + +\subsection{Thorn Source Code} + +\subsection{Thorn Documentation} + +\subsection{Acknowledgements} + + +\begin{thebibliography}{9} + +\end{thebibliography} + +% Do not delete next line +% END CACTUS THORNGUIDE + +\end{document} diff --git a/Carpet/Timers/interface.ccl b/Carpet/Timers/interface.ccl new file mode 100644 index 000000000..7d07d3a0c --- /dev/null +++ b/Carpet/Timers/interface.ccl @@ -0,0 +1,14 @@ +# Interface definition for thorn Timers + +IMPLEMENTS: Timers + +INCLUDE HEADER: CactusTimer.hh IN CactusTimer.hh +INCLUDE HEADER: CactusTimerSet.hh IN CactusTimerSet.hh +INCLUDE HEADER: Timer.hh IN Timer.hh +INCLUDE HEADER: TimerTree.hh IN TimerTree.hh + + + +# Check whether existing output files should be truncated or not +CCTK_INT FUNCTION IO_TruncateOutputFiles(CCTK_POINTER_TO_CONST IN cctkGH) +REQUIRES FUNCTION IO_TruncateOutputFiles diff --git a/Carpet/Timers/param.ccl b/Carpet/Timers/param.ccl new file mode 100644 index 000000000..2029006c9 --- /dev/null +++ b/Carpet/Timers/param.ccl @@ -0,0 +1,29 @@ +# Parameter definitions for thorn Timers + +SHARES: IO + +USES STRING out_dir + + + +PRIVATE: + +BOOLEAN verbose "Output (debug) messages when a timer is started or stopped" STEERABLE=always +{ +} "no" + +STRING xml_clock "Which clock to use in the XML timer output file" STEERABLE=always +{ + ".*" :: "must be a legal clock name" +} "gettimeofday" + +CCTK_REAL threshold_percentage "The percentage of the root timer below which timers are omitted" STEERABLE=always +{ + 0:* :: "" +} 1.0 + +INT output_precision "Number of decimal places to use in standard output for timer tree" STEERABLE=always +{ + 1:* :: "number of decimal places" +} 1 + diff --git a/Carpet/Timers/schedule.ccl b/Carpet/Timers/schedule.ccl new file mode 100644 index 000000000..a7f2cbc03 --- /dev/null +++ b/Carpet/Timers/schedule.ccl @@ -0,0 +1,11 @@ +# Schedule definitions for thorn Timers + +SCHEDULE Timer_Startup AT startup BEFORE Driver_Startup +{ + LANG: C +} "Prepare hierarchical timers" + +SCHEDULE Timer_Shutdown AT shutdown AFTER Driver_Shutdown +{ + LANG: C +} "Prepare hierarchical timers" diff --git a/Carpet/Timers/src/CactusTimer.cc b/Carpet/Timers/src/CactusTimer.cc new file mode 100644 index 000000000..51803d435 --- /dev/null +++ b/Carpet/Timers/src/CactusTimer.cc @@ -0,0 +1,254 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if HAVE_UNISTD_H +# include +# include +#endif + +#include + +#include "CactusTimer.hh" +#include "CactusTimerSet.hh" + + + +namespace Timers { + + using namespace std; + + // Create a new Cactus timer with the given name + CactusTimer::CactusTimer(string timername) + : running(false) + { + handle = CCTK_TimerCreate(timername.c_str()); + assert(handle >= 0); + + timerSet.add(this); + } + + // Destroy a timer + CactusTimer::~CactusTimer () + { + timerSet.remove (this); + check (not CCTK_TimerDestroyI (handle)); + } + + // Start the timer + void CactusTimer::start () + { + msgStart (); +// cout << "CactusTimer::start this = " << this << endl; + running = true; + CCTK_TimerStartI (handle); + } + + // Stop the timer + void CactusTimer::stop () + { + CCTK_TimerStopI (handle); + running = false; + msgStop (); + } + + // Reset the timer + void CactusTimer::reset () + { + CCTK_TimerResetI (handle); + } + + // Timer name + string CactusTimer::name () const + { + const char* const timername = CCTK_TimerName (handle); + assert (timername); + return string(timername); + } + + double CactusTimer::getTime() + { + DECLARE_CCTK_PARAMETERS; + + static cTimerData * timer = 0; + if (not timer) timer = CCTK_TimerCreateData (); + assert (timer); + CCTK_TimerI (handle, timer); + + const bool was_running = running; + if (was_running) stop(); + const cTimerVal* tv = CCTK_GetClockValue(xml_clock, timer); + if (was_running) start(); + + if (not tv) { + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING, + "Clock \"%s\" not found for timer #%d \"%s\"", + xml_clock, handle, CCTK_TimerName(handle)); + return -1.0; + } + + return CCTK_TimerClockSeconds(tv); + } + + void CactusTimer::getGlobalTime(double& avg, double& max) + { + const cGH *const cctkGH = 0; + + int ierr; + + static int op_sum = -1; + static int op_max = -1; + if (op_sum<0) op_sum = CCTK_ReductionArrayHandle("sum"); + if (op_max<0) op_max = CCTK_ReductionArrayHandle("maximum"); + + const double val = getTime(); + const CCTK_REAL val1 = val; + + CCTK_REAL sum1; + ierr = CCTK_ReduceLocScalar(cctkGH, -1, op_sum, + &val1, &sum1, CCTK_VARIABLE_REAL); + if (ierr) { + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING, + "Error in sum reduction"); + } + avg = sum1 / CCTK_nProcs(cctkGH); + + CCTK_REAL max1; + ierr = CCTK_ReduceLocScalar(cctkGH, -1, op_max, + &val1, &max1, CCTK_VARIABLE_REAL); + if (ierr) { + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING, + "Error in maximum reduction"); + } + max = max1; + } + + vector > CactusTimer::getAllTimerNames() const + { + DECLARE_CCTK_PARAMETERS; + + static cTimerData *timer = NULL; + if (not timer) timer = CCTK_TimerCreateData(); + assert(timer); + + CCTK_TimerI(handle, timer); + + vector > names(timer->n_vals); + for (int i=0; in_vals; ++i) { + names[i].first = timer->vals[i].heading; + names[i].second = timer->vals[i].units; + } + + return names; + } + + vector CactusTimer::getAllTimerValues() + { + DECLARE_CCTK_PARAMETERS; + + const bool was_running = running; + if (was_running) stop(); + + static cTimerData *timer = NULL; + if (not timer) timer = CCTK_TimerCreateData(); + assert(timer); + + CCTK_TimerI(handle, timer); + + vector vals(timer->n_vals); + for (int i=0; in_vals; ++i) { + switch (timer->vals[i].type) { + case val_int: vals[i] = timer->vals[i].val.i; break; + case val_long: vals[i] = timer->vals[i].val.l; break; + case val_double: vals[i] = timer->vals[i].val.d; break; + default: CCTK_BUILTIN_UNREACHABLE(); + } + } + + if (was_running) start(); + + return vals; + } + + // Print timer data + void CactusTimer::printData () + { + const bool was_running = running; + if (was_running) stop(); + +#if 0 + check (not CCTK_TimerPrintDataI (handle, -1)); // -1 means: all clocks +#endif + + static cTimerData * timer = 0; + if (not timer) timer = CCTK_TimerCreateData (); + assert (timer); + CCTK_TimerI (handle, timer); + + static bool firsttime = true; + if (firsttime) { + printf ("# 1: timer name"); + for (int i=0; in_vals; ++i) { + printf (" %d: %s [%s]", + i+2, timer->vals[i].heading, timer->vals[i].units); + } + printf ("\n"); + firsttime = false; + } + + printf ("%s:", name().c_str()); + for (int i=0; in_vals; ++i) { + switch (timer->vals[i].type) { + case val_int: + printf (" %d", timer->vals[i].val.i); + break; + case val_long: + printf (" %ld", timer->vals[i].val.l); + break; + case val_double: + printf (" %g", timer->vals[i].val.d); + break; + case val_none: + break; + default: + assert (0); + } + } + printf ("\n"); + + if (was_running) start(); + } + + // Output (debug) messages that a timer is starting or stopping + void CactusTimer::msgStart () const + { + DECLARE_CCTK_PARAMETERS; + if (verbose) { + CCTK_VInfo (CCTK_THORNSTRING, "Timer \"%s\" starting", name().c_str()); + } + } + + void CactusTimer::msgStop () const + { + DECLARE_CCTK_PARAMETERS; + if (verbose) { + CCTK_VInfo (CCTK_THORNSTRING, "Timer \"%s\" stopping", name().c_str()); + } + } + + ostream& CactusTimer::serialise(ostream &os) + { + os << scientific << setprecision(19) << getTime() << " " << name(); + return os; + } + +} // namespace Carpet diff --git a/Carpet/Timers/src/CactusTimer.hh b/Carpet/Timers/src/CactusTimer.hh new file mode 100644 index 000000000..c198d9014 --- /dev/null +++ b/Carpet/Timers/src/CactusTimer.hh @@ -0,0 +1,69 @@ +#ifndef CACTUSTIMER_HH +#define CACTUSTIMER_HH + +#include + +#include +#include +#include +#include +#include + + + +namespace Timers { + + /** The CactusTimer class wraps the Cactus timer mechanism. All + times are returned as doubles for now. */ + + class CactusTimer { + int handle; + bool running; + + public: + + /// Create a new Cactus timer with the given name + CactusTimer(std::string timername); + + /// Destruct the timer + ~CactusTimer(); + + /// Start the timer + void start(); + + /// Stop the timer + void stop(); + + /// Reset the timer + void reset(); + + /// Timer name + std::string name() const; + + /// Return the current time of the timer in seconds as a double + double getTime(); + + /// Return the average and maximum current time over all MPI processes + void getGlobalTime(double& avg, double& max); + + /// Return all clock names and their units + std::vector > getAllTimerNames() const; + + /// Return all clock values of the timer as double + std::vector getAllTimerValues(); + + /// Print timer data + void printData (); + + std::ostream& serialise(std::ostream &os); + + private: + + // Output (debug) messages that a timer is starting or stopping + void msgStart() const; + void msgStop() const; + }; + +} // namespace Timers + +#endif // CACTUSTIMER_HH diff --git a/Carpet/Timers/src/CactusTimerSet.cc b/Carpet/Timers/src/CactusTimerSet.cc new file mode 100644 index 000000000..54eed2f70 --- /dev/null +++ b/Carpet/Timers/src/CactusTimerSet.cc @@ -0,0 +1,179 @@ +#include +#include +#include +#include + +#include +#include +#include + +#if HAVE_UNISTD_H +# include +# include +#endif + +#include + +#include +#include +#include +#include + + + +namespace Timers { + + using namespace std; + + // A global timer set + CactusTimerSet timerSet; + + // Add a timer + void CactusTimerSet::add(CactusTimer* const timer) + { + timers.insert(timer); + } + + // Remove a timer + void CactusTimerSet::remove(CactusTimer* const timer) + { + timers.erase(timer); + } + + // Print all timer names + void CactusTimerSet::printNames() const + { + printf("Timer names:\n"); + int n = 0; + for (timers_t::const_iterator + itimer = timers.begin(); itimer != timers.end(); ++itimer) + { + printf(" [%4d] %s\n", n, (*itimer)->name().c_str()); + ++n; + } + } + + // Print all timer data + void CactusTimerSet::printData() + { + for (timers_t::const_iterator + itimer = timers.begin(); itimer != timers.end(); ++itimer) + { + (*itimer)->printData(); + } + printf("\n"); + } + + // Print all timer data + void CactusTimerSet::writeData(const cGH* const cctkGH, + const char* const filename) + { + const int oldfd = redirect(cctkGH, filename); +#if 0 + printf("********************************************************************************\n"); +#endif + printf("# Carpet timing information at iteration %d time %g:\n", + cctkGH->cctk_iteration, double(cctkGH->cctk_time)); + timerSet.printData(); + unredirect(oldfd); + } + + // If filename is not empty, then redirect stdout to a file + int CactusTimerSet::redirect(const cGH* const cctkGH, + const char* const filename) + { + DECLARE_CCTK_PARAMETERS; + + if (CCTK_EQUALS (filename, "")) { + return -1; + } + +#ifndef HAVE_UNISTD_H + CCTK_WARN(CCTK_WARN_ALERT, + "Cannot redirect timer output to a file; the operating system does not support this"); + return -1; +#else + + const int myproc = CCTK_MyProc(cctkGH); + char fullname[10000]; + Util_snprintf(fullname, sizeof fullname, + "%s/%s.%04d.txt", out_dir, filename, myproc); + + int flags = O_WRONLY | O_CREAT | O_APPEND; // append + static bool first_time = true; + if (first_time) { + first_time = false; + if (IO_TruncateOutputFiles(cctkGH)) { + flags = O_WRONLY | O_CREAT | O_TRUNC; // truncate + } + } + + // Temporarily redirect stdout + fflush(stdout); + const int oldfd = dup(1); // fd 1 is stdout + const int mode = 0644; // rw-r--r--, or a+r u+w + const int fdfile = open(fullname, flags, mode); + if (fdfile < 0) { + CCTK_VWarn(CCTK_WARN_ABORT, __LINE__, __FILE__, CCTK_THORNSTRING, + "Could not open timer output file \"%s\"", fullname); + close(oldfd); + return -1; + } + // close(1); + // const int fd = dup(fdfile); // dup to 1, i.e., stdout again + const int fd = dup2(fdfile, 1); // dup to 1, i.e., stdout again + assert(fd == 1); + close(fdfile); + return oldfd; +#endif + } + + // Redirect stdout back + void CactusTimerSet::unredirect(const int oldfd) + { + if (oldfd < 0) return; + +#ifdef HAVE_UNISTD_H + fflush (stdout); + // close(1); + // const int fd = dup(oldfd); + const int fd = dup2(oldfd, 1); + if (not (fd == 1)) { + fprintf(stderr, "oldfd=%d fd=%d\n", oldfd, fd); + } + assert(fd == 1); + close(oldfd); +#endif + } + + +#if 0 + /// Reduce each timer in the set across all processes and update + /// each timer with the reduction information. + void CactusTimerSet::reduce() + { + // Collect timer names that each process has + + // Construct union of all timer names, sort canonically and assign + // integer identifiers + + // For each timer, identify which processes have that timer + + // Reduce the timer across all those processes (return to root proc only) + + serialise(cout); + } + + ostream& CactusTimerSet::serialise(ostream &os) + { + for (timers_t::const_iterator + itimer = timers.begin(); itimer != timers.end(); ++itimer) + { + (*itimer)->serialise(os); + os << endl; + } + return os; + } +#endif + +} // namespace Carpet diff --git a/Carpet/Timers/src/CactusTimerSet.hh b/Carpet/Timers/src/CactusTimerSet.hh new file mode 100644 index 000000000..c53fa5bc3 --- /dev/null +++ b/Carpet/Timers/src/CactusTimerSet.hh @@ -0,0 +1,62 @@ +#ifndef CACTUSTIMERSET_HH +#define CACTUSTIMERSET_HH + +#include +#include + +#include +#include "CactusTimer.hh" + + + +namespace Timers { + + class CactusTimerSet; + extern CactusTimerSet timerSet; + + using namespace std; + + // A set of timers + class CactusTimerSet { + + typedef set timers_t; + timers_t timers; + + public: + + // Add a timer + void add(CactusTimer* timer); + + // Remove a timer + void remove(CactusTimer* timer); + + // Print all timer names + void printNames() const; + + // Print all timer data + void printData(); + + // Write all timer data of the global timer set to a file + static void writeData(cGH const* cctkGH, char const* filename); + +#if 0 + // Reduce each timer in the set across all processes and update + // each timer with the reduction information. + void reduce(); + + ostream& serialise(ostream &os); +#endif + + private: + + // If filename is not empty, then redirect stdout to a file, + // returning the old stdout file descriptor + static int redirect(cGH const* cctkGH, char const* filename); + + // Redirect stdout back + static void unredirect(int oldfd); + }; // class CactusTimerSet + +} // namespace Timers + +#endif // CACTUSTIMERSET_HH diff --git a/Carpet/Timers/src/Timer.cc b/Carpet/Timers/src/Timer.cc new file mode 100644 index 000000000..50631c374 --- /dev/null +++ b/Carpet/Timers/src/Timer.cc @@ -0,0 +1,135 @@ +#include + +#include +#include + +#include +#include + + + +namespace Timers { + + using namespace std; + + /********************************************************************* + Timer + *********************************************************************/ + + + + TimerTree main_timer_tree; + TimerTree mode_timer_tree; + + + + /// 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(string name_p, int tree): + d_name(name_p), d_tree(tree==0 ? &main_timer_tree : &mode_timer_tree) + { + } + + /// Destroy the timer + Timer::~Timer() + { + } + + /// Insert the timer into the tree of timers as a child of the most + /// recently started timer that has not been stopped. Don't start + /// the timer. This routine ensures a timer is created even if it is + /// never started. + void Timer::instantiate() + { + TimerNode *current_timer = d_tree->current; + if (not d_tree->root) return; // do nothing if there is no root + assert(current_timer); + current_timer->getChildTimer(name())->instantiate(); + } + + /// Start the timer and insert it into the tree of timers as a child + /// of the most recently started timer that has not been stopped. + void Timer::start() + { + TimerNode *current_timer = d_tree->current; + if (not d_tree->root) return; // do nothing if there is no root + assert(current_timer); + current_timer->getChildTimer(name())->start(); + } + + /// Stop the timer - it must be the most recently started timer + void Timer::stop() + { + TimerNode *current = d_tree->current; + if (not d_tree->root) return; // do nothing if there is no root + if (current->getName() != name()) + CCTK_VError(__LINE__, __FILE__, CCTK_THORNSTRING, + "Trying to stop enclosing timer '%s' before enclosed time '%s'", + name().c_str(), current->getName().c_str()); + current->stop(); + } + + /// Return the name of the timer + string Timer::name() const + { + return d_name; + } + + /// Return the current time of the timer as a double + double Timer::getTime() + { + return d_tree->current->getTime(); + } + + void Timer::outputTree(string name) + { + DECLARE_CCTK_PARAMETERS; + + TimerNode *tt = main_timer_tree.root->getChildTimer(name.c_str()); + double total_avg, total_max; + tt->getGlobalTime(total_avg, total_max); + tt->print + (cout, total_max, 0, threshold_percentage, output_precision); + mode_timer_tree.root->getGlobalTime(total_avg, total_max); + mode_timer_tree.root->print + (cout, total_max, 0, threshold_percentage, output_precision); + } + + void Timer::outputTreeXML() + { + DECLARE_CCTK_PARAMETERS; + + main_timer_tree.root->outputXML(out_dir, CCTK_MyProc(0)); + } + + + + extern "C" + int Timer_Startup() + { + // This must happen before any Timer objects are created + 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(); + + mode_timer_tree.root = new TimerNode(&mode_timer_tree, "meta mode"); + mode_timer_tree.current = 0; // No timer has been started yet + mode_timer_tree.root->start(); + + return 0; + } + + extern "C" + int Timer_Shutdown() + { + // main_timer_tree.root->stop(); + // mode_timer_tree.root->stop(); + + // Delete timer tree + delete main_timer_tree.root; main_timer_tree.root = 0; + delete mode_timer_tree.root; mode_timer_tree.root = 0; + + return 0; + } + +} // namespace Timers diff --git a/Carpet/Timers/src/Timer.hh b/Carpet/Timers/src/Timer.hh new file mode 100644 index 000000000..651659fec --- /dev/null +++ b/Carpet/Timers/src/Timer.hh @@ -0,0 +1,89 @@ +#ifndef TIMER_HH +#define TIMER_HH + +#include +#include + +#include + +#include + + + +namespace Timers { + + /** + This class allows the user to instrument their code with named + timers which can then be later queried to determine the amount of + time spent in the code between "start" and "end" calls. The + sequence of start and end calls of different timers determines a + dynamical hierarchical tree structure implemented by the + TimerNode class. + + To use this class, create a timer object with a particular name: + + Timer timer("MyTimer") + + Now wrap the code to be timed with start() and stop() calls: + + timer.start() + + some code + + timer.stop() + + You can start and stop a timer multiple times. The timer will be + created as a child of whatever timer is current (i.e. has been + started and not stopped) at the time of the first start() call. + Any timers which are started between the start() and stop(), + whether or not they are in the same file, will be stored as + children of this timer. + + Timer objects must be started and stopped in a non-overlapping + manner. Specifically, a timer cannot be stopped if it is not the + most recently started timer. Doing so will generate an error. + + Timer objects can be allocated as "static" or not - it does not + matter. + */ + + class Timer { + + public: + + Timer(std::string name, int tree=0); + ~Timer(); + + void instantiate(); + void start(); + void stop(); + std::string name() const; + double getTime(); + + static void outputTree(std::string name); + static void outputTreeXML(); + + private: + + std::string d_name; + TimerTree *d_tree; + }; + +} // namespace Timers + + + +// Macros for using timers in a convenient manner + +#define TIMING_BEGIN(name) \ + do { \ + static Timers::timer(name); \ + timer.start(); \ + { + +#define TIMING_END \ + } \ + timer.stop(); \ + } while (0) + +#endif // TIMER_HH diff --git a/Carpet/Timers/src/TimerTree.cc b/Carpet/Timers/src/TimerTree.cc new file mode 100644 index 000000000..e75281bf7 --- /dev/null +++ b/Carpet/Timers/src/TimerTree.cc @@ -0,0 +1,378 @@ +/* + * + * The MIT License + * + * Copyright (c) 1997-2010 Center for the Simulation of Accidental Fires and + * Explosions (CSAFE), and Scientific Computing and Imaging Institute (SCI), + * University of Utah. + * + * License for the specific language governing rights and limitations under + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "TimerTree.hh" + + + +namespace Timers { + + using namespace std; + + TimerNode::TimerNode(TimerTree *tree, const string& name): + d_name(name), d_parent(0), d_tree(tree), d_running(0), d_timer(0) + { + } + + TimerNode::~TimerNode() + { + for (map::iterator + iter=d_children.begin(); iter!=d_children.end(); ++iter) + { + delete iter->second; + } + d_children.clear(); + delete d_timer; + } + + string TimerNode::pathName() const + { + assert(d_parent != this); + if (d_parent) + return d_parent->pathName() + string("/") + getName(); + else + return getName(); + } + + void TimerNode::instantiate() + { + assert(!d_running); + d_parent = d_tree->current; + d_tree->current = this; + if (!d_timer) + d_timer = new CactusTimer(pathName()); + d_tree->current = d_parent; + } + + void TimerNode::start() + { + assert(!d_running); + + d_running = true; + d_parent = d_tree->current; + d_tree->current = this; + if (!d_timer) + d_timer = new CactusTimer(pathName()); + assert(d_timer); + d_timer->start(); + } + + void TimerNode::stop() + { + assert(d_running); + + // A timer can only be stopped if it is the current timer + if (this != d_tree->current) + CCTK_VError(__LINE__, __FILE__, CCTK_THORNSTRING, + "Tried to stop non-current timer '%s'", getName().c_str()); + + d_timer->stop(); + + d_running = false; + d_tree->current = d_parent; + } + + /// Get the name of the timer + string TimerNode::getName() const + { + assert(not d_name.empty()); + return d_name; + } + + /// Determine if the timer is running + bool TimerNode::isRunning() const + { + return d_running; + } + + /// Find the child timer that matches the name provided. If it is + /// not found then a new timer with that name is allocated. + TimerNode* TimerNode::getChildTimer(const string& name) + { + // Find child + TimerNode *child = d_children[name]; + + // If the pointer is null then allocate it + if (not child) + d_children[name] = child = new TimerNode(d_tree, name); + + return child; + } + + /// Get the time measured by this timer + double TimerNode::getTime() + { + return d_timer->getTime(); + } + + /// Get the global time measured by this timer + void TimerNode::getGlobalTime(double& avg, double& max) + { + return d_timer->getGlobalTime(avg, max); + } + + /// Get the names of all clocks of this timer + vector > TimerNode::getAllTimerNames() const + { + return d_timer->getAllTimerNames(); + } + + /// Get the values of all clocks of this timer + vector TimerNode::getAllTimerValues() + { + return d_timer->getAllTimerValues(); + } + + /// Print this node and its children as an ASCII tree + void TimerNode::print(ostream& out, + double total, int level, double threshold, + int precision) + { + string space; + + // Compute the level of indentation for this depth + for (int i=0;i values = getAllTimerValues(); + const string hyphens = string(precision-1, '-'); + const string spaces = string(precision-1, ' '); + + if (level == 0) { + const vector > names = getAllTimerNames(); + + out << "--------" << hyphens + << "--------" << hyphens + << "--------" << hyphens + << "--" << string(tnw, '-'); + for (size_t i=0; i::iterator iter = d_children.begin(); + iter != d_children.end(); iter++) + { + const string timername = iter->first; + const string root_timername = + CarpetLib::broadcast_string(dist::comm(), 0, timername); + if (timername != root_timername) { + CCTK_VError(__LINE__, __FILE__, CCTK_THORNSTRING, + "Timers are inconsistent across processes: root process expects timer %s, this process has timer %s instead", + root_timername.c_str(), timername.c_str()); + } + double child_avg, child_max; + iter->second->getGlobalTime(child_avg, child_max); + if (child_max * 100.0 / total > threshold) { + iter->second->print(out,total,level+1,threshold,precision); + printed_children = true; + } + //children_time += iter->second->getTime(); + children_tavg += child_avg; + } + { + const string timername = "[done]"; + const string root_timername = + CarpetLib::broadcast_string(dist::comm(), 0, timername); + if (timername != root_timername) { + CCTK_VError(__LINE__, __FILE__, CCTK_THORNSTRING, + "Timers are inconsistent across processes: root process expects timer %s, this process has timer %s instead", + root_timername.c_str(), timername.c_str()); + } + } + + if (d_children.size() > 0 && printed_children) { + //const double untimed = t - children_time; + const double untimed = tavg - children_tavg; + + if (100.0 * untimed / total > threshold) { + // Print the untimed portion + out << fixed << setw(pcw) << setprecision(1) + << 100.0 * untimed / total << "%" + << " " << fixed << setw(tw) << setprecision(1) << untimed + << " " + << " | " << space << "untimed" << "\n"; + } + } + out.precision (oldprecision); + out.setf (oldflags); + + if (level == 0) { + out << "--------" << hyphens + << "--------" << hyphens + << "--------" << hyphens + << "--" << string(tnw, '-'); + for (size_t i=0; i "; + out << getTime() << " "; + + // For compactness, only use multiple lines if there are children + if (d_children.size() != 0) + { + out << "\n"; + + // Recursively print the children + for (map::iterator + iter=d_children.begin(); iter!=d_children.end(); ++iter) + iter->second->printXML(out,level+1); + out << space; + } + + out << "" << "\n"; + } + + /// Make a string suitable for inclusion in an XML file + string TimerNode::escapeForXML(const string& s) const + { + ostringstream res; + for (string::const_iterator si=s.begin(); si!=s.end(); ++si) { + switch (*si) { + case '\'': res << "'"; break; + case '"': res << """; break; + case '&': res << "&"; break; + case '<': res << "<"; break; + case '>': res << ">"; break; + default: res << *si; break; + } + } + + return res.str(); + } + +} // namespace Timers diff --git a/Carpet/Timers/src/TimerTree.hh b/Carpet/Timers/src/TimerTree.hh new file mode 100644 index 000000000..55d61a0f8 --- /dev/null +++ b/Carpet/Timers/src/TimerTree.hh @@ -0,0 +1,121 @@ +/* + * + * The MIT License + * + * Copyright (c) 1997-2010 Center for the Simulation of Accidental Fires and + * Explosions (CSAFE), and Scientific Computing and Imaging Institute (SCI), + * University of Utah. + * + * License for the specific language governing rights and limitations under + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * */ + +/* This class was originally written by Justin Luitjens and + subsequently integrated with Cactus/Carpet by Ian Hinder and + heavily modified. */ + + + +#ifndef TIMERTREE_HH +#define TIMERTREE_HH + +#include +#include +#include +#include +#include +#include + +#include "CactusTimer.hh" + + + +namespace Timers { + + class TimerNode; + + class TimerTree { + public: + TimerTree(): root(0), current(0) + { + } + TimerNode *root; + TimerNode *current; + }; + + + + /** + The TimerNode class implements a tree structure where each node + represents a timer, implemented as a CactusTimer. Each node of + the tree can have zero of more children, where the names of the + child nodes are unique within a single parent, but not + necessarily unique within the entire tree. A tree formed of + TimerNode objects represents the execution profile of the + program, inasmuch as it is instrumented by timers. + + Child nodes of a given name are accessed using the getChildTimer + method, where a node is created with the given name if none + exists already. This ensures that the names of the child timers + are unique. + */ + + class TimerNode { + public: + TimerNode(TimerTree *root, const std::string& name); + ~TimerNode(); + + void instantiate(); + void start(); + void stop(); + + std::string getName() const; + std::string pathName() const; + + // Find the child timer that matches the name provided. If it is + // not found then that timer is allocated. + TimerNode* getChildTimer(const std::string& name); + + double getTime(); + void getGlobalTime(double& avg, double &max); + std::vector > getAllTimerNames() const; + std::vector getAllTimerValues(); + bool isRunning() const; + + void print(std::ostream& out, + double total, int level=0, double threshold=0.0, + int precision=1); + void printXML(std::ostream& out, int level=0); + void outputXML(const std::string& out_dir, int proc); + + private: + std::string escapeForXML(const std::string& s) const; + + std::string d_name; + std::map d_children; + TimerNode *d_parent; + TimerTree *d_tree; + bool d_running; + CactusTimer *d_timer; + }; + +} // namespace Timers + +#endif // TIMERTREE_HH diff --git a/Carpet/Timers/src/make.code.defn b/Carpet/Timers/src/make.code.defn new file mode 100644 index 000000000..4779d34ae --- /dev/null +++ b/Carpet/Timers/src/make.code.defn @@ -0,0 +1,7 @@ +# Main make.code.defn file for thorn Timers + +# Source files in this directory +SRCS = CactusTimer.cc CactusTimerSet.cc Timer.cc TimerTree.cc + +# Subdirectories containing source files +SUBDIRS = -- cgit v1.2.3