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"
29#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
32extern void pushRegion (
const std::string&);
33extern void popRegion ();
42TEUCHOSCOMM_LIB_DLL_EXPORT
void error_out(
const std::string& msg,
const bool fail_all =
false);
57 using Clock = std::chrono::high_resolution_clock;
59 BaseTimer() : accumulation_(0.0), count_started_(0), count_updates_(0), running_(
false) {}
64 error_out(
"Base_Timer:start Failed timer already running");
65 start_time_ = Clock::now();
74 error_out(
"Base_Timer:stop Failed timer not running");
75 accumulation_ += std::chrono::duration_cast<std::chrono::duration<double>>(Clock::now() - start_time_).count();
80 unsigned long long incrementUpdates(
unsigned long long count=1) {count_updates_ += count;
return count_updates_;}
97 if (count_updates_ > 0) {
98 return accumulation_/count_updates_;
113 if (count_started_> 0) {
114 return accumulation_/count_started_;
127 return accumulation_ - from.accumulation_;
133 error_out(
"BaseTimer, cannot reset a running timer");
135 count_started_ = count_updates_ = 0;
142 unsigned long numCalls()
const {
return count_started_; }
145 unsigned long long numUpdates()
const {
return count_updates_; }
149 { count_started_ = num_calls; }
153 { count_updates_ = num_updates; }
156 TimeInfo():time(0.0), count(0), updates(0),
running(false){}
157 TimeInfo(BaseTimer* t): time(t->accumulation_), count(t->count_started_), updates(t->count_updates_),
running(t->
running()) {}
160 unsigned long long updates;
165 double accumulation_;
166 unsigned long count_started_;
167 unsigned long long count_updates_;
168 Clock::time_point start_time_;
171 friend struct TimeInfo;
211 std::vector<LevelTimer> sub_timers_;
224 const char* name =
"RootTimer",
226 bool start_timer=
true) :
239 BaseTimer(src), level_(src.level_), name_(src.name_),parent_(src.parent_), sub_timers_(src.sub_timers_)
241 for (
unsigned i=0;i<sub_timers_.size();++i)
242 sub_timers_[i].parent_ =
this;
251 for (
unsigned i=0;i<sub_timers_.size();i++ )
252 if (sub_name == sub_timers_[i].name_ ) {
253 sub_timers_[i].BaseTimer::start();
254 return &sub_timers_[i];
256 sub_timers_.push_back(
LevelTimer(level_+1,sub_name,
this,
true));
257 return &sub_timers_[sub_timers_.size()-1];
269 error_out(
"Stopping timer "+name+
" But top level running timer is "+name_);
280 std::string parent_name(
"");
281 if ((parent_ !=
nullptr))
282 parent_name = parent_->get_full_name() +
"@";
284 std::string my_name(name_);
286 std::string full_name = parent_name + my_name;
297 for (
unsigned i=0;i<sub_timers_.size(); ++i)
303 names[pos++] = get_full_name();
304 for (
unsigned i=0;i<sub_timers_.size(); ++i)
305 sub_timers_[i].addTimerNames(names, pos);
315 if (locate_name ==
"")
318 std::string first_name,second_name;
320 size_t i = locate_name.find_first_of(
'@');
321 if ( i >= locate_name.size() ) {
322 first_name = locate_name;
325 first_name.assign(locate_name,0,i);
326 second_name.assign(locate_name,i+1,locate_name.size()-i-1);
328 for (
unsigned j=0;j<sub_timers_.size();++j)
329 if ( first_name == sub_timers_[j].name_)
330 return sub_timers_[j].accumulatedTime(second_name);
345 void splitString(
const std::string &locate_name, std::string &first_name, std::string &second_name) {
346 size_t i = locate_name.find_first_of(
'@');
347 if ( i >= locate_name.size() ) {
348 first_name = locate_name;
351 first_name.assign(locate_name,0,i);
352 second_name.assign(locate_name,i+1,locate_name.size()-i-1);
364 if (locate_name ==
"")
367 std::string first_name,second_name;
370 for (
unsigned j=0;j<sub_timers_.size();j++)
371 if ( first_name == sub_timers_[j].name_)
372 return sub_timers_[j].accumulatedTimePerUpdate(second_name);
383 if (locate_name ==
"")
386 std::string first_name,second_name;
389 for (
unsigned j=0;j<sub_timers_.size();j++)
390 if ( first_name == sub_timers_[j].name_)
391 return sub_timers_[j].accumulatedTimePerTimerCall(second_name);
411 void report(std::ostream &os);
418 const BaseTimer*
findBaseTimer(
const std::string &name)
const;
426 BaseTimer::TimeInfo
findTimer(
const std::string &name,
bool& found);
437 explicit StackedTimer(
const char *name,
const bool start_base_timer =
true)
438 :
timer_(0,name,nullptr,false),
439 global_mpi_aggregation_called_(false),
446 if (start_base_timer)
449 auto check_verbose = std::getenv(
"TEUCHOS_ENABLE_VERBOSE_TIMERS");
450 if (check_verbose !=
nullptr)
453 auto check_timestamp = std::getenv(
"TEUCHOS_ENABLE_VERBOSE_TIMESTAMP_LEVELS");
454 if (check_timestamp !=
nullptr) {
463 timer_.BaseTimer::start();
464#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
465 ::Kokkos::Tools::pushRegion(
timer_.get_full_name());
474#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
475 ::Kokkos::Tools::popRegion();
485 const bool push_kokkos_profiling_region =
true) {
491#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
492 if (push_kokkos_profiling_region) {
493 ::Kokkos::Tools::pushRegion(name);
503#if !defined(__GNUC__) || ( defined(__GNUC__) && (__GNUC__ > 4) )
504 else if (
top_ !=
nullptr) {
506 auto now = std::chrono::system_clock::now();
507 auto now_time = std::chrono::system_clock::to_time_t(now);
508 auto gmt = gmtime(&now_time);
509 auto timestamp = std::put_time(gmt,
"%Y-%m-%d %H:%M:%S");
510 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
511 *
verbose_ostream_ <<
"STARTING: " << name <<
" LEVEL: " <<
top_->level() <<
" COUNT: " <<
timer_.numCalls() <<
" TIMESTAMP: " << timestamp <<
"." << ms.count() << std::endl;
523 void stop(
const std::string &name,
524 const bool pop_kokkos_profiling_region =
true) {
530#if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
531 if (pop_kokkos_profiling_region) {
532 ::Kokkos::Tools::popRegion();
542#if !defined(__GNUC__) || ( defined(__GNUC__) && (__GNUC__ > 4) )
544 else if (
top_ !=
nullptr) {
546 auto now = std::chrono::system_clock::now();
547 auto now_time = std::chrono::system_clock::to_time_t(now);
548 auto gmt = gmtime(&now_time);
549 auto timestamp = std::put_time(gmt,
"%Y-%m-%d %H:%M:%S");
550 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
551 *
verbose_ostream_ <<
"STOPPING: " << name <<
" LEVEL: " <<
top_->level()+1 <<
" COUNT: " <<
timer_.numCalls() <<
" TIMESTAMP: " << timestamp <<
"." << ms.count() << std::endl;
563 top_->incrementUpdates(i);
573 return top_->accumulatedTime(name);
575 return timer_.accumulatedTime(name);
585 return top_->accumulatedTimePerUpdate(name);
587 return timer_.accumulatedTimePerUpdate(name);
596 return top_->accumulatedTimePerTimerCall(name);
598 return timer_.accumulatedTimePerTimerCall(name);
609 "StackedTimer::findBaseTimer() failed to find a timer named \"" << name <<
"\"!\n");
618 BaseTimer::TimeInfo
findTimer(
const std::string &name) {
619 bool foundTimer =
false;
620 const auto timeInfo =
timer_.findTimer(name,foundTimer);
622 "StackedTimer::findTimer() failed to find a timer named \"" << name <<
"\"!\n");
626 void report(std::ostream &os) {
643 struct OutputOptions {
644 OutputOptions() : output_fraction(
false), output_total_updates(
false), output_histogram(
false),
645 output_minmax(
false), output_proc_minmax(
false), num_histogram(10), max_levels(INT_MAX),
646 print_warnings(
true), align_columns(
false), print_names_before_values(
true),
648 bool output_fraction;
649 bool output_total_updates;
650 bool output_histogram;
652 bool output_proc_minmax;
657 bool print_names_before_values;
765 bool isTimer(
const std::string& flat_timer_name);
785 bool global_mpi_aggregation_called_;
788 struct AlignmentWidths {
789 std::string::size_type timer_names_;
790 std::string::size_type average_time_;
791 std::string::size_type fraction_;
792 std::string::size_type count_;
793 std::string::size_type total_updates_;
794 std::string::size_type min_;
795 std::string::size_type max_;
796 std::string::size_type procmin_;
797 std::string::size_type procmax_;
798 std::string::size_type stddev_;
799 std::string::size_type histogram_;
853 std::vector<bool> &printed,
double parent_time,
859 double printLevel(std::string prefix,
int level, std::ostream &os, std::vector<bool> &printed,
866 double printLevelXML(std::string prefix,
int level, std::ostream &os, std::vector<bool> &printed,
double parent_time,
const std::string& rootName =
"");
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.
Replacement for std::vector that is compatible with the Teuchos Memory Management classes.
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.
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.
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.
Abstract interface for distributed-memory communication.
Smart reference counting pointer class for automatic garbage collection.
RCP< T > rcpFromRef(T &r)
Return a non-owning weak RCP object from a raw object reference for a defined type.
Timer info at a given level and all the children.
double accumulatedTime(const std::string &locate_name="")
LevelTimer * start(const char *sub_name)
void report(std::ostream &os)
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.
BaseTimer::TimeInfo findTimer(const std::string &name, bool &found)
const BaseTimer * findBaseTimer(const std::string &name) const
LevelTimer * stop(const std::string &name="RootTimer")
unsigned level() const
Returns the level of the timer in the stack.
LevelTimer()
Default constructor, shouldn't be used but needed for std::vector.
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)
LevelTimer * top_
Current level running.
double computeColumnWidthsForAligment(std::string prefix, int print_level, std::vector< bool > &printed, double parent_time, const OutputOptions &options)
void collectRemoteData(Teuchos::RCP< const Teuchos::Comm< int > > comm, const OutputOptions &options)
double getMpiAverageTime(const std::string &flat_timer_name)
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)
const BaseTimer * findBaseTimer(const std::string &name) const
Teuchos::RCP< std::ostream > verbose_ostream_
For debugging, this is the ostream used for printing.
double printLevelXML(std::string prefix, int level, std::ostream &os, std::vector< bool > &printed, double parent_time, const std::string &rootName="")
void enableVerboseTimestamps(const unsigned levels)
Enable timestamps in verbose mode for the number of levels specified.
double accumulatedTimePerUpdate(const std::string &name="")
void incrementUpdates(const long long i=1)
int getFlatNameIndex(const std::string &flat_timer_name)
void setVerboseOstream(const Teuchos::RCP< std::ostream > &os)
Set the ostream for verbose mode(defaults to std::cout).
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="")
void aggregateMpiData(Teuchos::RCP< const Teuchos::Comm< int > > comm, OutputOptions options=OutputOptions())
void merge(Teuchos::RCP< const Teuchos::Comm< int > > comm)
bool isTimer(const std::string &flat_timer_name)
double printLevel(std::string prefix, int level, std::ostream &os, std::vector< bool > &printed, double parent_time, const OutputOptions &options)
StackedTimer(const char *name, const bool start_base_timer=true)
void enableVerbose(const bool enable_verbose)
If set to true, print timer start/stop to verbose ostream.
std::string reportWatchrXML(const std::string &name, Teuchos::RCP< const Teuchos::Comm< int > > comm)
double getMpiAverageCount(const std::string &flat_timer_name)
void reportXML(std::ostream &os, const std::string &datestamp, const std::string ×tamp, Teuchos::RCP< const Teuchos::Comm< int > > comm)
#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.