diff options
Diffstat (limited to 'Carpet/Timers/src/CactusTimer.cc')
-rw-r--r-- | Carpet/Timers/src/CactusTimer.cc | 254 |
1 files changed, 254 insertions, 0 deletions
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 <cassert> +#include <cstdio> +#include <cstring> +#include <iomanip> +#include <list> +#include <string> +#include <utility> +#include <vector> + +#include <cctk.h> +#include <cctk_Parameters.h> +#include <util_String.h> + +#if HAVE_UNISTD_H +# include <fcntl.h> +# include <unistd.h> +#endif + +#include <defs.hh> + +#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<pair<string,string> > CactusTimer::getAllTimerNames() const + { + DECLARE_CCTK_PARAMETERS; + + static cTimerData *timer = NULL; + if (not timer) timer = CCTK_TimerCreateData(); + assert(timer); + + CCTK_TimerI(handle, timer); + + vector<pair<string,string> > names(timer->n_vals); + for (int i=0; i<timer->n_vals; ++i) { + names[i].first = timer->vals[i].heading; + names[i].second = timer->vals[i].units; + } + + return names; + } + + vector<double> 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<double> vals(timer->n_vals); + for (int i=0; i<timer->n_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; i<timer->n_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; i<timer->n_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 |