|
Sierra Toolkit
Version of the Day
|
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 <stk_util/util/string_case_compare.hpp> 00018 00019 #include <stk_util/diag/Timer.hpp> 00020 #include <stk_util/diag/Writer.hpp> 00021 #include <stk_util/diag/WriterExt.hpp> 00022 00023 namespace stk { 00024 namespace diag { 00025 00026 namespace { 00027 00028 MetricsMask s_enabledMetricsMask = METRICS_LAP_COUNT | METRICS_CPU_TIME | METRICS_WALL_TIME; 00029 00030 template <class T> 00031 typename MetricTraits<T>::Type 00032 value_now() { 00033 if (MetricTraits<T>::METRIC & getEnabledTimerMetricsMask()) 00034 return MetricTraits<T>::value_now(); 00035 else 00036 return 0; 00037 } 00038 00039 std::vector<std::string> & 00040 split( 00041 const std::string & path, 00042 char separator, 00043 std::vector<std::string> & path_vector) 00044 { 00045 for (std::string::const_iterator it = path.begin(); ; ) { 00046 std::string::const_iterator it2 = std::find(it, path.end(), separator); 00047 path_vector.push_back(std::string(it, it2)); 00048 if (it2 == path.end()) 00049 break; 00050 it = it2 + 1; 00051 } 00052 00053 return path_vector; 00054 } 00055 00056 } // namespace <empty> 00057 00058 00059 MetricsMask getEnabledTimerMetricsMask() 00060 { 00061 return s_enabledMetricsMask; 00062 } 00063 00064 void 00065 setEnabledTimerMetricsMask( 00066 MetricsMask timer_mask) 00067 { 00068 s_enabledMetricsMask = timer_mask | METRICS_LAP_COUNT; 00069 } 00070 00071 00093 class TimerImpl 00094 { 00095 friend class Timer; 00096 00097 public: 00098 static void updateRootTimer(TimerImpl *root_timer); 00099 00100 static Timer createRootTimer(const std::string &name, const TimerSet &timer_set); 00101 00102 static void deleteRootTimer(TimerImpl *root_timer); 00103 00104 static std::vector<Timer> &findTimers(TimerImpl *root_timer, const std::string &path_tail, std::vector<Timer> &found_timers); 00105 00106 static void findTimer(TimerImpl *timer, std::vector<std::string> &path_tail_vector, std::vector<Timer> &found_timers); 00107 00108 private: 00118 static TimerImpl *reg(const std::string &name, TimerMask timer_mask, TimerImpl *parent_timer, const TimerSet &timer_set) { 00119 return parent_timer->addSubtimer(name, timer_mask, timer_set); 00120 } 00121 00129 TimerImpl(const std::string &name, TimerMask timer_mask, TimerImpl *parent_timer, const TimerSet &timer_set); 00130 00135 ~TimerImpl(); 00136 00137 TimerImpl(const TimerImpl &TimerImpl); 00138 TimerImpl &operator=(const TimerImpl &TimerImpl); 00139 00146 #ifdef __INTEL_COMPILER 00147 #pragma warning(push) 00148 #pragma warning(disable: 444) 00149 #endif 00150 class finder : private std::unary_function<Timer, bool> 00151 { 00152 public: 00153 explicit finder(const std::string &name) 00154 : m_name(name) 00155 {} 00156 00157 bool operator()(Timer timer) const { 00158 return equal_case(timer.getName(), m_name); 00159 } 00160 00161 private: 00162 std::string m_name; 00163 }; 00164 #ifdef __INTEL_COMPILER 00165 #pragma warning(pop) 00166 #endif 00167 00168 public: 00175 const std::string &getName() const { 00176 return m_name; 00177 } 00178 00184 TimerMask getTimerMask() const { 00185 return m_timerMask; 00186 } 00187 00193 const TimerSet &getTimerSet() const { 00194 return m_timerSet; 00195 } 00196 00205 bool shouldRecord() const { 00206 return m_timerSet.shouldRecord(m_timerMask) && s_enabledMetricsMask; 00207 } 00208 00215 double getSubtimerLapCount() const { 00216 return m_subtimerLapCount; 00217 } 00218 00219 void setSubtimerLapCount(double value) { 00220 m_subtimerLapCount = value; 00221 } 00222 00230 template <class T> 00231 const Timer::Metric<T> &getMetric() const; 00232 00240 const TimerList &getTimerList() const { 00241 return m_subtimerList; 00242 } 00243 00244 TimerList::iterator begin() { 00245 return m_subtimerList.begin(); 00246 } 00247 00248 TimerList::const_iterator begin() const { 00249 return m_subtimerList.begin(); 00250 } 00251 00252 TimerList::iterator end() { 00253 return m_subtimerList.end(); 00254 } 00255 00256 TimerList::const_iterator end() const { 00257 return m_subtimerList.end(); 00258 } 00259 00264 void reset(); 00265 00270 void checkpoint() const; 00271 00277 TimerImpl &start(); 00278 00284 TimerImpl &lap(); 00285 00292 TimerImpl &stop(); 00293 00301 double accumulateSubtimerLapCounts() const; 00302 00303 Timer getSubtimer(const std::string &name); 00304 00305 public: 00314 Writer &dump(Writer &dout) const; 00315 00316 private: 00328 TimerImpl *addSubtimer(const std::string &name, TimerMask timer_mask, const TimerSet &timer_set); 00329 00330 private: 00331 std::string m_name; 00332 TimerMask m_timerMask; 00333 TimerImpl * m_parentTimer; 00334 mutable double m_subtimerLapCount; 00335 unsigned m_lapStartCount; 00336 00337 TimerList m_subtimerList; 00338 00339 const TimerSet & m_timerSet; 00340 Timer::Metric<LapCount> m_lapCount; 00341 Timer::Metric<CPUTime> m_cpuTime; 00342 Timer::Metric<WallTime> m_wallTime; 00343 Timer::Metric<MPICount> m_MPICount; 00344 Timer::Metric<MPIByteCount> m_MPIByteCount; 00345 Timer::Metric<HeapAlloc> m_heapAlloc; 00346 }; 00347 00348 00358 inline Writer &operator<<(Writer &dout, const TimerImpl &timer) { 00359 return timer.dump(dout); 00360 } 00361 00362 00363 void 00364 updateRootTimer( 00365 Timer root_timer) 00366 { 00367 TimerImpl::updateRootTimer(root_timer.m_timerImpl); 00368 } 00369 00370 00371 Timer 00372 createRootTimer( 00373 const std::string & name, 00374 const TimerSet & timer_set) 00375 { 00376 return TimerImpl::createRootTimer(name, timer_set); 00377 } 00378 00379 00380 void 00381 deleteRootTimer( 00382 Timer timer) 00383 { 00384 TimerImpl::deleteRootTimer(timer.m_timerImpl); 00385 timer.m_timerImpl = 0; 00386 } 00387 00388 00389 std::vector<Timer> & 00390 findTimers(Timer root_timer, const std::string &path_tail, std::vector<Timer> &found_timers) { 00391 TimerImpl::findTimers(root_timer.m_timerImpl, path_tail, found_timers); 00392 return found_timers; 00393 } 00394 00395 00396 TimerImpl::TimerImpl( 00397 const std::string & name, 00398 TimerMask timer_mask, 00399 TimerImpl * parent_timer, 00400 const TimerSet & timer_set) 00401 : m_name(name), 00402 m_timerMask(timer_mask), 00403 m_parentTimer(parent_timer), 00404 m_subtimerLapCount(0.0), 00405 m_lapStartCount(0), 00406 m_subtimerList(), 00407 m_timerSet(timer_set) 00408 {} 00409 00410 00411 TimerImpl::~TimerImpl() 00412 { 00413 try { 00414 for (TimerList::iterator it = m_subtimerList.begin(); it != m_subtimerList.end(); ++it) 00415 delete (*it).m_timerImpl; 00416 } 00417 catch (std::exception &) { 00418 } 00419 } 00420 00421 00422 template<> 00423 const Timer::Metric<LapCount> & 00424 TimerImpl::getMetric<LapCount>() const { 00425 return m_lapCount; 00426 } 00427 00428 00429 template<> 00430 const Timer::Metric<CPUTime> & 00431 TimerImpl::getMetric<CPUTime>() const { 00432 return m_cpuTime; 00433 } 00434 00435 00436 template<> 00437 const Timer::Metric<WallTime> & 00438 TimerImpl::getMetric<WallTime>() const { 00439 return m_wallTime; 00440 } 00441 00442 00443 template<> 00444 const Timer::Metric<MPICount> & 00445 TimerImpl::getMetric<MPICount>() const { 00446 return m_MPICount; 00447 } 00448 00449 00450 template<> 00451 const Timer::Metric<MPIByteCount> & 00452 TimerImpl::getMetric<MPIByteCount>() const { 00453 return m_MPIByteCount; 00454 } 00455 00456 00457 template<> 00458 const Timer::Metric<HeapAlloc> & 00459 TimerImpl::getMetric<HeapAlloc>() const { 00460 return m_heapAlloc; 00461 } 00462 00463 00464 void 00465 TimerImpl::reset() 00466 { 00467 m_lapStartCount = 0; 00468 00469 m_lapCount.reset(); 00470 m_cpuTime.reset(); 00471 m_wallTime.reset(); 00472 m_MPICount.reset(); 00473 m_MPIByteCount.reset(); 00474 m_heapAlloc.reset(); 00475 } 00476 00477 00478 Timer 00479 TimerImpl::getSubtimer( 00480 const std::string & name) 00481 { 00482 TimerList::iterator it = std::find_if(m_subtimerList.begin(), m_subtimerList.end(), finder(name)); 00483 00484 if (it == m_subtimerList.end()) 00485 throw std::runtime_error("Timer not found"); 00486 else 00487 return *it; 00488 } 00489 00490 00491 TimerImpl * 00492 TimerImpl::addSubtimer( 00493 const std::string & name, 00494 TimerMask timer_mask, 00495 const TimerSet & timer_set) 00496 { 00497 TimerList::iterator it = std::find_if(m_subtimerList.begin(), m_subtimerList.end(), finder(name)); 00498 00499 if (it == m_subtimerList.end()) { 00500 TimerImpl *timer_impl = new TimerImpl(name, timer_mask, this, timer_set); 00501 m_subtimerList.push_back(Timer(timer_impl)); 00502 return timer_impl; 00503 } 00504 else 00505 return (*it).m_timerImpl; 00506 } 00507 00508 00509 TimerImpl & 00510 TimerImpl::start() 00511 { 00512 if (shouldRecord()) { 00513 if (m_lapStartCount++ == 0) { 00514 m_lapCount.m_lapStart = m_lapCount.m_lapStop; 00515 00516 m_cpuTime.m_lapStop = m_cpuTime.m_lapStart = value_now<CPUTime>(); 00517 m_wallTime.m_lapStop = m_wallTime.m_lapStart = value_now<WallTime>(); 00518 m_MPICount.m_lapStop = m_MPICount.m_lapStart = value_now<MPICount>(); 00519 m_MPIByteCount.m_lapStop = m_MPIByteCount.m_lapStart = value_now<MPIByteCount>(); 00520 m_heapAlloc.m_lapStop = m_heapAlloc.m_lapStart = value_now<HeapAlloc>(); 00521 } 00522 } 00523 00524 return *this; 00525 } 00526 00527 00528 TimerImpl & 00529 TimerImpl::lap() 00530 { 00531 if (shouldRecord()) { 00532 if (m_lapStartCount > 0) { 00533 m_cpuTime.m_lapStop = value_now<CPUTime>(); 00534 m_wallTime.m_lapStop = value_now<WallTime>(); 00535 m_MPICount.m_lapStop = value_now<MPICount>(); 00536 m_MPIByteCount.m_lapStop = value_now<MPIByteCount>(); 00537 m_heapAlloc.m_lapStop = value_now<HeapAlloc>(); 00538 } 00539 } 00540 00541 return *this; 00542 } 00543 00544 00545 TimerImpl & 00546 TimerImpl::stop() 00547 { 00548 if (shouldRecord()) { 00549 if (--m_lapStartCount <= 0) { 00550 m_lapStartCount = 0; 00551 m_lapCount.m_lapStop++; 00552 00553 m_cpuTime.m_lapStop = value_now<CPUTime>(); 00554 m_wallTime.m_lapStop = value_now<WallTime>(); 00555 m_MPICount.m_lapStop = value_now<MPICount>(); 00556 m_MPIByteCount.m_lapStop = value_now<MPIByteCount>(); 00557 m_heapAlloc.m_lapStop = value_now<HeapAlloc>(); 00558 00559 m_lapCount.addLap(); 00560 m_cpuTime.addLap(); 00561 m_wallTime.addLap(); 00562 m_MPICount.addLap(); 00563 m_MPIByteCount.addLap(); 00564 m_heapAlloc.addLap(); 00565 } 00566 } 00567 00568 return *this; 00569 } 00570 00571 00572 double 00573 TimerImpl::accumulateSubtimerLapCounts() const 00574 { 00575 m_subtimerLapCount = m_lapCount.getAccumulatedLap(false); 00576 00577 for (TimerList::const_iterator it = m_subtimerList.begin(); it != m_subtimerList.end(); ++it) 00578 (*it).m_timerImpl->accumulateSubtimerLapCounts(); 00579 00580 for (TimerList::const_iterator it = m_subtimerList.begin(); it != m_subtimerList.end(); ++it) 00581 m_subtimerLapCount += (*it).m_timerImpl->m_subtimerLapCount; 00582 00583 return m_subtimerLapCount; 00584 } 00585 00586 00587 void 00588 TimerImpl::checkpoint() const 00589 { 00590 m_lapCount.checkpoint(); 00591 m_cpuTime.checkpoint(); 00592 m_wallTime.checkpoint(); 00593 m_MPICount.checkpoint(); 00594 m_MPIByteCount.checkpoint(); 00595 m_heapAlloc.checkpoint(); 00596 00597 for (TimerList::const_iterator it = m_subtimerList.begin(); it != m_subtimerList.end(); ++it) 00598 (*it).m_timerImpl->checkpoint(); 00599 } 00600 00601 00602 void 00603 TimerImpl::updateRootTimer(TimerImpl *root_timer) 00604 { 00605 root_timer->m_lapCount.m_lapStop = value_now<LapCount>(); 00606 root_timer->m_cpuTime.m_lapStop = value_now<CPUTime>(); 00607 root_timer->m_wallTime.m_lapStop = value_now<WallTime>(); 00608 root_timer->m_MPICount.m_lapStop = value_now<MPICount>(); 00609 root_timer->m_MPIByteCount.m_lapStop = value_now<MPIByteCount>(); 00610 root_timer->m_heapAlloc.m_lapStop = value_now<HeapAlloc>(); 00611 00612 root_timer->m_lapCount.m_accumulatedLap = root_timer->m_lapCount.m_lapStop - root_timer->m_lapCount.m_lapStart; 00613 root_timer->m_cpuTime.m_accumulatedLap = root_timer->m_cpuTime.m_lapStop - root_timer->m_cpuTime.m_lapStart; 00614 root_timer->m_wallTime.m_accumulatedLap = root_timer->m_wallTime.m_lapStop - root_timer->m_wallTime.m_lapStart; 00615 root_timer->m_MPICount.m_accumulatedLap = root_timer->m_MPICount.m_lapStop - root_timer->m_MPICount.m_lapStart; 00616 root_timer->m_MPIByteCount.m_accumulatedLap = root_timer->m_MPIByteCount.m_lapStop - root_timer->m_MPIByteCount.m_lapStart; 00617 root_timer->m_heapAlloc.m_accumulatedLap = root_timer->m_heapAlloc.m_lapStop - root_timer->m_heapAlloc.m_lapStart; 00618 } 00619 00620 00621 00622 Timer 00623 TimerImpl::createRootTimer( 00624 const std::string & name, 00625 const TimerSet & timer_set) 00626 { 00627 TimerImpl *timer_impl = new TimerImpl(name, 0, 0, timer_set); 00628 return Timer(timer_impl); 00629 } 00630 00631 00632 void 00633 TimerImpl::deleteRootTimer( 00634 TimerImpl * root_timer) 00635 { 00636 delete root_timer; 00637 } 00638 00639 00640 void 00641 TimerImpl::findTimer( 00642 TimerImpl * timer, 00643 std::vector<std::string> & path_tail_vector, 00644 std::vector<Timer> & found_timers) 00645 { 00646 if (timer->begin() == timer->end()) { // at leaf 00647 00648 } 00649 else 00650 for (TimerList::const_iterator it = timer->begin(); it != timer->end(); ++it) 00651 findTimer((*it).m_timerImpl, path_tail_vector, found_timers); 00652 } 00653 00654 00655 std::vector<Timer> & 00656 TimerImpl::findTimers( 00657 TimerImpl * root_timer, 00658 const std::string & path_tail, 00659 std::vector<Timer> & found_timers) 00660 { 00661 std::vector<std::string> path_tail_vector; 00662 00663 findTimer(root_timer, split(path_tail, '.', path_tail_vector), found_timers); 00664 00665 return found_timers; 00666 } 00667 00668 00669 00670 Writer & 00671 TimerImpl::dump( 00672 Writer & dout) const 00673 { 00674 if (dout.shouldPrint()) { 00675 dout << "TimerImpl" << push << dendl; 00676 dout << "m_name, " << m_name << dendl; 00677 dout << "m_timerMask, " << m_timerMask << dendl; 00678 // dout << "m_parentTimer, " << c_ptr_name(m_parentTimer) << dendl; 00679 dout << "m_subtimerLapCount, " << m_subtimerLapCount << dendl; 00680 dout << "m_lapStartCount, " << m_lapStartCount << dendl; 00681 00682 dout << "m_lapCount, " << m_lapCount << dendl; 00683 dout << "m_cpuTime, " << m_cpuTime << dendl; 00684 dout << "m_wallTime, " << m_wallTime << dendl; 00685 dout << "m_MPICount, " << m_MPICount << dendl; 00686 dout << "m_MPIByteCount, " << m_MPIByteCount << dendl; 00687 dout << "m_heapAlloc, " << m_heapAlloc << dendl; 00688 00689 dout << "m_subtimerList, " << m_subtimerList << dendl; 00690 dout << pop; 00691 } 00692 00693 return dout; 00694 } 00695 00696 00697 Timer::Timer(const std::string &name, const Timer parent) 00698 : m_timerImpl(TimerImpl::reg(name, parent.getTimerMask(), parent.m_timerImpl, parent.getTimerSet())) 00699 {} 00700 00701 Timer::Timer(const std::string &name, TimerMask timer_mask, const Timer parent) 00702 : m_timerImpl(TimerImpl::reg(name, timer_mask, parent.m_timerImpl, parent.getTimerSet())) 00703 {} 00704 00705 Timer::Timer(const std::string &name, const Timer parent, const TimerSet &timer_set) 00706 : m_timerImpl(TimerImpl::reg(name, parent.getTimerMask(), parent.m_timerImpl, timer_set)) 00707 {} 00708 00709 Timer::Timer(const std::string &name, TimerMask timer_mask, const Timer parent, const TimerSet &timer_set) 00710 : m_timerImpl(TimerImpl::reg(name, timer_mask, parent.m_timerImpl, timer_set)) 00711 {} 00712 00713 00714 const std::string & 00715 Timer::getName() const { 00716 return m_timerImpl->m_name; 00717 } 00718 00719 TimerMask 00720 Timer::getTimerMask() const { 00721 return m_timerImpl->getTimerMask(); 00722 } 00723 00724 const TimerSet & 00725 Timer::getTimerSet() const { 00726 return m_timerImpl->getTimerSet(); 00727 } 00728 00729 double 00730 Timer::getSubtimerLapCount() const { 00731 return m_timerImpl->getSubtimerLapCount(); 00732 } 00733 00734 const TimerList & 00735 Timer::getTimerList() const { 00736 return m_timerImpl->getTimerList(); 00737 } 00738 00739 template<class T> 00740 const Timer::Metric<T> & 00741 Timer::getMetric() const { 00742 return m_timerImpl->getMetric<T>(); 00743 } 00744 00745 template const Timer::Metric<LapCount> &Timer::getMetric<LapCount>() const; 00746 template const Timer::Metric<CPUTime> &Timer::getMetric<CPUTime>() const; 00747 template const Timer::Metric<WallTime> &Timer::getMetric<WallTime>() const; 00748 template const Timer::Metric<MPICount> &Timer::getMetric<MPICount>() const; 00749 template const Timer::Metric<MPIByteCount> &Timer::getMetric<MPIByteCount>() const; 00750 template const Timer::Metric<HeapAlloc> &Timer::getMetric<HeapAlloc>() const; 00751 00752 00753 bool 00754 Timer::shouldRecord() const 00755 { 00756 return m_timerImpl->shouldRecord(); 00757 } 00758 00759 TimerList::iterator 00760 Timer::begin() 00761 { 00762 return m_timerImpl->begin(); 00763 } 00764 00765 TimerList::const_iterator 00766 Timer::begin() const 00767 { 00768 return m_timerImpl->begin(); 00769 } 00770 00771 TimerList::iterator 00772 Timer::end() 00773 { 00774 return m_timerImpl->end(); 00775 } 00776 00777 TimerList::const_iterator 00778 Timer::end() const 00779 { 00780 return m_timerImpl->end(); 00781 } 00782 00783 double 00784 Timer::accumulateSubtimerLapCounts() const { 00785 return m_timerImpl->accumulateSubtimerLapCounts(); 00786 } 00787 00788 Timer & 00789 Timer::start() { 00790 m_timerImpl->start(); 00791 return *this; 00792 } 00793 00794 Timer & 00795 Timer::lap() { 00796 m_timerImpl->lap(); 00797 return *this; 00798 } 00799 00800 Timer & 00801 Timer::stop() { 00802 m_timerImpl->stop(); 00803 return *this; 00804 } 00805 00806 void 00807 Timer::checkpoint() const { 00808 m_timerImpl->checkpoint(); 00809 } 00810 00811 Writer & 00812 Timer::dump(Writer& dout) const { 00813 return m_timerImpl->dump(dout); 00814 } 00815 00816 template <class T> 00817 Writer & 00818 Timer::Metric<T>::dump( 00819 Writer & dout) const 00820 { 00821 if (dout.shouldPrint()) { 00822 dout << "Timer::Metric<T>" << push << dendl; 00823 dout << "m_lapStart, " << m_lapStart << dendl; 00824 dout << "m_lapStop, " << m_lapStop << dendl; 00825 dout << "m_accumulatedLap, " << m_accumulatedLap << dendl; 00826 dout << "m_checkpoint, " << m_checkpoint << dendl; 00827 dout << pop; 00828 } 00829 return dout; 00830 } 00831 00832 template Writer &Timer::Metric<LapCount>::dump(Writer &) const; 00833 template Writer &Timer::Metric<CPUTime>::dump(Writer &) const; 00834 template Writer &Timer::Metric<WallTime>::dump(Writer &) const; 00835 template Writer &Timer::Metric<MPICount>::dump(Writer &) const; 00836 template Writer &Timer::Metric<MPIByteCount>::dump(Writer &) const; 00837 template Writer &Timer::Metric<HeapAlloc>::dump(Writer &) const; 00838 00839 00840 TimeBlockSynchronized::TimeBlockSynchronized( 00841 Timer & timer, 00842 MPI_Comm mpi_comm, 00843 bool start_timer) 00844 : m_timer(timer), 00845 m_mpiComm(mpi_comm), 00846 m_started(start_timer) 00847 { 00848 if (m_timer.m_timerImpl->shouldRecord()) { 00849 #ifdef STK_HAS_MPI 00850 if (mpi_comm != MPI_COMM_NULL) 00851 MPI_Barrier(mpi_comm); 00852 #endif 00853 00854 if (start_timer) 00855 m_timer.start(); 00856 } 00857 } 00858 00859 00860 TimeBlockSynchronized::~TimeBlockSynchronized() 00861 { 00862 if (m_started) { 00863 try { 00864 m_timer.stop(); 00865 } 00866 catch (...) { 00867 } 00868 } 00869 } 00870 00871 00872 void 00873 TimeBlockSynchronized::start() 00874 { 00875 // Place barrier here 00876 MPI_Barrier(m_mpiComm); 00877 m_started = true; 00878 m_timer.start(); 00879 } 00880 00881 00882 void 00883 TimeBlockSynchronized::stop() 00884 { 00885 m_started = false; 00886 m_timer.stop(); 00887 // Does a barrier need to be here? 00888 // MPI_Barrier(Env::parallel_comm()); 00889 } 00890 00891 } // namespace diag 00892 } // namespace stk