10 #ifndef TEUCHOS_STACKED_TIMER_HPP
11 #define TEUCHOS_STACKED_TIMER_HPP
29 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
32 extern void pushRegion (
const std::string&);
33 extern void popRegion ();
57 using Clock = std::chrono::high_resolution_clock;
64 error_out(
"Base_Timer:start Failed timer already running");
74 error_out(
"Base_Timer:stop Failed timer not running");
133 error_out(
"BaseTimer, cannot reset a running timer");
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)
298 count += sub_timers_[i].countTimers();
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;
368 splitString(locate_name, 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;
387 splitString(locate_name, 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;
437 explicit StackedTimer(
const char *name,
const bool start_base_timer =
true)
438 : timer_(0,name,nullptr,false),
439 global_mpi_aggregation_called_(false),
440 enable_verbose_(false),
441 verbose_timestamp_levels_(0),
442 verbose_ostream_(Teuchos::rcpFromRef(std::cout)),
446 if (start_base_timer)
447 this->startBaseTimer();
449 auto check_verbose = std::getenv(
"TEUCHOS_ENABLE_VERBOSE_TIMERS");
450 if (check_verbose !=
nullptr)
451 enable_verbose_ =
true;
453 auto check_timestamp = std::getenv(
"TEUCHOS_ENABLE_VERBOSE_TIMESTAMP_LEVELS");
454 if (check_timestamp !=
nullptr) {
455 verbose_timestamp_levels_ = std::atoi(check_timestamp);
463 timer_.BaseTimer::start();
464 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
465 ::Kokkos::Tools::pushRegion(timer_.get_full_name());
473 timer_.BaseTimer::stop();
474 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
475 ::Kokkos::Tools::popRegion();
485 const bool push_kokkos_profiling_region =
true) {
486 if (enable_timers_) {
488 top_ = timer_.start(name.c_str());
490 top_ = top_->start(name.c_str());
491 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
492 if (push_kokkos_profiling_region) {
493 ::Kokkos::Tools::pushRegion(name);
497 if (enable_verbose_) {
498 if (!verbose_timestamp_levels_) {
499 *verbose_ostream_ <<
"STARTING: " << name << std::endl;
503 #if !defined(__GNUC__) || ( defined(__GNUC__) && (__GNUC__ > 4) )
504 else if (top_ !=
nullptr) {
505 if ( top_->level() <= verbose_timestamp_levels_) {
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) {
525 if (enable_timers_) {
527 top_ = top_->stop(name);
529 timer_.BaseTimer::stop();
530 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOS)
531 if (pop_kokkos_profiling_region) {
532 ::Kokkos::Tools::popRegion();
536 if (enable_verbose_) {
537 if (!verbose_timestamp_levels_) {
538 *verbose_ostream_ <<
"STOPPING: " << name << std::endl;
542 #if !defined(__GNUC__) || ( defined(__GNUC__) && (__GNUC__ > 4) )
544 else if (top_ !=
nullptr) {
545 if ( (top_->level()+1) <= verbose_timestamp_levels_) {
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);
607 const BaseTimer* baseTimer = timer_.findBaseTimer(name);
609 "StackedTimer::findBaseTimer() failed to find a timer named \"" << name <<
"\"!\n");
619 bool foundTimer =
false;
620 const auto timeInfo = timer_.findTimer(name,foundTimer);
622 "StackedTimer::findTimer() failed to find a timer named \"" << name <<
"\"!\n");
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),
714 void enableVerbose(
const bool enable_verbose);
717 void enableVerboseTimestamps(
const unsigned levels);
724 void disableTimers();
745 double getMpiAverageTime(
const std::string& flat_timer_name);
755 double getMpiAverageCount(
const std::string& flat_timer_name);
765 bool isTimer(
const std::string& flat_timer_name);
844 int getFlatNameIndex(
const std::string& flat_timer_name);
852 double computeColumnWidthsForAligment(std::string prefix,
int print_level,
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 =
"");
void setAccumulatedTime(double accum=0)
Setter for accumulated time.
double accumulatedTimePerTimerCall(const std::string &name="")
Clock::time_point start_time_
double difference(const BaseTimer &from) const
Return the difference between two timers in seconds,.
StackedTimer(const char *name, const bool start_base_timer=true)
void overrideNumUpdatesForUnitTesting(const unsigned long long num_updates)
Sets the number of counts for this timer. This is only used for unit testing.
std::string::size_type timer_names_
double accumulatedTime() const
Get the total accumulated time since last reset or construction when the timer is running...
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 ...
void stop(const std::string &name, const bool pop_kokkos_profiling_region=true)
LevelTimer(int level, const char *name="RootTimer", LevelTimer *parent=nullptr, bool start_timer=true)
unsigned long long incrementUpdates(unsigned long long count=1)
Increment the total number of items updated between a start stop.
std::string::size_type histogram_
std::string::size_type average_time_
bool running() const
Returns true if the timer is currently accumulating time.
std::string::size_type total_updates_
double accumulatedTimePerTimerCall() const
return the average time per timer start/stop
std::string::size_type procmax_
std::vector< LevelTimer > sub_timers_
void addTimerNames(Array< std::string > &names, unsigned &pos)
unsigned long count_started_
std::string::size_type max_
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
double accumulatedTimePerUpdate() const
return the average time per item updated
Teuchos header file which uses auto-configuration information to include necessary C++ headers...
std::string::size_type procmin_
bool enable_verbose_
If set to true, prints to the debug ostream. At construction, default value is set from environment v...
void incrementUpdates(const long long i=1)
void start()
Start a currently stopped timer.
LevelTimer * top_
Current level running.
bool enable_timers_
Used to disable timers for asynchronous work.
double accumulatedTimePerUpdate(const std::string &name="")
unsigned verbose_timestamp_levels_
If set to a value greater than 0, verbose mode will print that many levels of timers with timestamps...
unsigned long numCalls() const
Returns the number of calls to start().
double accumulatedTime(const std::string &name="")
std::string::size_type fraction_
std::string::size_type count_
void start(const std::string name, const bool push_kokkos_profiling_region=true)
double accumulatedTime(const std::string &locate_name="")
void overrideNumCallsForUnitTesting(const unsigned long num_calls)
Sets the number of calls to start() for this timer. This is only used for unit testing.
void error_out(const std::string &msg, const bool)
Error reporting function for stacked timer.
The basic timer used internally, uses std::chrono::high_resolution_clock.
Stores the column widths for output alignment.
Array< Array< int > > hist_
std::chrono::high_resolution_clock Clock
LevelTimer(const LevelTimer &src)
Copy constructor.
bool print_names_before_values
Array< unsigned long long > updates_
Timer info at a given level and all the children.
std::string::size_type min_
const BaseTimer * findBaseTimer(const std::string &name) const
double accumulatedTimePerUpdate(const std::string &locate_name="")
Teuchos::RCP< std::ostream > verbose_ostream_
For debugging, this is the ostream used for printing.
LevelTimer timer_
Base timer.
double accumulatedTimePerTimerCall(const std::string &locate_name="")
Templated array class derived from the STL std::vector.
LevelTimer * stop(const std::string &name="RootTimer")
void reset()
Reset all the timer stats, throws if it is already running.
Array< std::string > flat_names_
void stop()
Stop a current running timer and accumulate time difference.
unsigned level() const
Returns the level of the timer in the stack.
bool global_mpi_aggregation_called_
void report(std::ostream &os)
#define TEUCHOSCOMM_LIB_DLL_EXPORT
unsigned long long count_updates_
Smart reference counting pointer class for automatic garbage collection.
BaseTimer::TimeInfo findTimer(const std::string &name)
This class allows one to push and pop timers on and off a stack.
unsigned long long numUpdates() const
Returns the number of updates added to this timer.
Array< unsigned long > count_
std::string::size_type stddev_
unsigned long long updates
bool output_total_updates
Reference-counted pointer class and non-member templated function implementations.
LevelTimer * start(const char *sub_name)
std::string get_full_name() const