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#include "TeuchosComm_config.h"
22#ifdef HAVE_TEUCHOSCOMM_MAGISTRATE
23#include "checkpoint/checkpoint.h"
25#ifdef HAVE_TEUCHOSCORE_KOKKOS
26#include "Kokkos_Core.hpp"
38#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
41extern void pushRegion (
const std::string&);
42extern void popRegion ();
51TEUCHOSCOMM_LIB_DLL_EXPORT
void error_out(
const std::string& msg,
const bool fail_all =
false);
66 using Clock = std::chrono::high_resolution_clock;
68 BaseTimer() : accumulation_(0.0), accumulationSquared_(0.0), count_started_(0), count_updates_(0), running_(
false) {}
70#ifdef HAVE_TEUCHOSCOMM_MAGISTRATE
72 explicit BaseTimer(magistrate::SERIALIZE_CONSTRUCT_TAG) {}
78 template<
typename Serializer>
89 | accumulationSquared_
93 if (
s.isUnpacking()) {
102 error_out(
"Base_Timer:start Failed timer already running");
103 start_time_ = Clock::now();
112 error_out(
"Base_Timer:stop Failed timer not running");
113 auto elapsed = std::chrono::duration_cast<std::chrono::duration<double>>(Clock::now() - start_time_).count();
120 unsigned long long incrementUpdates(
unsigned long long count=1) {count_updates_ += count;
return count_updates_;}
double accumulatedTimePerUpdate()
const {
140 if (count_updates_ > 0) {
141 return accumulation_/count_updates_;
156 if (count_started_> 0) {
157 return accumulation_/count_started_;
171 if (count_started_ > 0) {
173 return sqrt(std::max<double>(accumulationSquared_ / count_started_ -
mean*
mean, 0.0));
186 return accumulation_ -
from.accumulation_;
192 error_out(
"BaseTimer, cannot reset a running timer");
194 count_started_ = count_updates_ = 0;
201 unsigned long numCalls()
const {
return count_started_; }
204 unsigned long long numUpdates()
const {
return count_updates_; }
215 TimeInfo():time(0.0), stdDev(0.0), count(0), updates(0), running(
false){}
216 TimeInfo(BaseTimer* t): time(t->accumulation_), stdDev(t->
timePerCallStdDev()), count(t->count_started_), updates(t->count_updates_), running(t->running()) {}
217 bool operator ==(
const TimeInfo& ti)
218 {
return (time == ti.time) &&
219 (stdDev == ti.stdDev) &&
220 (count == ti.count) &&
221 (updates == ti.updates) &&
222 (running == ti.running);}
226 unsigned long long updates;
231 double accumulation_;
232 double accumulationSquared_;
233 unsigned long count_started_;
234 unsigned long long count_updates_;
235 Clock::time_point start_time_;
238 friend struct TimeInfo;
278 std::vector<LevelTimer> sub_timers_;
291 const char* name =
"RootTimer",
307 for (
unsigned i=0;
i<sub_timers_.size();++
i)
308 sub_timers_[
i].parent_ =
this;
311#ifdef HAVE_TEUCHOSCOMM_MAGISTRATE
319 template<
typename Serializer>
330 if (
s.isUnpacking()) {
332 for (
auto&
child : sub_timers_) {
333 child.parent_ =
this;
336 for (
size_t i=0; i < sub_timers_.size(); ++i) {
348 for (
unsigned i=0;
i<sub_timers_.size();
i++ )
350 sub_timers_[
i].BaseTimer::start();
351 return &sub_timers_[
i];
354 return &sub_timers_[sub_timers_.size()-1];
366 error_out(
"Stopping timer "+name+
" But top level running timer is "+name_);
378 if ((parent_ !=
nullptr))
387 std::string get_name()
const {
399 for (
unsigned i=0;
i<sub_timers_.size(); ++
i)
400 count += sub_timers_[
i].countTimers();
406 for (
unsigned i=0;
i<sub_timers_.size(); ++
i)
407 sub_timers_[
i].addTimerNames(
names,
pos);
418 return BaseTimer::accumulatedTime();
430 for (
unsigned j=0;
j<sub_timers_.size();++
j)
467 return BaseTimer::accumulatedTimePerUpdate();
472 for (
unsigned j=0;
j<sub_timers_.size();
j++)
474 return sub_timers_[
j].accumulatedTimePerUpdate(
second_name);
486 return BaseTimer::accumulatedTimePerTimerCall();
491 for (
unsigned j=0;
j<sub_timers_.size();
j++)
493 return sub_timers_[
j].accumulatedTimePerTimerCall(
second_name);
513 void report(std::ostream &os);
520 const BaseTimer* findBaseTimer(
const std::string &name)
const;
528 BaseTimer::TimeInfo findTimer(
const std::string &name,
bool&
found);
541 global_mpi_aggregation_called_(
false),
542 enable_verbose_(
false),
543 verbose_timestamp_levels_(0),
549 this->startBaseTimer();
551 auto check_verbose = std::getenv(
"TEUCHOS_ENABLE_VERBOSE_TIMERS");
553 enable_verbose_ =
true;
555 auto check_timestamp = std::getenv(
"TEUCHOS_ENABLE_VERBOSE_TIMESTAMP_LEVELS");
561#ifdef HAVE_TEUCHOSCOMM_MAGISTRATE
562 explicit StackedTimer(magistrate::SERIALIZE_CONSTRUCT_TAG) {}
564 template<
typename Serializer>
565 void serialize(Serializer& s) {
568 s | verbose_timestamp_levels_;
571 if (s.isUnpacking()) {
575 verbose_ostream_ = Teuchos::rcpFromRef(std::cout);
576 global_mpi_aggregation_called_ =
false;
582 return timer_.get_full_name();
589#ifdef HAVE_TEUCHOSCORE_KOKKOS
591 if (Behavior::fenceTimers()) {
592 Kokkos::fence(
"timer_fence_begin_"+timer_.get_name());
595 timer_.BaseTimer::start();
596#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
598 ::Kokkos::Tools::pushRegion(timer_.get_name());
607#ifdef HAVE_TEUCHOSCORE_KOKKOS
609 if (Behavior::fenceTimers()) {
610 Kokkos::fence(
"timer_fence_end_"+timer_.get_name());
613#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
615 ::Kokkos::Tools::popRegion();
618 timer_.BaseTimer::stop();
628 if (enable_timers_) {
629 if (top_ ==
nullptr) {
630 top_ = timer_.start(name.c_str());
632#ifdef HAVE_TEUCHOSCORE_KOKKOS
634 if (Behavior::fenceTimers()) {
635 Kokkos::fence(
"timer_fence_begin_"+name);
638 top_ = top_->start(name.c_str());
639#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
641 ::Kokkos::Tools::pushRegion(name);
646 if (enable_verbose_) {
647 if (!verbose_timestamp_levels_) {
648 *verbose_ostream_ <<
"STARTING: " << name << std::endl;
652#if !defined(__GNUC__) || ( defined(__GNUC__) && (__GNUC__ > 4) )
653 else if (top_ !=
nullptr) {
654 if ( top_->level() <= verbose_timestamp_levels_) {
655 auto now = std::chrono::system_clock::now();
656 auto now_time = std::chrono::system_clock::to_time_t(
now);
658 auto timestamp = std::put_time(
gmt,
"%Y-%m-%d %H:%M:%S");
659 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) % 1000;
660 *verbose_ostream_ <<
"STARTING: " << name <<
" LEVEL: " << top_->level() <<
" COUNT: " << timer_.numCalls() <<
" TIMESTAMP: " <<
timestamp <<
"." <<
ms.count() << std::endl;
672 void stop(
const std::string &name,
674 if (enable_timers_) {
676#ifdef HAVE_TEUCHOSCORE_KOKKOS
678 if (Behavior::fenceTimers()) {
679 Kokkos::fence(
"timer_fence_end_"+name);
682#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
684 ::Kokkos::Tools::popRegion();
687 top_ = top_->stop(name);
689 timer_.BaseTimer::stop();
692 if (enable_verbose_) {
693 if (!verbose_timestamp_levels_) {
694 *verbose_ostream_ <<
"STOPPING: " << name << std::endl;
698#if !defined(__GNUC__) || ( defined(__GNUC__) && (__GNUC__ > 4) )
700 else if (top_ !=
nullptr) {
701 if ( (top_->level()+1) <= verbose_timestamp_levels_) {
702 auto now = std::chrono::system_clock::now();
703 auto now_time = std::chrono::system_clock::to_time_t(
now);
705 auto timestamp = std::put_time(
gmt,
"%Y-%m-%d %H:%M:%S");
706 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) % 1000;
707 *verbose_ostream_ <<
"STOPPING: " << name <<
" LEVEL: " << top_->level()+1 <<
" COUNT: " << timer_.numCalls() <<
" TIMESTAMP: " <<
timestamp <<
"." <<
ms.count() << std::endl;
719 top_->incrementUpdates(
i);
729 return top_->accumulatedTime(name);
731 return timer_.accumulatedTime(name);
741 return top_->accumulatedTimePerUpdate(name);
743 return timer_.accumulatedTimePerUpdate(name);
752 return top_->accumulatedTimePerTimerCall(name);
754 return timer_.accumulatedTimePerTimerCall(name);
765 "StackedTimer::findBaseTimer() failed to find a timer named \"" << name <<
"\"!\n");
774 BaseTimer::TimeInfo
findTimer(
const std::string &name) {
778 "StackedTimer::findTimer() failed to find a timer named \"" << name <<
"\"!\n");
782 void report(std::ostream &os) {
801 OutputOptions() : output_fraction(
false), output_total_updates(
false), output_histogram(
false),
802 output_minmax(
false), output_proc_minmax(
false), num_histogram(10), max_levels(
INT_MAX),
803 print_warnings(
true), align_columns(
false), print_names_before_values(
true),
804 drop_time(-1.0), output_per_proc_stddev(
false) {}
805 bool output_fraction;
806 bool output_total_updates;
807 bool output_histogram;
809 bool output_proc_minmax;
814 bool print_names_before_values;
816 bool output_per_proc_stddev;
875 void enableVerboseTimestamps(
const unsigned levels);
882 void disableTimers();
935 std::stack<std::string> stopAllTimers();
968 bool global_mpi_aggregation_called_;
972 std::string::size_type timer_names_;
973 std::string::size_type average_time_;
974 std::string::size_type fraction_;
975 std::string::size_type count_;
976 std::string::size_type total_updates_;
977 std::string::size_type min_;
978 std::string::size_type max_;
979 std::string::size_type procmin_;
980 std::string::size_type procmax_;
981 std::string::size_type stddev_;
982 std::string::size_type histogram_;
1042 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.
Strategy interface for the indirect serializing and deserializing objects of a given type handled usi...
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_ASSERT(assertion_test)
This macro is throws when an assert fails.
#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.