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#ifdef HAVE_TEUCHOSCORE_KOKKOS
501 if (Behavior::fenceTimers()) {
502 Kokkos::fence(
"timer_fence_begin_"+timer_.get_name());
505 timer_.BaseTimer::start();
506#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
508 ::Kokkos::Tools::pushRegion(timer_.get_name());
517#ifdef HAVE_TEUCHOSCORE_KOKKOS
519 if (Behavior::fenceTimers()) {
520 Kokkos::fence(
"timer_fence_end_"+timer_.get_name());
523#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
525 ::Kokkos::Tools::popRegion();
528 timer_.BaseTimer::stop();
538 if (enable_timers_) {
539 if (top_ ==
nullptr) {
540 top_ = timer_.start(name.c_str());
542#ifdef HAVE_TEUCHOSCORE_KOKKOS
544 if (Behavior::fenceTimers()) {
545 Kokkos::fence(
"timer_fence_begin_"+name);
548 top_ = top_->start(name.c_str());
549#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
551 ::Kokkos::Tools::pushRegion(name);
556 if (enable_verbose_) {
557 if (!verbose_timestamp_levels_) {
558 *verbose_ostream_ <<
"STARTING: " << name << std::endl;
562#if !defined(__GNUC__) || ( defined(__GNUC__) && (__GNUC__ > 4) )
563 else if (top_ !=
nullptr) {
564 if ( top_->level() <= verbose_timestamp_levels_) {
565 auto now = std::chrono::system_clock::now();
566 auto now_time = std::chrono::system_clock::to_time_t(
now);
568 auto timestamp = std::put_time(
gmt,
"%Y-%m-%d %H:%M:%S");
569 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) % 1000;
570 *verbose_ostream_ <<
"STARTING: " << name <<
" LEVEL: " << top_->level() <<
" COUNT: " << timer_.numCalls() <<
" TIMESTAMP: " <<
timestamp <<
"." <<
ms.count() << std::endl;
582 void stop(
const std::string &name,
584 if (enable_timers_) {
586#ifdef HAVE_TEUCHOSCORE_KOKKOS
588 if (Behavior::fenceTimers()) {
589 Kokkos::fence(
"timer_fence_end_"+name);
592#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
594 ::Kokkos::Tools::popRegion();
597 top_ = top_->stop(name);
599 timer_.BaseTimer::stop();
602 if (enable_verbose_) {
603 if (!verbose_timestamp_levels_) {
604 *verbose_ostream_ <<
"STOPPING: " << name << std::endl;
608#if !defined(__GNUC__) || ( defined(__GNUC__) && (__GNUC__ > 4) )
610 else if (top_ !=
nullptr) {
611 if ( (top_->level()+1) <= verbose_timestamp_levels_) {
612 auto now = std::chrono::system_clock::now();
613 auto now_time = std::chrono::system_clock::to_time_t(
now);
615 auto timestamp = std::put_time(
gmt,
"%Y-%m-%d %H:%M:%S");
616 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) % 1000;
617 *verbose_ostream_ <<
"STOPPING: " << name <<
" LEVEL: " << top_->level()+1 <<
" COUNT: " << timer_.numCalls() <<
" TIMESTAMP: " <<
timestamp <<
"." <<
ms.count() << std::endl;
629 top_->incrementUpdates(
i);
639 return top_->accumulatedTime(name);
641 return timer_.accumulatedTime(name);
651 return top_->accumulatedTimePerUpdate(name);
653 return timer_.accumulatedTimePerUpdate(name);
662 return top_->accumulatedTimePerTimerCall(name);
664 return timer_.accumulatedTimePerTimerCall(name);
675 "StackedTimer::findBaseTimer() failed to find a timer named \"" << name <<
"\"!\n");
684 BaseTimer::TimeInfo
findTimer(
const std::string &name) {
688 "StackedTimer::findTimer() failed to find a timer named \"" << name <<
"\"!\n");
692 void report(std::ostream &os) {
711 OutputOptions() : output_fraction(
false), output_total_updates(
false), output_histogram(
false),
712 output_minmax(
false), output_proc_minmax(
false), num_histogram(10), max_levels(
INT_MAX),
713 print_warnings(
true), align_columns(
false), print_names_before_values(
true),
714 drop_time(-1.0), output_per_proc_stddev(
false) {}
715 bool output_fraction;
716 bool output_total_updates;
717 bool output_histogram;
719 bool output_proc_minmax;
724 bool print_names_before_values;
726 bool output_per_proc_stddev;
785 void enableVerboseTimestamps(
const unsigned levels);
792 void disableTimers();
855 bool global_mpi_aggregation_called_;
859 std::string::size_type timer_names_;
860 std::string::size_type average_time_;
861 std::string::size_type fraction_;
862 std::string::size_type count_;
863 std::string::size_type total_updates_;
864 std::string::size_type min_;
865 std::string::size_type max_;
866 std::string::size_type procmin_;
867 std::string::size_type procmax_;
868 std::string::size_type stddev_;
869 std::string::size_type histogram_;
929 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.