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"
19#include "Teuchos_EnvVariables.hpp"
21#include "Teuchos_Behavior.hpp"
22#include "TeuchosComm_config.h"
23#ifdef HAVE_TEUCHOSCOMM_MAGISTRATE
24#include "checkpoint/checkpoint.h"
26#ifdef HAVE_TEUCHOSCORE_KOKKOS
27#include "Kokkos_Core.hpp"
39#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
42extern void pushRegion (
const std::string&);
43extern void popRegion ();
52TEUCHOSCOMM_LIB_DLL_EXPORT
void error_out(
const std::string& msg,
const bool fail_all =
false);
67 using Clock = std::chrono::high_resolution_clock;
69 BaseTimer() : accumulation_(0.0), accumulationSquared_(0.0), count_started_(0), count_updates_(0), running_(
false) {}
71#ifdef HAVE_TEUCHOSCOMM_MAGISTRATE
73 explicit BaseTimer(magistrate::SERIALIZE_CONSTRUCT_TAG) {}
79 template<
typename Serializer>
90 | accumulationSquared_
94 if (
s.isUnpacking()) {
103 error_out(
"Base_Timer:start Failed timer already running");
104 start_time_ = Clock::now();
113 error_out(
"Base_Timer:stop Failed timer not running");
114 auto elapsed = std::chrono::duration_cast<std::chrono::duration<double>>(Clock::now() - start_time_).count();
121 unsigned long long incrementUpdates(
unsigned long long count=1) {count_updates_ += count;
return count_updates_;}
double accumulatedTimePerUpdate()
const {
141 if (count_updates_ > 0) {
142 return accumulation_/count_updates_;
157 if (count_started_> 0) {
158 return accumulation_/count_started_;
172 if (count_started_ > 0) {
174 return sqrt(std::max<double>(accumulationSquared_ / count_started_ -
mean*
mean, 0.0));
187 return accumulation_ -
from.accumulation_;
193 error_out(
"BaseTimer, cannot reset a running timer");
195 count_started_ = count_updates_ = 0;
202 unsigned long numCalls()
const {
return count_started_; }
205 unsigned long long numUpdates()
const {
return count_updates_; }
216 TimeInfo():time(0.0), stdDev(0.0), count(0), updates(0), running(
false){}
217 TimeInfo(BaseTimer* t): time(t->accumulation_), stdDev(t->
timePerCallStdDev()), count(t->count_started_), updates(t->count_updates_), running(t->running()) {}
218 bool operator ==(
const TimeInfo& ti)
const
219 {
return (time == ti.time) &&
220 (stdDev == ti.stdDev) &&
221 (count == ti.count) &&
222 (updates == ti.updates) &&
223 (running == ti.running);}
227 unsigned long long updates;
232 double accumulation_;
233 double accumulationSquared_;
234 unsigned long count_started_;
235 unsigned long long count_updates_;
236 Clock::time_point start_time_;
239 friend struct TimeInfo;
279 std::vector<LevelTimer> sub_timers_;
292 const char* name =
"RootTimer",
308 for (
unsigned i=0;
i<sub_timers_.size();++
i)
309 sub_timers_[
i].parent_ =
this;
312#ifdef HAVE_TEUCHOSCOMM_MAGISTRATE
320 template<
typename Serializer>
331 if (
s.isUnpacking()) {
333 for (
auto&
child : sub_timers_) {
334 child.parent_ =
this;
337 for (
size_t i=0; i < sub_timers_.size(); ++i) {
349 for (
unsigned i=0;
i<sub_timers_.size();
i++ )
351 sub_timers_[
i].BaseTimer::start();
352 return &sub_timers_[
i];
355 return &sub_timers_[sub_timers_.size()-1];
367 error_out(
"Stopping timer "+name+
" But top level running timer is "+name_);
379 if ((parent_ !=
nullptr))
388 std::string get_name()
const {
400 for (
unsigned i=0;
i<sub_timers_.size(); ++
i)
401 count += sub_timers_[
i].countTimers();
407 for (
unsigned i=0;
i<sub_timers_.size(); ++
i)
408 sub_timers_[
i].addTimerNames(
names,
pos);
419 return BaseTimer::accumulatedTime();
431 for (
unsigned j=0;
j<sub_timers_.size();++
j)
468 return BaseTimer::accumulatedTimePerUpdate();
473 for (
unsigned j=0;
j<sub_timers_.size();
j++)
475 return sub_timers_[
j].accumulatedTimePerUpdate(
second_name);
487 return BaseTimer::accumulatedTimePerTimerCall();
492 for (
unsigned j=0;
j<sub_timers_.size();
j++)
494 return sub_timers_[
j].accumulatedTimePerTimerCall(
second_name);
514 void report(std::ostream &os);
521 const BaseTimer* findBaseTimer(
const std::string &name)
const;
529 BaseTimer::TimeInfo findTimer(
const std::string &name,
bool&
found);
542 global_mpi_aggregation_called_(
false),
543 enable_verbose_(
false),
544 verbose_timestamp_levels_(0),
550 this->startBaseTimer();
554 enable_verbose_ =
true;
562#ifdef HAVE_TEUCHOSCOMM_MAGISTRATE
563 explicit StackedTimer(magistrate::SERIALIZE_CONSTRUCT_TAG) {}
565 template<
typename Serializer>
566 void serialize(Serializer& s) {
569 s | verbose_timestamp_levels_;
572 if (s.isUnpacking()) {
576 verbose_ostream_ = Teuchos::rcpFromRef(std::cout);
577 global_mpi_aggregation_called_ =
false;
583 return timer_.get_full_name();
590#ifdef HAVE_TEUCHOSCORE_KOKKOS
592 if (Behavior::fenceTimers()) {
593 Kokkos::fence(
"timer_fence_begin_"+timer_.get_name());
596 timer_.BaseTimer::start();
597#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
599 ::Kokkos::Tools::pushRegion(timer_.get_name());
608#ifdef HAVE_TEUCHOSCORE_KOKKOS
610 if (Behavior::fenceTimers()) {
611 Kokkos::fence(
"timer_fence_end_"+timer_.get_name());
614#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
616 ::Kokkos::Tools::popRegion();
619 timer_.BaseTimer::stop();
629 if (enable_timers_) {
630 if (top_ ==
nullptr) {
631 top_ = timer_.start(name.c_str());
633#ifdef HAVE_TEUCHOSCORE_KOKKOS
635 if (Behavior::fenceTimers()) {
636 Kokkos::fence(
"timer_fence_begin_"+name);
639 top_ = top_->start(name.c_str());
640#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
642 ::Kokkos::Tools::pushRegion(name);
647 if (enable_verbose_) {
648 if (!verbose_timestamp_levels_) {
649 *verbose_ostream_ <<
"STARTING: " << name << std::endl;
653#if !defined(__GNUC__) || ( defined(__GNUC__) && (__GNUC__ > 4) )
654 else if (top_ !=
nullptr) {
655 if ( top_->level() <= verbose_timestamp_levels_) {
656 auto now = std::chrono::system_clock::now();
657 auto now_time = std::chrono::system_clock::to_time_t(
now);
659 auto timestamp = std::put_time(
gmt,
"%Y-%m-%d %H:%M:%S");
660 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) % 1000;
661 *verbose_ostream_ <<
"STARTING: " << name <<
" LEVEL: " << top_->level() <<
" COUNT: " << timer_.numCalls() <<
" TIMESTAMP: " <<
timestamp <<
"." <<
ms.count() << std::endl;
673 void stop(
const std::string &name,
675 if (enable_timers_) {
677#ifdef HAVE_TEUCHOSCORE_KOKKOS
679 if (Behavior::fenceTimers()) {
680 Kokkos::fence(
"timer_fence_end_"+name);
683#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
685 ::Kokkos::Tools::popRegion();
688 top_ = top_->stop(name);
690 timer_.BaseTimer::stop();
693 if (enable_verbose_) {
694 if (!verbose_timestamp_levels_) {
695 *verbose_ostream_ <<
"STOPPING: " << name << std::endl;
699#if !defined(__GNUC__) || ( defined(__GNUC__) && (__GNUC__ > 4) )
701 else if (top_ !=
nullptr) {
702 if ( (top_->level()+1) <= verbose_timestamp_levels_) {
703 auto now = std::chrono::system_clock::now();
704 auto now_time = std::chrono::system_clock::to_time_t(
now);
706 auto timestamp = std::put_time(
gmt,
"%Y-%m-%d %H:%M:%S");
707 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) % 1000;
708 *verbose_ostream_ <<
"STOPPING: " << name <<
" LEVEL: " << top_->level()+1 <<
" COUNT: " << timer_.numCalls() <<
" TIMESTAMP: " <<
timestamp <<
"." <<
ms.count() << std::endl;
720 top_->incrementUpdates(
i);
730 return top_->accumulatedTime(name);
732 return timer_.accumulatedTime(name);
742 return top_->accumulatedTimePerUpdate(name);
744 return timer_.accumulatedTimePerUpdate(name);
753 return top_->accumulatedTimePerTimerCall(name);
755 return timer_.accumulatedTimePerTimerCall(name);
766 "StackedTimer::findBaseTimer() failed to find a timer named \"" << name <<
"\"!\n");
775 BaseTimer::TimeInfo
findTimer(
const std::string &name) {
779 "StackedTimer::findTimer() failed to find a timer named \"" << name <<
"\"!\n");
783 void report(std::ostream &os) {
802 OutputOptions() : output_fraction(
false), output_total_updates(
false), output_histogram(
false),
803 output_minmax(
false), output_proc_minmax(
false), num_histogram(10), max_levels(
INT_MAX),
804 print_warnings(
true), align_columns(
false), print_names_before_values(
true),
805 drop_time(-1.0), output_per_proc_stddev(
false) {}
806 bool output_fraction;
807 bool output_total_updates;
808 bool output_histogram;
810 bool output_proc_minmax;
815 bool print_names_before_values;
817 bool output_per_proc_stddev;
876 void enableVerboseTimestamps(
const unsigned levels);
883 void disableTimers();
936 std::stack<std::string> stopAllTimers();
969 bool global_mpi_aggregation_called_;
973 std::string::size_type timer_names_;
974 std::string::size_type average_time_;
975 std::string::size_type fraction_;
976 std::string::size_type count_;
977 std::string::size_type total_updates_;
978 std::string::size_type min_;
979 std::string::size_type max_;
980 std::string::size_type procmin_;
981 std::string::size_type procmax_;
982 std::string::size_type stddev_;
983 std::string::size_type histogram_;
1043 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,...
const char * getEnvironmentVariableValue(const char name[])
Read a process environment variable by name.
void error_out(const std::string &msg, const bool)
Error reporting function for stacked timer.
Stores the column widths for output alignment.