10#ifndef TEUCHOS_STACKED_TIMER_HPP 
   11#define TEUCHOS_STACKED_TIMER_HPP 
   14#include "Teuchos_Comm.hpp" 
   15#include "Teuchos_DefaultComm.hpp" 
   16#include "Teuchos_CommHelpers.hpp" 
   20#include "Teuchos_Behavior.hpp" 
   21#ifdef HAVE_TEUCHOSCORE_KOKKOS 
   22#include "Kokkos_Core.hpp" 
   33#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS) 
   36extern void pushRegion (
const std::string&);
 
   37extern void popRegion ();
 
   46TEUCHOSCOMM_LIB_DLL_EXPORT 
void error_out(
const std::string& msg, 
const bool fail_all = 
false);
 
   61  using Clock = std::chrono::high_resolution_clock;
 
   63  BaseTimer() : accumulation_(0.0), accumulationSquared_(0.0), count_started_(0), count_updates_(0), running_(
false) {}
 
   68      error_out(
"Base_Timer:start Failed timer already running");
 
   69    start_time_ = Clock::now();
 
 
   78      error_out(
"Base_Timer:stop Failed timer not running");
 
   79    auto elapsed = std::chrono::duration_cast<std::chrono::duration<double>>(Clock::now() - start_time_).count();
 
 
   86  unsigned long long incrementUpdates(
unsigned long long count=1) {count_updates_ += count; 
return count_updates_;}
 
  double accumulatedTimePerUpdate()
 const {
  106    if (count_updates_ > 0) {
 
  107      return accumulation_/count_updates_;
 
  122    if (count_started_> 0) {
 
  123      return accumulation_/count_started_;
 
 
  137    if (count_started_ > 0) {
 
  139      return sqrt(std::max<double>(accumulationSquared_ / count_started_ - 
mean*
mean, 0.0));
 
 
  152    return accumulation_ - 
from.accumulation_;
 
 
  158       error_out(
"BaseTimer, cannot reset a running timer");
 
  160    count_started_ = count_updates_ = 0;
 
 
  167  unsigned long numCalls()
 const { 
return count_started_; }
 
  170  unsigned long long numUpdates()
 const { 
return count_updates_; }
 
  181    TimeInfo():time(0.0), stdDev(0.0), count(0), updates(0), running(
false){}
 
  182    TimeInfo(BaseTimer* t): time(t->accumulation_), stdDev(t->
timePerCallStdDev()), count(t->count_started_), updates(t->count_updates_), running(t->running()) {}
 
  186    unsigned long long updates;
 
  191  double accumulation_;       
 
  192  double accumulationSquared_;  
 
  193  unsigned long count_started_; 
 
  194  unsigned long long count_updates_; 
 
  195  Clock::time_point start_time_;
 
  198  friend struct TimeInfo;
 
 
  238    std::vector<LevelTimer> sub_timers_;
 
  251        const char* name = 
"RootTimer",
 
 
  268      for (
unsigned i=0;
i<sub_timers_.size();++
i)
 
  269        sub_timers_[
i].parent_ = 
this;
 
 
  278      for (
unsigned i=0;
i<sub_timers_.size();
i++ )
 
  280          sub_timers_[
i].BaseTimer::start();
 
  281          return &sub_timers_[
i];
 
  284      return &sub_timers_[sub_timers_.size()-1];
 
 
  296        error_out(
"Stopping timer "+name+
" But top level running timer is "+name_);
 
 
  308      if ((parent_ != 
nullptr))
 
 
  317    std::string get_name()
 const {
 
  329      for (
unsigned i=0;
i<sub_timers_.size(); ++
i)
 
  330        count += sub_timers_[
i].countTimers();
 
 
  336      for (
unsigned i=0;
i<sub_timers_.size(); ++
i)
 
  337        sub_timers_[
i].addTimerNames(
names, 
pos);
 
  348        return BaseTimer::accumulatedTime();
 
  360      for (
unsigned j=0;
j<sub_timers_.size();++
j)
 
 
  397         return BaseTimer::accumulatedTimePerUpdate();
 
  402       for (
unsigned j=0;
j<sub_timers_.size();
j++)
 
  404           return sub_timers_[
j].accumulatedTimePerUpdate(
second_name);
 
 
  416         return BaseTimer::accumulatedTimePerTimerCall();
 
  421       for (
unsigned j=0;
j<sub_timers_.size();
j++)
 
  423           return sub_timers_[
j].accumulatedTimePerTimerCall(
second_name);
 
 
  443     void report(std::ostream &os);
 
  450    const BaseTimer* findBaseTimer(
const std::string &name) 
const;
 
  458    BaseTimer::TimeInfo findTimer(
const std::string &name,
bool& 
found);
 
 
  471      global_mpi_aggregation_called_(
false),
 
  472      enable_verbose_(
false),
 
  473      verbose_timestamp_levels_(0), 
 
  479      this->startBaseTimer();
 
  481    auto check_verbose = std::getenv(
"TEUCHOS_ENABLE_VERBOSE_TIMERS");
 
  483      enable_verbose_ = 
true;
 
  485    auto check_timestamp = std::getenv(
"TEUCHOS_ENABLE_VERBOSE_TIMESTAMP_LEVELS");
 
 
  492    return timer_.get_full_name();
 
  499    timer_.BaseTimer::start();
 
  500#ifdef HAVE_TEUCHOSCORE_KOKKOS 
  501    if (Behavior::fenceTimers()) {
 
  502      Kokkos::fence(
"timer_fence_begin_"+timer_.get_name());
 
  505#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS) 
  507      ::Kokkos::Tools::pushRegion(timer_.get_name());
 
 
  516    timer_.BaseTimer::stop();
 
  517#ifdef HAVE_TEUCHOSCORE_KOKKOS 
  518    if (Behavior::fenceTimers()) {
 
  519      Kokkos::fence(
"timer_fence_end_"+timer_.get_name());
 
  522#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS) 
  524      ::Kokkos::Tools::popRegion();
 
 
  536    if (enable_timers_) {
 
  537      if (top_ == 
nullptr) {
 
  538        top_ = timer_.start(name.c_str());
 
  540        top_ = top_->start(name.c_str());
 
  541#ifdef HAVE_TEUCHOSCORE_KOKKOS 
  542        if (Behavior::fenceTimers()) {
 
  543          Kokkos::fence(
"timer_fence_begin_"+name);
 
  546#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS) 
  548          ::Kokkos::Tools::pushRegion(name);
 
  553    if (enable_verbose_) {
 
  554      if (!verbose_timestamp_levels_) {
 
  555        *verbose_ostream_ << 
"STARTING: " << name << std::endl;
 
  559#if !defined(__GNUC__) || ( defined(__GNUC__) && (__GNUC__ > 4) ) 
  560      else if (top_ != 
nullptr) {
 
  561        if ( top_->level() <= verbose_timestamp_levels_) {
 
  562          auto now = std::chrono::system_clock::now();
 
  563          auto now_time = std::chrono::system_clock::to_time_t(
now);
 
  565          auto timestamp = std::put_time(
gmt, 
"%Y-%m-%d %H:%M:%S");
 
  566          auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) % 1000;
 
  567          *verbose_ostream_ << 
"STARTING: " << name << 
" LEVEL: " << top_->level() << 
" COUNT: " << timer_.numCalls() << 
" TIMESTAMP: " << 
timestamp << 
"." << 
ms.count() << std::endl;
 
 
  579  void stop(
const std::string &name,
 
  581    if (enable_timers_) {
 
  583        top_ = top_->stop(name);
 
  584#ifdef HAVE_TEUCHOSCORE_KOKKOS 
  585        if (Behavior::fenceTimers()) {
 
  586          Kokkos::fence(
"timer_fence_end_"+name);
 
  589#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS) 
  591          ::Kokkos::Tools::popRegion();
 
  595        timer_.BaseTimer::stop();
 
  598    if (enable_verbose_) {
 
  599      if (!verbose_timestamp_levels_) {
 
  600        *verbose_ostream_ << 
"STOPPING: " << name << std::endl;
 
  604#if !defined(__GNUC__) || ( defined(__GNUC__) && (__GNUC__ > 4) ) 
  606      else if (top_ != 
nullptr) {
 
  607        if ( (top_->level()+1) <= verbose_timestamp_levels_) {
 
  608          auto now = std::chrono::system_clock::now();
 
  609          auto now_time = std::chrono::system_clock::to_time_t(
now);
 
  611          auto timestamp = std::put_time(
gmt, 
"%Y-%m-%d %H:%M:%S");
 
  612          auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) % 1000;
 
  613          *verbose_ostream_ << 
"STOPPING: " << name << 
" LEVEL: " << top_->level()+1 << 
" COUNT: " << timer_.numCalls() << 
" TIMESTAMP: " << 
timestamp << 
"." << 
ms.count() << std::endl;
 
 
  625    top_->incrementUpdates(
i);
 
 
  635      return top_->accumulatedTime(name);
 
  637      return timer_.accumulatedTime(name);
 
 
  647       return top_->accumulatedTimePerUpdate(name);
 
  649       return timer_.accumulatedTimePerUpdate(name);
 
 
  658       return top_->accumulatedTimePerTimerCall(name);
 
  660       return timer_.accumulatedTimePerTimerCall(name);
 
 
  671                               "StackedTimer::findBaseTimer() failed to find a timer named \"" << name << 
"\"!\n");
 
 
  680  BaseTimer::TimeInfo 
findTimer(
const std::string &name) {
 
  684      "StackedTimer::findTimer() failed to find a timer named \"" << name << 
"\"!\n");
 
 
  688  void report(std::ostream &os) {
 
  707    OutputOptions() : output_fraction(
false), output_total_updates(
false), output_histogram(
false),
 
  708                      output_minmax(
false), output_proc_minmax(
false), num_histogram(10), max_levels(
INT_MAX),
 
  709                      print_warnings(
true), align_columns(
false), print_names_before_values(
true),
 
  710                      drop_time(-1.0), output_per_proc_stddev(
false) {}
 
  711    bool output_fraction;
 
  712    bool output_total_updates;
 
  713    bool output_histogram;
 
  715    bool output_proc_minmax;
 
  720    bool print_names_before_values;
 
  722    bool output_per_proc_stddev;
 
 
  781  void enableVerboseTimestamps(
const unsigned levels);
 
  788  void disableTimers();
 
  851  bool global_mpi_aggregation_called_;
 
  855    std::string::size_type timer_names_;
 
  856    std::string::size_type average_time_;
 
  857    std::string::size_type fraction_;
 
  858    std::string::size_type count_;
 
  859    std::string::size_type total_updates_;
 
  860    std::string::size_type min_;
 
  861    std::string::size_type max_;
 
  862    std::string::size_type procmin_;
 
  863    std::string::size_type procmax_;
 
  864    std::string::size_type stddev_;
 
  865    std::string::size_type histogram_;
 
 
  925  double printLevel(std::string 
prefix, 
int level, std::ostream &os, std::vector<bool> &
printed,
 
 
Templated array class derived from the STL std::vector.
 
Teuchos header file which uses auto-configuration information to include necessary C++ headers.
 
Reference-counted pointer class and non-member templated function implementations.
 
The basic timer used internally, uses std::chrono::high_resolution_clock.
 
void setAccumulatedTime(double accum=0)
Setter for accumulated time.
 
double difference(const BaseTimer &from) const
Return the difference between two timers in seconds,.
 
void reset()
Reset all the timer stats, throws if it is already running.
 
void start()
Start a currently stopped timer.
 
double accumulatedTimePerTimerCall() const
return the average time per timer start/stop
 
double accumulatedTimePerUpdate() const
return the average time per item updated
 
void stop()
Stop a current running timer and accumulate time difference.
 
void overrideNumUpdatesForUnitTesting(const unsigned long long num_updates)
Sets the number of counts for this timer. This is only used for unit testing.
 
double accumulatedTime() const
Get the total accumulated time since last reset or construction when the timer is running.
 
double timePerCallStdDev() const
return the std dev in time per timer start/stop
 
void overrideNumCallsForUnitTesting(const unsigned long num_calls)
Sets the number of calls to start() for this timer. This is only used for unit testing.
 
unsigned long long numUpdates() const
Returns the number of updates added to this timer.
 
void setAccumulatedTimeSquared(double accumSq=0)
Setter for squared accumulated time.
 
unsigned long numCalls() const
Returns the number of calls to start().
 
unsigned long long incrementUpdates(unsigned long long count=1)
Increment the total number of items updated between a start stop.
 
bool running() const
Returns true if the timer is currently accumulating time.
 
Smart reference counting pointer class for automatic garbage collection.
 
Timer info at a given level and all the children.
 
double accumulatedTime(const std::string &locate_name="")
 
LevelTimer * start(const char *sub_name)
 
void splitString(const std::string &locate_name, std::string &first_name, std::string &second_name)
split a string into two parts split by a '@' if no '@' first gets the full string
 
double accumulatedTimePerTimerCall(const std::string &locate_name="")
 
LevelTimer(const LevelTimer &src)
Copy constructor.
 
LevelTimer * stop(const std::string &name="RootTimer")
 
unsigned level() const
Returns the level of the timer in the stack.
 
double accumulatedTimePerUpdate(const std::string &locate_name="")
 
std::string get_full_name() const
 
LevelTimer * unpack(unsigned from)
 
LevelTimer(int level, const char *name="RootTimer", LevelTimer *parent=nullptr, bool start_timer=true)
 
This class allows one to push and pop timers on and off a stack.
 
LevelTimer * top_
Current level running.
 
void start(const std::string name, const bool push_kokkos_profiling_region=true)
 
BaseTimer::TimeInfo findTimer(const std::string &name)
 
void stop(const std::string &name, const bool pop_kokkos_profiling_region=true)
 
void startBaseTimer(const bool push_kokkos_profiling_region=true)
 
void stopBaseTimer(const bool pop_kokkos_profiling_region=true)
 
const BaseTimer * findBaseTimer(const std::string &name) const
 
Teuchos::RCP< std::ostream > verbose_ostream_
For debugging, this is the ostream used for printing.
 
double accumulatedTimePerUpdate(const std::string &name="")
 
void incrementUpdates(const long long i=1)
 
bool enable_timers_
Used to disable timers for asynchronous work.
 
unsigned verbose_timestamp_levels_
If set to a value greater than 0, verbose mode will print that many levels of timers with timestamps....
 
double accumulatedTime(const std::string &name="")
 
LevelTimer timer_
Base timer.
 
bool enable_verbose_
If set to true, prints to the debug ostream. At construction, default value is set from environment v...
 
double accumulatedTimePerTimerCall(const std::string &name="")
 
StackedTimer(const char *name, const bool start_base_timer=true)
 
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
 
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...
 
void error_out(const std::string &msg, const bool)
Error reporting function for stacked timer.
 
Stores the column widths for output alignment.