53#ifdef HAVE_TEUCHOS_ADD_TIME_MONITOR_TO_STACKED_TIMER
110 template<
class Ordinal,
class ScalarType,
class IndexType>
116 const std::pair<ScalarType, IndexType>
inBuffer[],
117 std::pair<ScalarType, IndexType>
inoutBuffer[])
const;
120 template<
class Ordinal>
126 const std::pair<double, int>
inBuffer[],
129 for (Ordinal
ind = 0;
ind < count; ++
ind) {
136 }
else if (
in.first <
inout.first) {
172 template<
class Ordinal,
class ScalarType,
class IndexType>
178 const std::pair<ScalarType, IndexType>
inBuffer[],
179 std::pair<ScalarType, IndexType>
inoutBuffer[])
const;
182 template<
class Ordinal>
188 const std::pair<double, int>
inBuffer[],
191 for (Ordinal
ind = 0;
ind < count; ++
ind) {
198 }
else if (
in.first >
inout.first) {
211 template<
class Ordinal,
class ScalarType,
class IndexType>
217 const std::pair<ScalarType, IndexType>
inBuffer[],
218 std::pair<ScalarType, IndexType>
inoutBuffer[])
const;
221 template<
class Ordinal>
227 const std::pair<double, int>
inBuffer[],
230 for (Ordinal
ind = 0;
ind < count; ++
ind) {
234 if ( (
in.first <
inout.first &&
in.first != 0) || (
inout.first == 0 &&
in.first != 0) ) {
237 }
else if (
in.first >
inout.first) {
251 typedef std::map<std::string, std::pair<double, int> >
timer_map_t;
261#ifdef HAVE_TEUCHOS_ADD_TIME_MONITOR_TO_STACKED_TIMER
271#ifdef HAVE_TEUCHOS_ADD_TIME_MONITOR_TO_STACKED_TIMER
276 catch (std::runtime_error&
e) {
279 "\n*********************************************************************\n"
280 "WARNING: Overlapping timers detected! Near: " <<
counter().name()<<
"\n"
281 "A TimeMonitor timer was stopped before a nested subtimer was\n"
282 "stopped. This is not allowed by the StackedTimer. This corner case\n"
283 "typically occurs if the TimeMonitor is stored in an RCP and the RCP is\n"
284 "assigned to a new timer. To disable this warning, either fix the\n"
285 "ordering of timer creation and destuction or disable the StackedTimer\n"
286 "support in the TimeMonitor by setting the StackedTimer to null\n"
288 " RCP<TimeMonitor> MM = rcp(new TimeMonitor(*(TimeMonitor::getNewTimer(\"Junk\"))));\n"
290 "MM = Teuchos::null;\n"
291 "MM = rcp(new TimeMonitor(*(TimeMonitor::getNewTimer(\"SecondJunk\"))));\n"
292 "*********************************************************************\n";
293 std::cout <<
warning.str() << std::endl <<
e.what() << std::endl;
305 timer == null, std::invalid_argument,
306 "TimeMonitor::disableTimer: Invalid timer \"" << name <<
"\"");
315 timer == null, std::invalid_argument,
316 "TimeMonitor::enableTimer: Invalid timer \"" << name <<
"\"");
323 typedef std::map<std::string, RCP<Time> > map_type;
338 it->second->isRunning (), std::runtime_error,
339 "Timer \"" <<
it->second->name () <<
"\" is currently running. "
340 "You are not allowed to reset running timers.");
345 it->second->reset ();
358 std::pair<std::string, std::pair<double, int> >
361 return std::make_pair (name, std::make_pair (
double(0),
int(0)));
383 const std::map<std::string, RCP<Time> >& localCounters,
384 const std::string& filter=
"")
386 using std::make_pair;
387 typedef timer_map_t::iterator iter_t;
390 for (std::map<std::string, RCP<Time> >::const_iterator it = localCounters.begin();
391 it != localCounters.end(); ++it) {
392 const std::string& name = it->second->name ();
396 const bool skipThisOne = (filter !=
"" && name.find (filter) != 0);
398 const double timing = it->second->totalElapsedTime ();
399 const int numCalls = it->second->numCalls ();
403 iter_t loc = theLocalData.find (name);
404 if (loc == theLocalData.end()) {
406 theLocalData.insert (loc, make_pair (name, make_pair (timing, numCalls)));
409 loc->second.first += timing;
410 loc->second.second += numCalls;
416 localData.swap (theLocalData);
428 for (timer_map_t::const_iterator it = timerData.begin();
429 it != timerData.end(); ++it) {
430 if (it->second.second > 0) {
431 newTimerData[it->first] = it->second;
434 timerData.swap (newTimerData);
459 collectLocalTimerDataAndNames (
timer_map_t& localTimerData,
460 Array<std::string>& localTimerNames,
461 const std::map<std::string, RCP<Time> >& localTimers,
462 const bool writeZeroTimers,
463 const std::string& filter=
"")
466 collectLocalTimerData (localTimerData, localTimers, filter);
472 if (! writeZeroTimers) {
473 filterZeroData (localTimerData);
478 localTimerNames.reserve (localTimerData.size());
479 for (timer_map_t::const_iterator it = localTimerData.begin();
480 it != localTimerData.end(); ++it) {
481 localTimerNames.push_back (it->first);
520 collectGlobalTimerData (
timer_map_t& globalTimerData,
521 Array<std::string>& globalTimerNames,
523 Array<std::string>& localTimerNames,
524 Ptr<
const Comm<int> > comm,
525 const bool alwaysWriteLocal,
554 const timer_map_t::size_type myNumGlobalNames = globalTimerNames.size();
555 timer_map_t::size_type minNumGlobalNames = 0;
556 timer_map_t::size_type maxNumGlobalNames = 0;
557 reduceAll (*comm,
REDUCE_MIN, myNumGlobalNames,
558 outArg (minNumGlobalNames));
559 reduceAll (*comm,
REDUCE_MAX, myNumGlobalNames,
560 outArg (maxNumGlobalNames));
562 std::logic_error,
"Min # global timer names = " << minNumGlobalNames
563 <<
" != max # global timer names = " << maxNumGlobalNames
564 <<
". Please report this bug to the Teuchos developers.");
566 std::logic_error,
"My # global timer names = " << myNumGlobalNames
567 <<
" != min # global timer names = " << minNumGlobalNames
568 <<
". Please report this bug to the Teuchos developers.");
587 timer_map_t::iterator globalMapIter = globalTimerData.begin();
588 timer_map_t::iterator localMapIter;
590 it != globalTimerNames.end(); ++it) {
591 const std::string& globalName = *it;
592 localMapIter = localTimerData.find (globalName);
594 if (localMapIter == localTimerData.end()) {
595 if (alwaysWriteLocal) {
611 localMapIter = localTimerData.insert (localMapIter, makeEmptyTimerDatum (globalName));
616 localTimerNames.push_back (globalName);
621 globalMapIter = globalTimerData.insert (globalMapIter, makeEmptyTimerDatum (globalName));
627 globalMapIter = globalTimerData.insert (globalMapIter, std::make_pair (globalName, localMapIter->second));
631 if (alwaysWriteLocal) {
634 std::sort (localTimerNames.begin(), localTimerNames.end());
641 const timer_map_t::size_type myNumGlobalTimers = globalTimerData.size();
642 timer_map_t::size_type minNumGlobalTimers = 0;
643 timer_map_t::size_type maxNumGlobalTimers = 0;
644 reduceAll (*comm,
REDUCE_MIN, myNumGlobalTimers,
645 outArg (minNumGlobalTimers));
646 reduceAll (*comm,
REDUCE_MAX, myNumGlobalTimers,
647 outArg (maxNumGlobalTimers));
649 std::logic_error,
"Min # global timers = " << minNumGlobalTimers
650 <<
" != max # global timers = " << maxNumGlobalTimers
651 <<
". Please report this bug to the Teuchos developers.");
653 std::logic_error,
"My # global timers = " << myNumGlobalTimers
654 <<
" != min # global timers = " << minNumGlobalTimers
655 <<
". Please report this bug to the Teuchos developers.");
708 std::vector<std::string>& statNames,
709 Ptr<
const Comm<int> > comm,
711 const bool ignoreZeroTimers)
715 const int numTimers =
static_cast<int> (globalTimerData.size());
716 const int numProcs = comm->getSize();
721 Array<std::pair<double, int> > timingsAndCallCounts;
722 timingsAndCallCounts.reserve (numTimers);
723 for (timer_map_t::const_iterator it = globalTimerData.begin();
724 it != globalTimerData.end(); ++it) {
725 timingsAndCallCounts.push_back (it->second);
732 Array<std::pair<double, int> > minTimingsAndCallCounts (numTimers);
734 if (ignoreZeroTimers)
735 reduceAll (*comm, MinLocNonzero<int, double, int>(), numTimers,
736 &timingsAndCallCounts[0], &minTimingsAndCallCounts[0]);
738 reduceAll (*comm, MinLoc<int, double, int>(), numTimers,
739 &timingsAndCallCounts[0], &minTimingsAndCallCounts[0]);
746 Array<std::pair<double, int> > maxTimingsAndCallCounts (numTimers);
748 reduceAll (*comm, MaxLoc<int, double, int>(), numTimers,
749 &timingsAndCallCounts[0], &maxTimingsAndCallCounts[0]);
763 Array<double> meanOverCallCountsTimings (numTimers);
764 Array<double> meanOverProcsTimings (numTimers);
765 Array<double> meanCallCounts (numTimers);
766 Array<int> ICallThisTimer (numTimers);
767 Array<int> numProcsCallingEachTimer (numTimers);
770 if (ignoreZeroTimers) {
771 for (
int k = 0; k < numTimers; ++k) {
772 const double callCount =
static_cast<double> (timingsAndCallCounts[k].second);
773 if (callCount > 0) ICallThisTimer[k] = 1;
774 else ICallThisTimer[k] = 0;
777 reduceAll (*comm,
REDUCE_SUM, numTimers, &ICallThisTimer[0],
778 &numProcsCallingEachTimer[0]);
785 Array<double> scaledTimings (numTimers);
786 Array<double> scaledCallCounts (numTimers);
787 const double P =
static_cast<double> (numProcs);
789 if (ignoreZeroTimers) {
790 for (
int k = 0; k < numTimers; ++k) {
791 const double timing = timingsAndCallCounts[k].first;
792 const double callCount =
static_cast<double> (timingsAndCallCounts[k].second);
794 scaledTimings[k] = timing / numProcsCallingEachTimer[k];
795 scaledCallCounts[k] = callCount / numProcsCallingEachTimer[k];
799 for (
int k = 0; k < numTimers; ++k) {
800 const double timing = timingsAndCallCounts[k].first;
801 const double callCount =
static_cast<double> (timingsAndCallCounts[k].second);
803 scaledTimings[k] = timing / P;
804 scaledCallCounts[k] = callCount / P;
809 reduceAll (*comm,
REDUCE_SUM, numTimers, &scaledTimings[0],
810 &meanOverProcsTimings[0]);
811 reduceAll (*comm,
REDUCE_SUM, numTimers, &scaledCallCounts[0],
816 for (
int k = 0; k < numTimers; ++k) {
818 meanOverCallCountsTimings[k] = meanOverProcsTimings[k] / meanCallCounts[k];
830 statNames.resize (4);
831 statNames[0] =
"MinOverProcs";
832 statNames[1] =
"MeanOverProcs";
833 statNames[2] =
"MaxOverProcs";
834 statNames[3] =
"MeanOverCallCounts";
836 stat_map_type::iterator statIter = statData.end();
837 timer_map_t::const_iterator it = globalTimerData.begin();
838 for (
int k = 0; it != globalTimerData.end(); ++k, ++it) {
839 std::vector<std::pair<double, double> > curData (4);
840 curData[0] = minTimingsAndCallCounts[k];
841 curData[1] = std::make_pair (meanOverProcsTimings[k], meanCallCounts[k]);
842 curData[2] = maxTimingsAndCallCounts[k];
843 curData[3] = std::make_pair (meanOverCallCountsTimings[k], meanCallCounts[k]);
848 statIter = statData.insert (statIter, std::make_pair (it->first, curData));
869 RCP<const Comm<int> >
881 int mpiHasBeenStarted = 0;
882 MPI_Initialized (&mpiHasBeenStarted);
883 if (! mpiHasBeenStarted) {
885 comm = rcp_implicit_cast<const Comm<int> > (
rcp (
new SerialComm<int> ()));
900 const std::string&
filter)
931 const std::string&
filter,
972 const int precision =
format().precision();
973 const std::ios_base::fmtflags&
flags = out.flags();
991 titles.append (
"Timer Name");
1011 titles.append (
"Local time (num calls)");
1042 titles.append (
"Global time (num calls)");
1058 stat_map_type::const_iterator
it =
statData.begin();
1090 const std::string&
filter,
1106 const std::string&
filter)
1155 if (label.empty ()) {
1162 const bool alreadyQuoted = label.
size () >= 2 &&
1163 label[0] ==
'"' && label[label.size() - 1] ==
'"';
1168 bool needToQuote =
false;
1171 out.reserve (label.size ());
1173 const size_t startPos = alreadyQuoted ? 1 : 0;
1174 const size_t endPos = alreadyQuoted ? label.
size () - 1 : label.
size ();
1175 for (
size_t i = startPos; i < endPos; ++i) {
1176 const char c = label[i];
1177 if (c ==
'"' || c ==
'\\') {
1178 out.push_back (
'\\');
1181 else if (c ==
':') {
1187 if (needToQuote || alreadyQuoted) {
1190 return "\"" + out +
"\"";
1204 const std::string&
filter)
1207 using Teuchos::fancyOStream;
1208 using Teuchos::getFancyOStream;
1211 using Teuchos::rcpFromRef;
1213 typedef std::vector<std::string>::size_type size_type;
1240 pfout->setTabIndentStr (
" ");
1243 fout <<
"# Teuchos::TimeMonitor report" << endl
1255 fout <<
"Output mode: " << (
compact ?
"compact" :
"spacious") << endl
1256 <<
"Number of processes: " <<
numProcs << endl
1257 <<
"Time unit: s" << endl;
1261 fout <<
"Statistics collected: ";
1271 fout <<
"]" << endl;
1286 fout <<
"Timer names: ";
1290 for (stat_map_type::const_iterator
it =
statData.begin();
1297 fout <<
"]" << endl;
1302 for (stat_map_type::const_iterator
it =
statData.begin();
1309 fout <<
"Total times: ";
1318 const std::vector<std::pair<double, double> >&
curData =
outerIter->second;
1332 fout <<
"}" << endl;
1344 const std::vector<std::pair<double, double> >&
curData =
outerIter->second;
1353 fout <<
"Call counts:";
1362 const std::vector<std::pair<double, double> >&
curData =
outerIter->second;
1376 fout <<
"}" << endl;
1388 const std::vector<std::pair<double, double> >&
curData =
outerIter->second;
1400 const std::string&
filter)
1425 const std::string name (
"Report format");
1427 const std::string docString (
"Output format for report of timer statistics");
1433 docs.push_back (
"YAML (see yaml.org) format");
1436 docs.push_back (
"Tabular format via Teuchos::TableFormat");
1448 const std::string name (
"YAML style");
1450 const std::string docString (
"YAML-specific output format");
1455 strings.push_back (
"compact");
1456 docs.push_back (
"Compact format: use \"flow style\" (see YAML 1.2 spec at "
1457 "yaml.org) for most sequences except the outermost sequence");
1460 strings.push_back (
"spacious");
1461 docs.push_back (
"Spacious format: avoid flow style");
1473 const std::string name (
"How to merge timer sets");
1475 const std::string docString (
"How to merge differing sets of timers "
1476 "across processes");
1481 strings.push_back (
"Intersection");
1482 docs.push_back (
"Compute intersection of timer sets over processes");
1485 docs.push_back (
"Compute union of timer sets over processes");
1486 values.push_back (
Union);
1521 "Always output local timers' values on Proc 0");
1523 "statistics, even if there is only one process in the "
1526 "timers that have never been called");
1574 const std::string&
filter,
1588 "Invalid report format. This should never happen; ParameterList "
1589 "validation should have caught this. Please report this bug to the "
1590 "Teuchos developers.");
1604 const std::string&
filter,
Defines basic traits for the scalar field type.
A column of TableEntry objects.
Scope guard for Teuchos::Time, with MPI collective timer reporting.
std::vector< T >::const_iterator const_iterator
The type of a const forward iterator.
int size(const Comm< Ordinal > &comm)
Get the number of processes in the communicator.
static Teuchos::RCP< const Comm< OrdinalType > > getComm()
Return the default global communicator.
void reduce(const Ordinal count, const std::pair< double, int > inBuffer[], std::pair< double, int > inoutBuffer[]) const
Teuchos version of MPI_MAXLOC.
void reduce(const Ordinal count, const std::pair< ScalarType, IndexType > inBuffer[], std::pair< ScalarType, IndexType > inoutBuffer[]) const
void reduce(const Ordinal count, const std::pair< double, int > inBuffer[], std::pair< double, int > inoutBuffer[]) const
same as MinLoc, but don't allow zero
void reduce(const Ordinal count, const std::pair< ScalarType, IndexType > inBuffer[], std::pair< ScalarType, IndexType > inoutBuffer[]) const
void reduce(const Ordinal count, const std::pair< double, int > inBuffer[], std::pair< double, int > inoutBuffer[]) const
Teuchos version of MPI_MINLOC.
void reduce(const Ordinal count, const std::pair< ScalarType, IndexType > inBuffer[], std::pair< ScalarType, IndexType > inoutBuffer[]) const
A list of parameters of arbitrary type.
Simple wrapper class for raw pointers to single objects where no persisting relationship exists.
Smart reference counting pointer class for automatic garbage collection.
Concrete serial communicator subclass.
virtual void barrier() const
virtual int getSize() const
virtual int getRank() const
This class allows one to push and pop timers on and off a stack.
~SyncTimeMonitor() override
Destructor: stops the timer.
SyncTimeMonitor()=delete
Default constructor is deleted, since it would be unsafe.
Ptr< const Comm< int > > comm_
Scope guard for Time, that can compute MPI collective timer statistics.
~TimeMonitor() override
Destructor: stops the timer.
ETimeMonitorReportFormat
Valid output formats for report().
ETimeMonitorYamlFormat
Valid YAML output formats for report().
static void computeGlobalTimerStatistics(stat_map_type &statData, std::vector< std::string > &statNames, Ptr< const Comm< int > > comm, const ECounterSetOp setOp=Intersection, const std::string &filter="")
Compute global timer statistics for all timers on the given communicator.
static void setReportParameters(const RCP< ParameterList > ¶ms)
Set parameters for report(). Call only from report().
static void setSetOpParameter(ParameterList &plist)
Add the "How to merge timer sets" parameter to plist.
static void summarizeToYaml(Ptr< const Comm< int > > comm, std::ostream &out, const ETimeMonitorYamlFormat yamlStyle, const std::string &filter="")
Like summarize(), but with YAML-format output.
static Teuchos::RCP< Teuchos::StackedTimer > getStackedTimer()
The StackedTimer used by the TimeMonitor.
static ETimeMonitorReportFormat reportFormat_
Parameters for the report() class method.
static void enableTimer(const std::string &name)
Enable the timer with the given name.
static void zeroOutTimers()
Reset all global timers to zero.
static void setStackedTimer(const Teuchos::RCP< Teuchos::StackedTimer > &t)
Sets the StackedTimer into which the TimeMonitor will insert timings.
static void report(Ptr< const Comm< int > > comm, std::ostream &out, const std::string &filter, const RCP< ParameterList > ¶ms=null)
Report timer statistics to the given output stream.
static bool writeZeroTimers_
Whether report() should report timers with zero call counts.
static void summarize(Ptr< const Comm< int > > comm, std::ostream &out=std::cout, const bool alwaysWriteLocal=false, const bool writeGlobalStats=true, const bool writeZeroTimers=true, const ECounterSetOp setOp=Intersection, const std::string &filter="", const bool ignoreZeroTimers=false)
Print summary statistics for all timers on the given communicator.
static Teuchos::RCP< Teuchos::StackedTimer > stackedTimer_
Stacked timer for optional injection of timing from TimeMonitor-enabled objects.
static bool writeGlobalStats_
Whether report() should always compute global timer statistics.
static RCP< const ParameterList > getValidReportParameters()
Default parameters (with validators) for report().
static ECounterSetOp setOp_
Whether report() should use the intersection or union of timers over (MPI) processes.
static ETimeMonitorYamlFormat yamlStyle_
Current output style for report(), when using YAML output.
static void disableTimer(const std::string &name)
Disable the timer with the given name.
static void setReportFormatParameter(ParameterList &plist)
Add the "Report format" parameter to plist.
static bool alwaysWriteLocal_
Whether report() should always report (MPI) Process 0's local timer results.
static void setYamlFormatParameter(ParameterList &plist)
Add the "YAML style" parameter to plist.
TimeMonitor()=delete
Default constructor is deleted, since it would be unsafe.
static bool setParams_
Whether setReportParameters() completed successfully.
Base interface class for user-defined reduction operations for objects that use value semantics.
std::ostream subclass that performs the magic of indenting data sent to an std::ostream object among ...
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
bool nonnull(const std::shared_ptr< T > &p)
Returns true if p.get()!=NULL.
ECounterSetOp
Set operation type for mergeCounterNames() to perform.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
std::map< std::string, std::pair< double, int > > timer_map_t
void mergeCounterNames(const Comm< int > &comm, const Array< std::string > &localNames, Array< std::string > &globalNames, const ECounterSetOp setOp)
Merge counter names over all processors.
std::map< std::string, std::vector< std::pair< double, double > > > stat_map_type
Global statistics collected from timer data.
This structure defines some basic traits for a scalar field type.
static T zero()
Returns representation of zero for this scalar type.