17 #include <sys/times.h> 19 #include <sys/resource.h> 25 #include <stk_util/util/FeatureTest.hpp> 27 #ifdef SIERRA_INCLUDE_LIBPAPI 29 # if defined(PAPI_VERSION) && (PAPI_VERSION_MAJOR(PAPI_VERSION) != 3) 30 # error "Compiling against an unknown PAPI version" 43 #include <stk_util/diag/Writer.hpp> 44 #include <stk_util/diag/Timer.hpp> 45 #include <stk_util/diag/PrintTable.hpp> 46 #include <stk_util/diag/Env.hpp> 47 #include <stk_util/parallel/MPI.hpp> 49 #include <stk_util/util/string_case_compare.hpp> 51 #include <stk_util/diag/WriterExt.hpp> 58 MetricsMask s_enabledMetricsMask = METRICS_LAP_COUNT | METRICS_CPU_TIME | METRICS_WALL_TIME;
61 typename MetricTraits<T>::Type
63 if (MetricTraits<T>::METRIC & getEnabledTimerMetricsMask())
64 return MetricTraits<T>::value_now();
69 std::vector<std::string> &
71 const std::string & path,
73 std::vector<std::string> & path_vector)
75 for (std::string::const_iterator it = path.begin(); ; ) {
76 std::string::const_iterator it2 =
std::find(it, path.end(), separator);
77 path_vector.push_back(std::string(it, it2));
78 if (it2 == path.end())
89 MetricsMask getEnabledTimerMetricsMask()
91 return s_enabledMetricsMask;
95 setEnabledTimerMetricsMask(
96 MetricsMask timer_mask)
98 s_enabledMetricsMask = timer_mask | METRICS_LAP_COUNT;
128 static void updateRootTimer(TimerImpl *root_timer);
130 static Timer createRootTimer(
const std::string &name,
const TimerSet &timer_set);
132 static void deleteRootTimer(TimerImpl *root_timer);
134 static std::vector<Timer> &findTimers(TimerImpl *root_timer,
const std::string &path_tail, std::vector<Timer> &found_timers);
136 static void findTimer(TimerImpl *timer, std::vector<std::string> &path_tail_vector, std::vector<Timer> &found_timers);
148 static TimerImpl *reg(
const std::string &name, TimerMask timer_mask, TimerImpl *parent_timer,
const TimerSet &timer_set) {
149 return parent_timer->addSubtimer(name, timer_mask, timer_set);
159 TimerImpl(
const std::string &name, TimerMask timer_mask, TimerImpl *parent_timer,
const TimerSet &timer_set);
167 TimerImpl(
const TimerImpl &TimerImpl);
168 TimerImpl &operator=(
const TimerImpl &TimerImpl);
176 #ifdef __INTEL_COMPILER 177 #pragma warning(push) 178 #pragma warning(disable: 444) 180 class finder :
private std::unary_function<Timer, bool>
183 explicit finder(
const std::string &name)
187 bool operator()(Timer timer)
const {
194 #ifdef __INTEL_COMPILER 205 const std::string &getName()
const {
214 TimerMask getTimerMask()
const {
223 const TimerSet &getTimerSet()
const {
235 bool shouldRecord()
const {
236 return m_timerSet.
shouldRecord(m_timerMask) && s_enabledMetricsMask;
245 double getSubtimerLapCount()
const {
246 return m_subtimerLapCount;
249 void setSubtimerLapCount(
double value) {
250 m_subtimerLapCount = value;
261 const Timer::Metric<T> &getMetric()
const;
270 const TimerList &getTimerList()
const {
271 return m_subtimerList;
274 TimerList::iterator begin() {
275 return m_subtimerList.begin();
278 TimerList::const_iterator begin()
const {
279 return m_subtimerList.begin();
282 TimerList::iterator end() {
283 return m_subtimerList.end();
286 TimerList::const_iterator end()
const {
287 return m_subtimerList.end();
300 void checkpoint()
const;
331 double accumulateSubtimerLapCounts()
const;
333 Timer getSubtimer(
const std::string &name);
344 Writer &
dump(Writer &dout)
const;
358 TimerImpl *addSubtimer(
const std::string &name, TimerMask timer_mask,
const TimerSet &timer_set);
362 TimerMask m_timerMask;
363 TimerImpl * m_parentTimer;
364 mutable double m_subtimerLapCount;
365 unsigned m_lapStartCount;
367 TimerList m_subtimerList;
369 const TimerSet & m_timerSet;
370 Timer::Metric<LapCount> m_lapCount;
371 Timer::Metric<CPUTime> m_cpuTime;
372 Timer::Metric<WallTime> m_wallTime;
373 Timer::Metric<MPICount> m_MPICount;
374 Timer::Metric<MPIByteCount> m_MPIByteCount;
375 Timer::Metric<HeapAlloc> m_heapAlloc;
388 inline Writer &
operator<<(Writer &dout,
const TimerImpl &timer) {
389 return timer.
dump(dout);
397 TimerImpl::updateRootTimer(root_timer.m_timerImpl);
403 const std::string & name,
406 return TimerImpl::createRootTimer(name, timer_set);
414 TimerImpl::deleteRootTimer(timer.m_timerImpl);
415 timer.m_timerImpl = 0;
420 findTimers(
Timer root_timer,
const std::string &path_tail, std::vector<Timer> &found_timers) {
421 TimerImpl::findTimers(root_timer.m_timerImpl, path_tail, found_timers);
426 TimerImpl::TimerImpl(
427 const std::string & name,
428 TimerMask timer_mask,
429 TimerImpl * parent_timer,
432 m_timerMask(timer_mask),
433 m_parentTimer(parent_timer),
434 m_subtimerLapCount(0.0),
437 m_timerSet(timer_set)
441 TimerImpl::~TimerImpl()
444 for (TimerList::iterator it = m_subtimerList.begin(); it != m_subtimerList.end(); ++it)
445 delete (*it).m_timerImpl;
447 catch (std::exception &) {
453 const Timer::Metric<LapCount> &
454 TimerImpl::getMetric<LapCount>()
const {
460 const Timer::Metric<CPUTime> &
461 TimerImpl::getMetric<CPUTime>()
const {
467 const Timer::Metric<WallTime> &
468 TimerImpl::getMetric<WallTime>()
const {
474 const Timer::Metric<MPICount> &
475 TimerImpl::getMetric<MPICount>()
const {
481 const Timer::Metric<MPIByteCount> &
482 TimerImpl::getMetric<MPIByteCount>()
const {
483 return m_MPIByteCount;
488 const Timer::Metric<HeapAlloc> &
489 TimerImpl::getMetric<HeapAlloc>()
const {
503 m_MPIByteCount.reset();
509 TimerImpl::getSubtimer(
510 const std::string & name)
512 TimerList::iterator it = std::find_if(m_subtimerList.begin(), m_subtimerList.end(), finder(name));
514 if (it == m_subtimerList.end())
515 throw std::runtime_error(
"Timer not found");
522 TimerImpl::addSubtimer(
523 const std::string & name,
524 TimerMask timer_mask,
525 const TimerSet & timer_set)
527 TimerList::iterator it = std::find_if(m_subtimerList.begin(), m_subtimerList.end(), finder(name));
529 if (it == m_subtimerList.end()) {
530 TimerImpl *timer_impl =
new TimerImpl(name, timer_mask,
this, timer_set);
531 m_subtimerList.push_back(Timer(timer_impl));
535 return (*it).m_timerImpl;
542 if (shouldRecord()) {
543 if (m_lapStartCount++ == 0) {
544 m_lapCount.m_lapStart = m_lapCount.m_lapStop;
546 m_cpuTime.m_lapStop = m_cpuTime.m_lapStart = value_now<CPUTime>();
547 m_wallTime.m_lapStop = m_wallTime.m_lapStart = value_now<WallTime>();
548 m_MPICount.m_lapStop = m_MPICount.m_lapStart = value_now<MPICount>();
549 m_MPIByteCount.m_lapStop = m_MPIByteCount.m_lapStart = value_now<MPIByteCount>();
550 m_heapAlloc.m_lapStop = m_heapAlloc.m_lapStart = value_now<HeapAlloc>();
561 if (shouldRecord()) {
562 if (m_lapStartCount > 0) {
563 m_cpuTime.m_lapStop = value_now<CPUTime>();
564 m_wallTime.m_lapStop = value_now<WallTime>();
565 m_MPICount.m_lapStop = value_now<MPICount>();
566 m_MPIByteCount.m_lapStop = value_now<MPIByteCount>();
567 m_heapAlloc.m_lapStop = value_now<HeapAlloc>();
578 if (shouldRecord()) {
579 if (--m_lapStartCount <= 0) {
581 m_lapCount.m_lapStop++;
583 m_cpuTime.m_lapStop = value_now<CPUTime>();
584 m_wallTime.m_lapStop = value_now<WallTime>();
585 m_MPICount.m_lapStop = value_now<MPICount>();
586 m_MPIByteCount.m_lapStop = value_now<MPIByteCount>();
587 m_heapAlloc.m_lapStop = value_now<HeapAlloc>();
593 m_MPIByteCount.addLap();
594 m_heapAlloc.addLap();
603 TimerImpl::accumulateSubtimerLapCounts()
const 605 m_subtimerLapCount = m_lapCount.getAccumulatedLap(
false);
607 for (TimerList::const_iterator it = m_subtimerList.begin(); it != m_subtimerList.end(); ++it)
608 (*it).m_timerImpl->accumulateSubtimerLapCounts();
610 for (TimerList::const_iterator it = m_subtimerList.begin(); it != m_subtimerList.end(); ++it)
611 m_subtimerLapCount += (*it).m_timerImpl->m_subtimerLapCount;
613 return m_subtimerLapCount;
618 TimerImpl::checkpoint()
const 620 m_lapCount.checkpoint();
621 m_cpuTime.checkpoint();
622 m_wallTime.checkpoint();
623 m_MPICount.checkpoint();
624 m_MPIByteCount.checkpoint();
625 m_heapAlloc.checkpoint();
627 for (TimerList::const_iterator it = m_subtimerList.begin(); it != m_subtimerList.end(); ++it)
628 (*it).m_timerImpl->checkpoint();
633 TimerImpl::updateRootTimer(TimerImpl *root_timer)
635 root_timer->m_lapCount.m_lapStop = value_now<LapCount>();
636 root_timer->m_cpuTime.m_lapStop = value_now<CPUTime>();
637 root_timer->m_wallTime.m_lapStop = value_now<WallTime>();
638 root_timer->m_MPICount.m_lapStop = value_now<MPICount>();
639 root_timer->m_MPIByteCount.m_lapStop = value_now<MPIByteCount>();
640 root_timer->m_heapAlloc.m_lapStop = value_now<HeapAlloc>();
642 root_timer->m_lapCount.m_accumulatedLap = root_timer->m_lapCount.m_lapStop - root_timer->m_lapCount.m_lapStart;
643 root_timer->m_cpuTime.m_accumulatedLap = root_timer->m_cpuTime.m_lapStop - root_timer->m_cpuTime.m_lapStart;
644 root_timer->m_wallTime.m_accumulatedLap = root_timer->m_wallTime.m_lapStop - root_timer->m_wallTime.m_lapStart;
645 root_timer->m_MPICount.m_accumulatedLap = root_timer->m_MPICount.m_lapStop - root_timer->m_MPICount.m_lapStart;
646 root_timer->m_MPIByteCount.m_accumulatedLap = root_timer->m_MPIByteCount.m_lapStop - root_timer->m_MPIByteCount.m_lapStart;
647 root_timer->m_heapAlloc.m_accumulatedLap = root_timer->m_heapAlloc.m_lapStop - root_timer->m_heapAlloc.m_lapStart;
653 TimerImpl::createRootTimer(
654 const std::string & name,
655 const TimerSet & timer_set)
657 TimerImpl *timer_impl =
new TimerImpl(name, 0, 0, timer_set);
658 return Timer(timer_impl);
663 TimerImpl::deleteRootTimer(
664 TimerImpl * root_timer)
671 TimerImpl::findTimer(
673 std::vector<std::string> & path_tail_vector,
674 std::vector<Timer> & found_timers)
676 if (timer->begin() == timer->end()) {
680 for (TimerList::const_iterator it = timer->begin(); it != timer->end(); ++it)
681 findTimer((*it).m_timerImpl, path_tail_vector, found_timers);
686 TimerImpl::findTimers(
687 TimerImpl * root_timer,
688 const std::string & path_tail,
689 std::vector<Timer> & found_timers)
691 std::vector<std::string> path_tail_vector;
693 findTimer(root_timer, split(path_tail,
'.', path_tail_vector), found_timers);
704 if (
dout.shouldPrint()) {
707 dout <<
"m_timerMask, " << m_timerMask <<
dendl;
709 dout <<
"m_subtimerLapCount, " << m_subtimerLapCount <<
dendl;
710 dout <<
"m_lapStartCount, " << m_lapStartCount <<
dendl;
712 dout <<
"m_lapCount, " << m_lapCount <<
dendl;
713 dout <<
"m_cpuTime, " << m_cpuTime <<
dendl;
714 dout <<
"m_wallTime, " << m_wallTime <<
dendl;
715 dout <<
"m_MPICount, " << m_MPICount <<
dendl;
716 dout <<
"m_MPIByteCount, " << m_MPIByteCount <<
dendl;
717 dout <<
"m_heapAlloc, " << m_heapAlloc <<
dendl;
719 dout <<
"m_subtimerList, " << m_subtimerList <<
dendl;
728 : m_timerImpl(TimerImpl::reg(name, parent.getTimerMask(), parent.m_timerImpl, parent.getTimerSet()))
732 : m_timerImpl(TimerImpl::reg(name, timer_mask, parent.m_timerImpl, parent.getTimerSet()))
736 : m_timerImpl(TimerImpl::reg(name, parent.getTimerMask(), parent.m_timerImpl, timer_set))
740 : m_timerImpl(TimerImpl::reg(name, timer_mask, parent.m_timerImpl, timer_set))
746 return m_timerImpl->m_name;
751 return m_timerImpl->getTimerMask();
756 return m_timerImpl->getTimerSet();
761 return m_timerImpl->getSubtimerLapCount();
765 Timer::getTimerList()
const {
766 return m_timerImpl->getTimerList();
770 const Timer::Metric<T> &
772 return m_timerImpl->getMetric<T>();
784 Timer::shouldRecord()
const 786 return m_timerImpl->shouldRecord();
792 return m_timerImpl->begin();
795 TimerList::const_iterator
798 return m_timerImpl->begin();
804 return m_timerImpl->end();
807 TimerList::const_iterator
810 return m_timerImpl->end();
815 return m_timerImpl->accumulateSubtimerLapCounts();
820 m_timerImpl->start();
838 m_timerImpl->checkpoint();
843 return m_timerImpl->dump(dout);
851 if (dout.shouldPrint()) {
852 dout <<
"Timer::Metric<T>" << push <<
dendl;
853 dout <<
"m_lapStart, " << m_lapStart <<
dendl;
854 dout <<
"m_lapStop, " << m_lapStop <<
dendl;
855 dout <<
"m_accumulatedLap, " << m_accumulatedLap <<
dendl;
856 dout <<
"m_checkpoint, " << m_checkpoint <<
dendl;
876 m_started(start_timer)
878 if (m_timer.m_timerImpl->shouldRecord()) {
880 if (mpi_comm != MPI_COMM_NULL)
881 MPI_Barrier(mpi_comm);
906 MPI_Barrier(m_mpiComm);
926 #ifdef SIERRA_INCLUDE_LIBPAPI 927 class PAPIRuntimeError :
public std::runtime_error
930 PAPIRuntimeError(
const char *message,
int status)
931 :
std::runtime_error(message),
935 virtual const char *what()
const throw() {
936 static std::string message;
937 static char papi_message[PAPI_MAX_STR_LEN];
939 PAPI_perror(m_status, papi_message,
sizeof(papi_message));
941 message = std::runtime_error::what();
942 message += papi_message;
944 return message.c_str();
959 s_timerNameMaxWidth = DEFAULT_TIMER_NAME_MAX_WIDTH;
967 SierraRootTimer::SierraRootTimer()
968 : m_sierraTimer(
stk_classic::diag::createRootTimer(
"Sierra", sierraTimerSet()))
972 SierraRootTimer::~SierraRootTimer()
974 stk_classic::diag::deleteRootTimer(m_sierraTimer);
980 return m_sierraTimer;
987 static TimerSet s_sierraTimerSet(TIMER_PROCEDURE | TIMER_REGION);
989 return s_sierraTimerSet;
993 boost::shared_ptr<SierraRootTimer> sierraRootTimer()
995 static boost::shared_ptr<SierraRootTimer> s_sierraRootTimer(
new SierraRootTimer());
996 if ( ! s_sierraRootTimer ) {
997 s_sierraRootTimer.reset(
new SierraRootTimer());
999 return s_sierraRootTimer;
1006 return sierraRootTimer()->sierraTimer();
1010 sierraTimerDestroy()
1012 sierraRootTimer().reset();
1017 setEnabledTimerMask(
1018 TimerMask timer_mask)
1025 getEnabledTimerMask()
1032 setTimeFormat(
int time_format) {
1033 stk_classic::diag::setTimerTimeFormat(time_format);
1038 setTimeFormatMillis()
1040 if ((getTimeFormat() & stk_classic::TIMEFORMAT_STYLE_MASK ) == stk_classic::TIMEFORMAT_HMS) {
1041 if (getSierraWallTime() > 3600.0)
1042 setTimeFormat(getTimeFormat() & ~stk_classic::TIMEFORMAT_MILLIS);
1044 setTimeFormat(getTimeFormat() | stk_classic::TIMEFORMAT_MILLIS);
1046 else if ((getTimeFormat() & stk_classic::TIMEFORMAT_STYLE_MASK ) == stk_classic::TIMEFORMAT_SECONDS) {
1047 if (getSierraWallTime() > 1000.0)
1048 setTimeFormat(getTimeFormat() & ~stk_classic::TIMEFORMAT_MILLIS);
1050 setTimeFormat(getTimeFormat() | stk_classic::TIMEFORMAT_MILLIS);
1058 return stk_classic::diag::getTimerTimeFormat();
1063 setTimerNameMaxWidth(
1066 s_timerNameMaxWidth = width;
1071 getTimerNameMaxWidth()
1073 return s_timerNameMaxWidth;
1077 stk_classic::diag::MetricTraits<stk_classic::diag::CPUTime>::Type
1084 stk_classic::diag::MetricTraits<stk_classic::diag::WallTime>::Type
1091 stk_classic::diag::MetricTraits<stk_classic::diag::CPUTime>::Type
1092 getCPULapTime(Timer timer) {
1096 stk_classic::diag::MetricTraits<stk_classic::diag::CPUTime>::Type
1097 getCPUAccumulatedLapTime(Timer timer) {
1105 static TimerParser parser;
1111 TimerParser::TimerParser()
1114 mask(
"cpu", 0,
"Display CPU times");
1115 mask(
"wall", 0,
"Display wall times");
1117 mask(
"hms", 0,
"Display times in HH:MM:SS format");
1118 mask(
"seconds", 0,
"Display times in seconds");
1124 mask(
"all", TIMER_ALL,
"Enable all metrics");
1125 mask(
"none", TIMER_NONE,
"Disable all timers");
1127 mask(
"domain", TIMER_DOMAIN,
"Enable metrics on the domain");
1128 mask(
"region", TIMER_REGION,
"Enable metrics on regions");
1129 mask(
"procedure", TIMER_PROCEDURE,
"Enable metrics on procedures");
1130 mask(
"mechanics", TIMER_MECHANICS,
"Enable metrics on mechanics");
1131 mask(
"algorithm", TIMER_ALGORITHM,
"Enable metrics on algorithms");
1132 mask(
"solver", TIMER_SOLVER,
"Enable metrics on solvers");
1133 mask(
"contact", TIMER_CONTACT,
"Enable metrics on contact");
1134 mask(
"material", TIMER_MATERIAL,
"Enable metrics on materials");
1135 mask(
"search", TIMER_SEARCH,
"Enable metrics on searches");
1136 mask(
"transfer", TIMER_TRANSFER,
"Enable metrics on user functions");
1137 mask(
"adaptivity", TIMER_ADAPTIVITY,
"Enable metrics on adaptivity");
1138 mask(
"recovery", TIMER_RECOVERY,
"Enable metrics on encore recovery");
1139 mask(
"profile1", TIMER_PROFILE_1,
"Enable app defined profiling metrics");
1140 mask(
"profile2", TIMER_PROFILE_2,
"Enable app defined profiling metrics");
1141 mask(
"profile3", TIMER_PROFILE_3,
"Enable app defined profiling metrics");
1142 mask(
"profile4", TIMER_PROFILE_4,
"Enable app defined profiling metrics");
1143 mask(
"app1", TIMER_APP_1,
"Enable app defined metrics");
1144 mask(
"app2", TIMER_APP_2,
"Enable app defined metrics");
1145 mask(
"app3", TIMER_APP_3,
"Enable app defined metrics");
1146 mask(
"app4", TIMER_APP_4,
"Enable app defined metrics");
1152 const char * mask)
const 1154 m_metricsSetMask = 0;
1165 if (m_metricsSetMask != 0)
1166 stk_classic::diag::setEnabledTimerMetricsMask(m_metricsMask);
1174 const std::string & name,
1175 const std::string & arg)
const 1177 if (name ==
"cpu") {
1178 m_metricsMask |= stk_classic::diag::METRICS_CPU_TIME;
1179 m_metricsSetMask |= stk_classic::diag::METRICS_CPU_TIME;
1181 else if (name ==
"wall") {
1182 m_metricsMask |= stk_classic::diag::METRICS_WALL_TIME;
1183 m_metricsSetMask |= stk_classic::diag::METRICS_WALL_TIME;
1185 else if (name ==
"heap") {
1186 m_metricsMask |= stk_classic::diag::METRICS_HEAP_ALLOC;
1187 m_metricsSetMask |= stk_classic::diag::METRICS_HEAP_ALLOC;
1189 else if (name ==
"none") {
1191 m_metricsSetMask = stk_classic::diag::METRICS_WALL_TIME | stk_classic::diag::METRICS_CPU_TIME;
1194 else if (name ==
"hms") {
1195 Diag::setTimeFormat(stk_classic::TIMEFORMAT_HMS);
1197 else if (name ==
"seconds") {
1198 Diag::setTimeFormat(stk_classic::TIMEFORMAT_SECONDS);
std::ostream & dout()
Diagnostic output stream.
TimerMask getEnabledTimerMask() const
Timer(const std::string &name, const Timer parent)
virtual void parseArg(const std::string &name, const std::string &arg) const
void setEnabledTimerMask(TimerMask timer_mask)
double getSubtimerLapCount() const
bool shouldRecord(TimerMask timer_mask) const
void mask(const std::string &name, const Mask l_mask, const std::string &description)
OptionMask m_optionMask
Most recently parsed mask.
std::ostream & operator<<(std::ostream &s, const Bucket &k)
Print the part names for which this bucket is a subset.
virtual Mask parse(const char *mask) const
Writer & dendl(Writer &dout)
Writer function dendl calls the Writer::dendl manipulator.
Writer & dump(Writer &dout, const std::vector< T > &t)
Template dump prints the object contained within a std::vector object to the diagnostic writer...
TimerMask getTimerMask() const
Writer & dump(Writer &dout) const
Mask parse(const char *mask_string) const
Member function parse parses the mask string and generates the corresponding bit mask.
Class TimerSet implements a set of timer classifications. A time classification consists of a bit mas...
TimeBlockSynchronized(Timer &timer, ParallelMachine mpi_comm, bool start_timer=true)
const TimerSet & getTimerSet() const
Class Writer implements a runtime selectable diagnostic output writer to aid in the development and d...
bool equal_case(const char *lhs, const char *rhs)
Case-insensitive equality compare.
virtual void parseArg(const std::string &name, const std::string &arg) const
void reset(MPI_Comm new_comm)
Function reset determines new parallel_size and parallel_rank. Flushes, closes, and reopens log files...
OptionMask Mask
Mask for this option.
double accumulateSubtimerLapCounts() const
const std::string & getName() const
const Metric< T > & getMetric() const
Writer & dump(Writer &dout) const
Part * find(const PartVector &parts, const std::string &name)
Find a part by name in a collection of parts.
Class Timer implements a diagnostic timer and timer container for the collection and display of execu...