Sierra Toolkit Version of the Day
Timer.cpp
00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010 - 2011 Sandia Corporation.              */
00003 /*  Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive   */
00004 /*  license for use of this work by or on behalf of the U.S. Government.  */
00005 /*  Export of this program may require a license from the                 */
00006 /*  United States Government.                                             */
00007 /*------------------------------------------------------------------------*/
00008 
00009 #include <math.h>
00010 #include <sstream>
00011 #include <iomanip>
00012 #include <algorithm>
00013 #include <functional>
00014 #include <stdexcept>
00015 #include <limits>
00016 
00017 #include <sys/times.h>
00018 #include <sys/time.h>
00019 #include <sys/resource.h>
00020 
00021 #ifdef __JVN
00022 #include <sys/wait.h>
00023 #endif
00024 
00025 #include <stk_util/util/FeatureTest.hpp>
00026 
00027 #ifdef SIERRA_INCLUDE_LIBPAPI
00028 #  include <papi.h>
00029 #  if defined(PAPI_VERSION) && (PAPI_VERSION_MAJOR(PAPI_VERSION) != 3)
00030 #    error "Compiling against an unknown PAPI version"
00031 #  endif
00032 #endif
00033 
00034 // #include <fenv.h>
00035 #include <math.h>
00036 #include <sstream>
00037 #include <iomanip>
00038 #include <algorithm>
00039 #include <functional>
00040 #include <stdexcept>
00041 #include <limits>
00042 
00043 #include <stk_util/diag/Writer.hpp>
00044 #include <stk_util/diag/Timer.hpp>
00045 #include <stk_util/diag/PrintTable.hpp>
00046 #include <stk_util/diag/Env.hpp>
00047 #include <stk_util/parallel/MPI.hpp>
00048 
00049 #include <stk_util/util/string_case_compare.hpp>
00050 
00051 #include <stk_util/diag/WriterExt.hpp>
00052 
00053 namespace stk {
00054 namespace diag {
00055 
00056 namespace {
00057 
00058 MetricsMask s_enabledMetricsMask = METRICS_LAP_COUNT | METRICS_CPU_TIME | METRICS_WALL_TIME;        
00059 
00060 template <class T>
00061 typename MetricTraits<T>::Type
00062 value_now() {
00063   if (MetricTraits<T>::METRIC & getEnabledTimerMetricsMask())
00064     return MetricTraits<T>::value_now();
00065   else
00066     return 0;
00067 }
00068 
00069 std::vector<std::string> &
00070 split(
00071   const std::string &           path,
00072   char                          separator,
00073   std::vector<std::string> &    path_vector)
00074 {
00075   for (std::string::const_iterator it = path.begin(); ; ) {
00076     std::string::const_iterator it2 = std::find(it, path.end(), separator);
00077     path_vector.push_back(std::string(it, it2));
00078     if (it2 == path.end())
00079       break;
00080     it = it2 + 1;
00081   }
00082   
00083   return path_vector;
00084 }
00085 
00086 } // namespace <empty>
00087 
00088 
00089 MetricsMask getEnabledTimerMetricsMask()
00090 {
00091   return s_enabledMetricsMask;
00092 }
00093 
00094 void
00095 setEnabledTimerMetricsMask(
00096   MetricsMask   timer_mask)
00097 {
00098   s_enabledMetricsMask = timer_mask | METRICS_LAP_COUNT;
00099 }
00100 
00101 
00123 class TimerImpl
00124 {
00125   friend class Timer;
00126   
00127 public:
00128   static void updateRootTimer(TimerImpl *root_timer);
00129   
00130   static Timer createRootTimer(const std::string &name, const TimerSet &timer_set);
00131     
00132   static void deleteRootTimer(TimerImpl *root_timer);
00133 
00134   static std::vector<Timer> &findTimers(TimerImpl *root_timer, const std::string &path_tail, std::vector<Timer> &found_timers);
00135 
00136   static void findTimer(TimerImpl *timer, std::vector<std::string> &path_tail_vector, std::vector<Timer> &found_timers);
00137   
00138 private:
00148   static TimerImpl *reg(const std::string &name, TimerMask timer_mask, TimerImpl *parent_timer, const TimerSet &timer_set) {
00149     return parent_timer->addSubtimer(name, timer_mask, timer_set);
00150   }
00151 
00159   TimerImpl(const std::string &name, TimerMask timer_mask, TimerImpl *parent_timer, const TimerSet &timer_set);
00160 
00165   ~TimerImpl();
00166   
00167   TimerImpl(const TimerImpl &TimerImpl);
00168   TimerImpl &operator=(const TimerImpl &TimerImpl);
00169   
00176 #ifdef __INTEL_COMPILER
00177 #pragma warning(push)
00178 #pragma warning(disable: 444)
00179 #endif
00180   class finder : private std::unary_function<Timer, bool>
00181   {
00182   public:
00183     explicit finder(const std::string &name)
00184       : m_name(name)
00185     {}
00186     
00187     bool operator()(Timer timer) const {
00188       return equal_case(timer.getName(), m_name);
00189     }
00190 
00191   private:
00192     std::string    m_name;
00193   };
00194 #ifdef __INTEL_COMPILER
00195 #pragma warning(pop)
00196 #endif
00197 
00198 public:
00205   const std::string &getName() const {
00206     return m_name;
00207   }
00208 
00214   TimerMask getTimerMask() const {
00215     return m_timerMask;
00216   }
00217 
00223   const TimerSet &getTimerSet() const {
00224     return m_timerSet;
00225   }
00226 
00235   bool shouldRecord() const {
00236     return m_timerSet.shouldRecord(m_timerMask) && s_enabledMetricsMask;
00237   }
00238 
00245   double getSubtimerLapCount() const {
00246     return m_subtimerLapCount;
00247   }
00248 
00249   void setSubtimerLapCount(double value) {
00250     m_subtimerLapCount = value;
00251   }
00252 
00260   template <class T>
00261   const Timer::Metric<T> &getMetric() const;
00262 
00270   const TimerList &getTimerList() const {
00271     return m_subtimerList;
00272   }
00273  
00274   TimerList::iterator begin() {
00275     return m_subtimerList.begin();
00276   }
00277     
00278   TimerList::const_iterator begin() const {
00279     return m_subtimerList.begin();
00280   }
00281     
00282   TimerList::iterator end() {
00283     return m_subtimerList.end();
00284   }
00285     
00286   TimerList::const_iterator end() const {
00287     return m_subtimerList.end();
00288   }
00289     
00294   void reset();
00295 
00300   void checkpoint() const;
00301 
00307   TimerImpl &start();
00308 
00314   TimerImpl &lap();
00315 
00322   TimerImpl &stop();
00323 
00331   double accumulateSubtimerLapCounts() const;
00332 
00333   Timer getSubtimer(const std::string &name);
00334 
00335 public:
00344   Writer &dump(Writer &dout) const;
00345 
00346 private:
00358   TimerImpl *addSubtimer(const std::string &name, TimerMask timer_mask, const TimerSet &timer_set);
00359 
00360 private:
00361   std::string           m_name;                 
00362   TimerMask             m_timerMask;            
00363   TimerImpl *           m_parentTimer;          
00364   mutable double        m_subtimerLapCount;     
00365   unsigned              m_lapStartCount;        
00366 
00367   TimerList             m_subtimerList;         
00368 
00369   const TimerSet &              m_timerSet;     
00370   Timer::Metric<LapCount>       m_lapCount;     
00371   Timer::Metric<CPUTime>        m_cpuTime;      
00372   Timer::Metric<WallTime>       m_wallTime;     
00373   Timer::Metric<MPICount>       m_MPICount;     
00374   Timer::Metric<MPIByteCount>   m_MPIByteCount; 
00375   Timer::Metric<HeapAlloc>      m_heapAlloc;    
00376 };
00377 
00378 
00388 inline Writer &operator<<(Writer &dout, const TimerImpl &timer) {
00389   return timer.dump(dout);
00390 }
00391 
00392 
00393 void
00394 updateRootTimer(
00395   Timer                 root_timer)
00396 {
00397   TimerImpl::updateRootTimer(root_timer.m_timerImpl);
00398 }
00399 
00400 
00401 Timer
00402 createRootTimer(
00403   const std::string &   name,
00404   const TimerSet &      timer_set)
00405 {
00406   return TimerImpl::createRootTimer(name, timer_set);
00407 }
00408 
00409 
00410 void
00411 deleteRootTimer(
00412   Timer                 timer)
00413 {
00414   TimerImpl::deleteRootTimer(timer.m_timerImpl);
00415   timer.m_timerImpl = 0;
00416 }
00417 
00418 
00419 std::vector<Timer> &
00420 findTimers(Timer root_timer, const std::string &path_tail, std::vector<Timer> &found_timers) {
00421   TimerImpl::findTimers(root_timer.m_timerImpl, path_tail, found_timers);
00422   return found_timers;
00423 }
00424 
00425 
00426 TimerImpl::TimerImpl(
00427   const std::string &  name,
00428   TimerMask    timer_mask,
00429   TimerImpl *    parent_timer,
00430   const TimerSet &      timer_set)
00431   : m_name(name),
00432     m_timerMask(timer_mask),
00433     m_parentTimer(parent_timer),
00434     m_subtimerLapCount(0.0),
00435     m_lapStartCount(0),
00436     m_subtimerList(),
00437     m_timerSet(timer_set)
00438 {}
00439 
00440 
00441 TimerImpl::~TimerImpl()
00442 {
00443   try {  
00444     for (TimerList::iterator it = m_subtimerList.begin(); it != m_subtimerList.end(); ++it)
00445       delete (*it).m_timerImpl;
00446   }
00447   catch (std::exception &) {
00448   }  
00449 }
00450 
00451 
00452 template<>
00453 const Timer::Metric<LapCount> &
00454 TimerImpl::getMetric<LapCount>() const {
00455   return m_lapCount;
00456 }
00457 
00458 
00459 template<>
00460 const Timer::Metric<CPUTime> &
00461 TimerImpl::getMetric<CPUTime>() const {
00462   return m_cpuTime;
00463 }
00464 
00465 
00466 template<>
00467 const Timer::Metric<WallTime> &
00468 TimerImpl::getMetric<WallTime>() const {
00469   return m_wallTime;
00470 }
00471 
00472 
00473 template<>
00474 const Timer::Metric<MPICount> &
00475 TimerImpl::getMetric<MPICount>() const {
00476   return m_MPICount;
00477 }
00478 
00479 
00480 template<>
00481 const Timer::Metric<MPIByteCount> &
00482 TimerImpl::getMetric<MPIByteCount>() const {
00483   return m_MPIByteCount;
00484 }
00485 
00486 
00487 template<>
00488 const Timer::Metric<HeapAlloc> &
00489 TimerImpl::getMetric<HeapAlloc>() const {
00490   return m_heapAlloc;
00491 }
00492 
00493 
00494 void
00495 TimerImpl::reset()
00496 {
00497   m_lapStartCount = 0;
00498 
00499   m_lapCount.reset();
00500   m_cpuTime.reset();
00501   m_wallTime.reset();
00502   m_MPICount.reset();
00503   m_MPIByteCount.reset();
00504   m_heapAlloc.reset();
00505 }
00506 
00507 
00508 Timer
00509 TimerImpl::getSubtimer(
00510   const std::string &  name)
00511 {
00512   TimerList::iterator it = std::find_if(m_subtimerList.begin(), m_subtimerList.end(), finder(name));
00513 
00514   if (it == m_subtimerList.end())
00515     throw std::runtime_error("Timer not found");
00516   else
00517     return *it;
00518 }
00519 
00520 
00521 TimerImpl *
00522 TimerImpl::addSubtimer(
00523   const std::string &  name,
00524   TimerMask          timer_mask,
00525   const TimerSet &      timer_set)
00526 {
00527   TimerList::iterator it = std::find_if(m_subtimerList.begin(), m_subtimerList.end(), finder(name));
00528 
00529   if (it == m_subtimerList.end()) {
00530     TimerImpl *timer_impl = new TimerImpl(name, timer_mask, this, timer_set);
00531     m_subtimerList.push_back(Timer(timer_impl));
00532     return timer_impl;
00533   }
00534   else
00535     return (*it).m_timerImpl;
00536 }
00537 
00538 
00539 TimerImpl &
00540 TimerImpl::start()
00541 {
00542   if (shouldRecord()) {
00543     if (m_lapStartCount++ == 0) {
00544       m_lapCount.m_lapStart = m_lapCount.m_lapStop;
00545 
00546       m_cpuTime.m_lapStop = m_cpuTime.m_lapStart = value_now<CPUTime>();
00547       m_wallTime.m_lapStop = m_wallTime.m_lapStart = value_now<WallTime>();
00548       m_MPICount.m_lapStop = m_MPICount.m_lapStart = value_now<MPICount>();
00549       m_MPIByteCount.m_lapStop = m_MPIByteCount.m_lapStart = value_now<MPIByteCount>();
00550       m_heapAlloc.m_lapStop = m_heapAlloc.m_lapStart = value_now<HeapAlloc>();
00551     }
00552   }
00553 
00554   return *this;
00555 }
00556 
00557 
00558 TimerImpl &
00559 TimerImpl::lap()
00560 {
00561   if (shouldRecord()) {
00562     if (m_lapStartCount > 0) {
00563       m_cpuTime.m_lapStop = value_now<CPUTime>();
00564       m_wallTime.m_lapStop = value_now<WallTime>();
00565       m_MPICount.m_lapStop = value_now<MPICount>();
00566       m_MPIByteCount.m_lapStop = value_now<MPIByteCount>();
00567       m_heapAlloc.m_lapStop = value_now<HeapAlloc>();
00568     }
00569   }
00570 
00571   return *this;
00572 }
00573 
00574 
00575 TimerImpl &
00576 TimerImpl::stop()
00577 {
00578   if (shouldRecord()) {
00579     if (--m_lapStartCount <= 0) {
00580       m_lapStartCount = 0;
00581       m_lapCount.m_lapStop++;
00582 
00583       m_cpuTime.m_lapStop = value_now<CPUTime>();
00584       m_wallTime.m_lapStop = value_now<WallTime>();
00585       m_MPICount.m_lapStop = value_now<MPICount>();
00586       m_MPIByteCount.m_lapStop = value_now<MPIByteCount>();
00587       m_heapAlloc.m_lapStop = value_now<HeapAlloc>();
00588 
00589       m_lapCount.addLap();
00590       m_cpuTime.addLap();
00591       m_wallTime.addLap();
00592       m_MPICount.addLap();
00593       m_MPIByteCount.addLap();
00594       m_heapAlloc.addLap();
00595     }
00596   }
00597 
00598   return *this;
00599 }
00600 
00601 
00602 double
00603 TimerImpl::accumulateSubtimerLapCounts() const
00604 {
00605   m_subtimerLapCount = m_lapCount.getAccumulatedLap(false);
00606 
00607   for (TimerList::const_iterator it = m_subtimerList.begin(); it != m_subtimerList.end(); ++it)
00608     (*it).m_timerImpl->accumulateSubtimerLapCounts();
00609 
00610   for (TimerList::const_iterator it = m_subtimerList.begin(); it != m_subtimerList.end(); ++it)
00611     m_subtimerLapCount += (*it).m_timerImpl->m_subtimerLapCount;
00612 
00613   return m_subtimerLapCount;
00614 }
00615 
00616 
00617 void
00618 TimerImpl::checkpoint() const
00619 {
00620   m_lapCount.checkpoint();
00621   m_cpuTime.checkpoint();
00622   m_wallTime.checkpoint();
00623   m_MPICount.checkpoint();
00624   m_MPIByteCount.checkpoint();
00625   m_heapAlloc.checkpoint();
00626 
00627   for (TimerList::const_iterator it = m_subtimerList.begin(); it != m_subtimerList.end(); ++it)
00628     (*it).m_timerImpl->checkpoint();
00629 }
00630 
00631 
00632 void
00633 TimerImpl::updateRootTimer(TimerImpl *root_timer)
00634 {
00635   root_timer->m_lapCount.m_lapStop = value_now<LapCount>();
00636   root_timer->m_cpuTime.m_lapStop = value_now<CPUTime>();
00637   root_timer->m_wallTime.m_lapStop = value_now<WallTime>();
00638   root_timer->m_MPICount.m_lapStop = value_now<MPICount>();
00639   root_timer->m_MPIByteCount.m_lapStop = value_now<MPIByteCount>();
00640   root_timer->m_heapAlloc.m_lapStop = value_now<HeapAlloc>();
00641 
00642   root_timer->m_lapCount.m_accumulatedLap = root_timer->m_lapCount.m_lapStop - root_timer->m_lapCount.m_lapStart;
00643   root_timer->m_cpuTime.m_accumulatedLap = root_timer->m_cpuTime.m_lapStop - root_timer->m_cpuTime.m_lapStart;
00644   root_timer->m_wallTime.m_accumulatedLap = root_timer->m_wallTime.m_lapStop - root_timer->m_wallTime.m_lapStart;
00645   root_timer->m_MPICount.m_accumulatedLap = root_timer->m_MPICount.m_lapStop - root_timer->m_MPICount.m_lapStart;
00646   root_timer->m_MPIByteCount.m_accumulatedLap = root_timer->m_MPIByteCount.m_lapStop - root_timer->m_MPIByteCount.m_lapStart;
00647   root_timer->m_heapAlloc.m_accumulatedLap = root_timer->m_heapAlloc.m_lapStop - root_timer->m_heapAlloc.m_lapStart;
00648 }
00649 
00650 
00651 
00652 Timer
00653 TimerImpl::createRootTimer(
00654   const std::string &   name,
00655   const TimerSet &      timer_set)
00656 {
00657   TimerImpl *timer_impl = new TimerImpl(name, 0, 0, timer_set);
00658   return Timer(timer_impl);
00659 }
00660 
00661 
00662 void
00663 TimerImpl::deleteRootTimer(
00664   TimerImpl *           root_timer)
00665 {
00666   delete root_timer;
00667 }
00668 
00669 
00670 void
00671 TimerImpl::findTimer(
00672   TimerImpl *                   timer,
00673   std::vector<std::string> &    path_tail_vector,
00674   std::vector<Timer> &          found_timers)
00675 {
00676   if (timer->begin() == timer->end()) { // at leaf
00677     
00678   }
00679   else
00680     for (TimerList::const_iterator it = timer->begin(); it != timer->end(); ++it)
00681       findTimer((*it).m_timerImpl, path_tail_vector, found_timers);
00682 }
00683 
00684 
00685 std::vector<Timer> &
00686 TimerImpl::findTimers(
00687   TimerImpl *                   root_timer,
00688   const std::string &           path_tail,
00689   std::vector<Timer> &          found_timers)
00690 {
00691   std::vector<std::string> path_tail_vector;
00692   
00693   findTimer(root_timer, split(path_tail, '.', path_tail_vector), found_timers);
00694 
00695   return found_timers;
00696 }
00697 
00698 
00699 
00700 Writer &
00701 TimerImpl::dump(
00702   Writer &    dout) const
00703 {
00704   if (dout.shouldPrint()) {
00705     dout << "TimerImpl" << push << dendl;
00706     dout << "m_name, " << m_name << dendl;
00707     dout << "m_timerMask, " << m_timerMask << dendl;
00708 //    dout << "m_parentTimer, " << c_ptr_name(m_parentTimer) << dendl;
00709     dout << "m_subtimerLapCount, " << m_subtimerLapCount << dendl;
00710     dout << "m_lapStartCount, " << m_lapStartCount << dendl;
00711 
00712     dout << "m_lapCount, " << m_lapCount << dendl;
00713     dout << "m_cpuTime, " << m_cpuTime << dendl;
00714     dout << "m_wallTime, " << m_wallTime << dendl;
00715     dout << "m_MPICount, " << m_MPICount << dendl;
00716     dout << "m_MPIByteCount, " << m_MPIByteCount << dendl;
00717     dout << "m_heapAlloc, " << m_heapAlloc << dendl;
00718 
00719     dout << "m_subtimerList, " << m_subtimerList << dendl;
00720     dout << pop;
00721   }
00722 
00723   return dout;
00724 }
00725 
00726 
00727 Timer::Timer(const std::string &name, const Timer parent)
00728   : m_timerImpl(TimerImpl::reg(name, parent.getTimerMask(), parent.m_timerImpl, parent.getTimerSet()))
00729 {}
00730 
00731 Timer::Timer(const std::string &name, TimerMask timer_mask, const Timer parent)
00732   : m_timerImpl(TimerImpl::reg(name, timer_mask, parent.m_timerImpl, parent.getTimerSet()))
00733 {}
00734 
00735 Timer::Timer(const std::string &name, const Timer parent, const TimerSet &timer_set)
00736   : m_timerImpl(TimerImpl::reg(name, parent.getTimerMask(), parent.m_timerImpl, timer_set))
00737 {}
00738 
00739 Timer::Timer(const std::string &name, TimerMask timer_mask, const Timer parent, const TimerSet &timer_set)
00740   : m_timerImpl(TimerImpl::reg(name, timer_mask, parent.m_timerImpl, timer_set))
00741 {}
00742 
00743 
00744 const std::string &
00745 Timer::getName() const {
00746   return m_timerImpl->m_name;
00747 }
00748 
00749 TimerMask
00750 Timer::getTimerMask() const {
00751   return m_timerImpl->getTimerMask();
00752 }
00753 
00754 const TimerSet &
00755 Timer::getTimerSet() const {
00756   return m_timerImpl->getTimerSet();
00757 }
00758 
00759 double
00760 Timer::getSubtimerLapCount() const {
00761   return m_timerImpl->getSubtimerLapCount();
00762 }
00763 
00764 const TimerList &
00765 Timer::getTimerList() const {
00766   return m_timerImpl->getTimerList();
00767 }
00768 
00769 template<class T>
00770 const Timer::Metric<T> &
00771 Timer::getMetric() const {
00772   return m_timerImpl->getMetric<T>();
00773 }
00774 
00775 template const Timer::Metric<LapCount> &Timer::getMetric<LapCount>() const;
00776 template const Timer::Metric<CPUTime> &Timer::getMetric<CPUTime>() const;
00777 template const Timer::Metric<WallTime> &Timer::getMetric<WallTime>() const;
00778 template const Timer::Metric<MPICount> &Timer::getMetric<MPICount>() const;
00779 template const Timer::Metric<MPIByteCount> &Timer::getMetric<MPIByteCount>() const;
00780 template const Timer::Metric<HeapAlloc> &Timer::getMetric<HeapAlloc>() const;
00781 
00782 
00783 bool
00784 Timer::shouldRecord() const
00785 {
00786   return m_timerImpl->shouldRecord();
00787 }
00788 
00789 TimerList::iterator
00790 Timer::begin()
00791 {
00792   return m_timerImpl->begin();
00793 }
00794     
00795 TimerList::const_iterator
00796 Timer::begin() const
00797 {
00798   return m_timerImpl->begin();
00799 }
00800     
00801 TimerList::iterator
00802 Timer::end()
00803 {
00804   return m_timerImpl->end();
00805 }
00806     
00807 TimerList::const_iterator
00808 Timer::end() const
00809 {
00810   return m_timerImpl->end();
00811 }
00812     
00813 double
00814 Timer::accumulateSubtimerLapCounts() const {
00815   return m_timerImpl->accumulateSubtimerLapCounts();
00816 }
00817 
00818 Timer &
00819 Timer::start() {
00820   m_timerImpl->start();
00821   return *this;
00822 }
00823 
00824 Timer &
00825 Timer::lap() {
00826   m_timerImpl->lap();
00827   return *this;
00828 }
00829 
00830 Timer &
00831 Timer::stop() {
00832   m_timerImpl->stop();
00833   return *this;
00834 }
00835 
00836 void
00837 Timer::checkpoint() const {
00838   m_timerImpl->checkpoint();
00839 }
00840 
00841 Writer &
00842 Timer::dump(Writer& dout) const {
00843   return m_timerImpl->dump(dout);
00844 }
00845 
00846 template <class T>
00847 Writer &
00848 Timer::Metric<T>::dump(
00849   Writer &    dout) const
00850 {
00851   if (dout.shouldPrint()) {
00852     dout << "Timer::Metric<T>" << push << dendl;
00853     dout << "m_lapStart, " << m_lapStart << dendl;
00854     dout << "m_lapStop, " << m_lapStop << dendl;
00855     dout << "m_accumulatedLap, " << m_accumulatedLap << dendl;
00856     dout << "m_checkpoint, " << m_checkpoint << dendl;
00857     dout << pop;
00858   }
00859   return dout;
00860 }
00861 
00862 template Writer &Timer::Metric<LapCount>::dump(Writer &) const;
00863 template Writer &Timer::Metric<CPUTime>::dump(Writer &) const;
00864 template Writer &Timer::Metric<WallTime>::dump(Writer &) const;
00865 template Writer &Timer::Metric<MPICount>::dump(Writer &) const;
00866 template Writer &Timer::Metric<MPIByteCount>::dump(Writer &) const;
00867 template Writer &Timer::Metric<HeapAlloc>::dump(Writer &) const;
00868 
00869 
00870 TimeBlockSynchronized::TimeBlockSynchronized(
00871   Timer &    timer,
00872   MPI_Comm    mpi_comm,
00873   bool      start_timer)
00874   : m_timer(timer),
00875     m_mpiComm(mpi_comm),
00876     m_started(start_timer)
00877 {
00878   if (m_timer.m_timerImpl->shouldRecord()) {
00879 #ifdef STK_HAS_MPI
00880     if (mpi_comm != MPI_COMM_NULL)
00881       MPI_Barrier(mpi_comm);
00882 #endif
00883 
00884     if (start_timer)
00885       m_timer.start();
00886   }
00887 }
00888 
00889 
00890 TimeBlockSynchronized::~TimeBlockSynchronized()
00891 {
00892   if (m_started) {
00893     try {
00894       m_timer.stop();
00895     }
00896     catch (...) {
00897     }
00898   }
00899 }
00900 
00901 
00902 void
00903 TimeBlockSynchronized::start()
00904 {
00905   // Place barrier here
00906   MPI_Barrier(m_mpiComm);
00907   m_started = true;
00908   m_timer.start();
00909 }
00910 
00911 
00912 void
00913 TimeBlockSynchronized::stop()
00914 {
00915   m_started = false;
00916   m_timer.stop();
00917   // Does a barrier need to be here?
00918   // MPI_Barrier(Env::parallel_comm());
00919 }
00920 
00921 } // namespace diag
00922 } // namespace stk
00923 
00924 
00925 
00926 #ifdef SIERRA_INCLUDE_LIBPAPI
00927 class PAPIRuntimeError : public std::runtime_error
00928 {
00929 public:
00930   PAPIRuntimeError(const char *message, int status)
00931     : std::runtime_error(message),
00932       m_status(status)
00933   {}
00934 
00935   virtual const char *what() const throw() {
00936     static std::string message;
00937     static char papi_message[PAPI_MAX_STR_LEN];
00938 
00939     PAPI_perror(m_status, papi_message, sizeof(papi_message));
00940 
00941     message = std::runtime_error::what();
00942     message += papi_message;
00943 
00944     return message.c_str();
00945   }
00946 
00947 private:
00948   int m_status;
00949 };
00950 #endif
00951 
00952 
00953 namespace sierra {
00954 namespace Diag {
00955 
00956 namespace {
00957 
00958 size_t
00959 s_timerNameMaxWidth = DEFAULT_TIMER_NAME_MAX_WIDTH;   
00960 
00961 } // namespace
00962 
00963 
00964 // 
00965 // SierraRootTimer member functions:
00966 // 
00967 SierraRootTimer::SierraRootTimer()
00968   : m_sierraTimer(stk::diag::createRootTimer("Sierra", sierraTimerSet()))
00969 { }
00970 
00971 
00972 SierraRootTimer::~SierraRootTimer()
00973 {
00974   stk::diag::deleteRootTimer(m_sierraTimer);
00975 }
00976 
00977 
00978 stk::diag::Timer & SierraRootTimer::sierraTimer()
00979 {
00980   return m_sierraTimer;
00981 }
00982 
00983 
00984 TimerSet &
00985 sierraTimerSet()
00986 {
00987   static TimerSet s_sierraTimerSet(TIMER_PROCEDURE | TIMER_REGION);
00988 
00989   return s_sierraTimerSet;
00990 }
00991 
00992 
00993 boost::shared_ptr<SierraRootTimer> sierraRootTimer()
00994 {
00995   static boost::shared_ptr<SierraRootTimer> s_sierraRootTimer(new SierraRootTimer());
00996   if ( ! s_sierraRootTimer ) {
00997     s_sierraRootTimer.reset(new SierraRootTimer());
00998   }
00999   return s_sierraRootTimer;
01000 }
01001 
01002 
01003 Timer &
01004 sierraTimer()
01005 {
01006   return sierraRootTimer()->sierraTimer();
01007 }
01008 
01009 void
01010 sierraTimerDestroy()
01011 {
01012   sierraRootTimer().reset();
01013 }
01014 
01015 
01016 void
01017 setEnabledTimerMask(
01018   TimerMask     timer_mask)
01019 {
01020   sierraTimerSet().setEnabledTimerMask(timer_mask);
01021 }
01022 
01023 
01024 TimerMask
01025 getEnabledTimerMask()
01026 {
01027   return sierraTimerSet().getEnabledTimerMask();
01028 }
01029 
01030 
01031 void
01032 setTimeFormat(int time_format) {
01033   stk::diag::setTimerTimeFormat(time_format);
01034 }
01035 
01036 
01037 void
01038 setTimeFormatMillis()
01039 {
01040   if ((getTimeFormat() & stk::TIMEFORMAT_STYLE_MASK ) == stk::TIMEFORMAT_HMS) {
01041     if (getSierraWallTime() > 3600.0)
01042       setTimeFormat(getTimeFormat() & ~stk::TIMEFORMAT_MILLIS);
01043     else
01044       setTimeFormat(getTimeFormat() | stk::TIMEFORMAT_MILLIS);
01045   }
01046   else if ((getTimeFormat() & stk::TIMEFORMAT_STYLE_MASK ) == stk::TIMEFORMAT_SECONDS) {
01047     if (getSierraWallTime() > 1000.0)
01048       setTimeFormat(getTimeFormat() & ~stk::TIMEFORMAT_MILLIS);
01049     else
01050       setTimeFormat(getTimeFormat() | stk::TIMEFORMAT_MILLIS);
01051   }
01052 }
01053 
01054 
01055 int
01056 getTimeFormat()
01057 {
01058   return stk::diag::getTimerTimeFormat();
01059 }
01060 
01061 
01062 void
01063 setTimerNameMaxWidth(
01064   size_t        width)
01065 {
01066   s_timerNameMaxWidth = width;
01067 }
01068 
01069 
01070 size_t
01071 getTimerNameMaxWidth()
01072 {
01073   return s_timerNameMaxWidth;
01074 }
01075 
01076 
01077 stk::diag::MetricTraits<stk::diag::CPUTime>::Type
01078 getSierraCPUTime()
01079 {
01080   return sierraTimer().getMetric<stk::diag::CPUTime>().getAccumulatedLap(false);
01081 }
01082 
01083 
01084 stk::diag::MetricTraits<stk::diag::WallTime>::Type
01085 getSierraWallTime()
01086 {
01087   return sierraTimer().getMetric<stk::diag::WallTime>().getAccumulatedLap(false);
01088 }
01089 
01090 
01091 stk::diag::MetricTraits<stk::diag::CPUTime>::Type
01092 getCPULapTime(Timer timer) {
01093   return timer.getMetric<stk::diag::CPUTime>().getLap();
01094 }
01095 
01096 stk::diag::MetricTraits<stk::diag::CPUTime>::Type
01097 getCPUAccumulatedLapTime(Timer timer) {
01098   return timer.getMetric<stk::diag::CPUTime>().getAccumulatedLap(false);
01099 }
01100 
01101 
01102 TimerParser &
01103 theTimerParser()
01104 {
01105   static TimerParser parser;
01106 
01107   return parser;
01108 }
01109 
01110 
01111 TimerParser::TimerParser()
01112   : sierra::OptionMaskParser()
01113 {
01114   mask("cpu", 0, "Display CPU times");
01115   mask("wall", 0, "Display wall times");
01116 
01117   mask("hms", 0, "Display times in HH:MM:SS format");
01118   mask("seconds", 0, "Display times in seconds");
01119 
01120   
01121 //   mask("table", TIMER_TABLE, "Format output as a table");
01122 //   mask("xml", TIMER_XML, "Format output as an XML file");
01123 
01124   mask("all", TIMER_ALL, "Enable all metrics");
01125   mask("none", TIMER_NONE, "Disable all timers");
01126 
01127   mask("domain", TIMER_DOMAIN, "Enable metrics on the domain");
01128   mask("region", TIMER_REGION, "Enable metrics on regions");
01129   mask("procedure", TIMER_PROCEDURE, "Enable metrics on procedures");
01130   mask("mechanics", TIMER_MECHANICS, "Enable metrics on mechanics");
01131   mask("algorithm", TIMER_ALGORITHM, "Enable metrics on algorithms");
01132   mask("solver", TIMER_SOLVER, "Enable metrics on solvers");
01133   mask("contact", TIMER_CONTACT, "Enable metrics on contact");
01134   mask("material", TIMER_MATERIAL, "Enable metrics on materials");
01135   mask("search", TIMER_SEARCH, "Enable metrics on searches");
01136   mask("transfer", TIMER_TRANSFER, "Enable metrics on user functions");
01137   mask("adaptivity", TIMER_ADAPTIVITY, "Enable metrics on adaptivity");
01138   mask("recovery", TIMER_RECOVERY, "Enable metrics on encore recovery");
01139   mask("profile1", TIMER_PROFILE_1, "Enable app defined profiling metrics");
01140   mask("profile2", TIMER_PROFILE_2, "Enable app defined profiling metrics");
01141   mask("profile3", TIMER_PROFILE_3, "Enable app defined profiling metrics");
01142   mask("profile4", TIMER_PROFILE_4, "Enable app defined profiling metrics");
01143   mask("app1", TIMER_APP_1, "Enable app defined metrics");
01144   mask("app2", TIMER_APP_2, "Enable app defined metrics");
01145   mask("app3", TIMER_APP_3, "Enable app defined metrics");
01146   mask("app4", TIMER_APP_4, "Enable app defined metrics");
01147 }
01148 
01149 
01150 OptionMaskParser::Mask
01151 TimerParser::parse(
01152   const char *          mask) const
01153 {
01154   m_metricsSetMask = 0;
01155   m_metricsMask = 0;
01156   m_optionMask = getEnabledTimerMask();
01157   
01158   m_optionMask = OptionMaskParser::parse(mask);
01159 
01160 //   if ((m_optionMask & TIMER_FORMAT) == 0)
01161 //     m_optionMask |= TIMER_TABLE;
01162 
01163   setEnabledTimerMask(m_optionMask);
01164   
01165   if (m_metricsSetMask != 0)
01166     stk::diag::setEnabledTimerMetricsMask(m_metricsMask);
01167     
01168   return m_optionMask;
01169 }
01170 
01171 
01172 void
01173 TimerParser::parseArg(
01174   const std::string &   name,
01175   const std::string &   arg) const
01176 {
01177   if (name == "cpu") {
01178     m_metricsMask |= stk::diag::METRICS_CPU_TIME;
01179     m_metricsSetMask |= stk::diag::METRICS_CPU_TIME;
01180   }
01181   else if (name == "wall") {
01182     m_metricsMask |= stk::diag::METRICS_WALL_TIME;
01183     m_metricsSetMask |= stk::diag::METRICS_WALL_TIME;
01184   }
01185   else if (name == "heap") {
01186     m_metricsMask |= stk::diag::METRICS_HEAP_ALLOC;
01187     m_metricsSetMask |= stk::diag::METRICS_HEAP_ALLOC;
01188   }
01189   else if (name == "none") {
01190     m_optionMask = 0;
01191     m_metricsSetMask = stk::diag::METRICS_WALL_TIME | stk::diag::METRICS_CPU_TIME;
01192   }
01193 
01194   else if (name == "hms") {
01195     Diag::setTimeFormat(stk::TIMEFORMAT_HMS);
01196   }
01197   else if (name == "seconds") {
01198     Diag::setTimeFormat(stk::TIMEFORMAT_SECONDS);
01199   }
01200 
01201   else
01202     OptionMaskParser::parseArg(name, arg);
01203 }
01204 
01205 } // namespace Diag
01206 } // namespace sierra
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines