Teuchos - Trilinos Tools Package  Version of the Day
Teuchos_Time.cpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Teuchos: Common Tools Package
5 // Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 // Kris
43 // 07.08.03 -- Move into Teuchos package/namespace
44 
45 #include "Teuchos_Time.hpp"
46 
47 #if defined(__INTEL_COMPILER) && defined(_WIN32)
48 
49 #define WIN32_LEAN_AND_MEAN
50 #include <windows.h>
51 #include <cassert>
52 
53 namespace {
54 
55 bool seconds_initialized = false;
56 LARGE_INTEGER start_count, count_freq; // counts per sec.
57 
58 inline void seconds_initialize() {
59  if( seconds_initialized ) return;
60  std::cout << "\nCalling Win32 version of Teuchos::seconds_initialize()!\n";
61  // Figure out how often the performance counter increments
62  ::QueryPerformanceFrequency( &count_freq );
63  // Set this thread's priority as high as reasonably possible to prevent
64  // timeslice interruptions
65  ::SetThreadPriority( ::GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );
66  // Get the first count.
67  assert( QueryPerformanceCounter( &start_count ) );
68  seconds_initialized = true;
69 }
70 
71 } // end namespace
72 
73 #endif // defined(__INTEL_COMPILER) && defined(_WIN32)
74 
75 #ifdef HAVE_TEUCHOS_TIME_MASSIF_SNAPSHOTS
76 #include <valgrind.h>
77 #include <algorithm>
78 #include <unistd.h>
79 #endif
80 
81 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOSCORE)
82 namespace Kokkos {
83 namespace Profiling {
84 extern void pushRegion (const std::string&);
85 extern void popRegion ();
86 } // namespace Profiling
87 } // namespace Kokkos
88 #endif
89 
90 namespace Teuchos {
91 
92 #ifdef HAVE_TEUCHOS_TIME_MASSIF_SNAPSHOTS
93  void removeIllegalChars(std::string& s){
94  std::string illegalChars = "\\/:?\"<>|";
95  for (auto it = s.begin() ; it < s.end() ; ++it){
96  bool found = illegalChars.find(*it) != std::string::npos;
97  if(found)
98  *it = ' ';
99  }
100  }
101 #endif
102 
103 //=============================================================================
104 Time::Time(const std::string& name_in, bool start_in)
105  : startTime_(0), totalTime_(0), isRunning_(false), enabled_ (true), name_(name_in), numCalls_(0)
106 {
107  if(start_in) this->start();
108 #ifdef HAVE_TEUCHOS_TIME_MASSIF_SNAPSHOTS
109  numCallsMassifSnapshots_ = 0;
110 #endif
111 }
112 
113 void Time::start(bool reset_in)
114 {
115  if (enabled_) {
116  isRunning_ = true;
117  if (reset_in) totalTime_ = 0;
118 #ifdef HAVE_TEUCHOS_TIME_MASSIF_SNAPSHOTS
119  if (numCallsMassifSnapshots_ < 100) {
120  std::string filename = "massif.out." + std::to_string(::getpid()) + "." + name_ + "." + std::to_string(numCallsMassifSnapshots_) + ".start.out";
121  removeIllegalChars(filename);
122  std::replace(filename.begin(), filename.end(), ' ', '_');
123  std::string cmd = "snapshot " + filename;
124  VALGRIND_MONITOR_COMMAND(cmd.data());
125  }
126 #endif
127  startTime_ = wallTime();
128 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOSCORE)
129  ::Kokkos::Profiling::pushRegion (name_);
130 #endif
131  }
132 }
133 
134 double Time::stop()
135 {
136  if (enabled_) {
137  if (isRunning_) {
138  totalTime_ += ( wallTime() - startTime_ );
139  isRunning_ = false;
140  startTime_ = 0;
141 #ifdef HAVE_TEUCHOS_TIME_MASSIF_SNAPSHOTS
142  if (numCallsMassifSnapshots_ < 100) {
143  std::string filename = "massif.out." + std::to_string(::getpid()) + "." + name_ + "." + std::to_string(numCallsMassifSnapshots_) + ".stop.out";
144  removeIllegalChars(filename);
145  std::replace(filename.begin(), filename.end(), ' ', '_');
146  std::string cmd = "snapshot " + filename;
147  VALGRIND_MONITOR_COMMAND(cmd.data());
148  numCallsMassifSnapshots_++;
149  }
150 #endif
151 #if defined(HAVE_TEUCHOS_KOKKOS_PROFILING) && defined(HAVE_TEUCHOSCORE_KOKKOSCORE)
152  ::Kokkos::Profiling::popRegion ();
153 #endif
154  }
155  }
156  return totalTime_;
157 }
158 
159 double Time::totalElapsedTime(bool readCurrentTime) const
160 {
161  if(readCurrentTime)
162  return wallTime() - startTime_ + totalTime_;
163  return totalTime_;
164 }
165 
166 void Time::reset () {
167  totalTime_ = 0;
168  numCalls_ = 0;
169 }
170 
171 void Time::disable () {
172  enabled_ = false;
173 }
174 
175 void Time::enable () {
176  enabled_ = true;
177 }
178 
180  if (enabled_) {
181  ++numCalls_;
182  }
183 }
184 
186 {
187  /* KL: warning: this code is probably not portable! */
188  /* HT: have added some preprocessing to address problem compilers */
189  /* RAB: I modifed so that timer will work if MPI support is compiled in but not initialized */
190 
191 #ifdef HAVE_MPI
192 
193  int mpiInitialized;
194  MPI_Initialized(&mpiInitialized);
195 
196  if( mpiInitialized ) {
197 
198  return(MPI_Wtime());
199 
200  }
201  else {
202 
203  clock_t start;
204 
205  start = clock();
206  return( (double)( start ) / CLOCKS_PER_SEC );
207 
208  }
209 
210 #elif defined(__INTEL_COMPILER) && defined(_WIN32)
211 
212  seconds_initialize();
213  LARGE_INTEGER count;
214  QueryPerformanceCounter( &count );
215  // "QuadPart" is a 64 bit integer (__int64). VC++ supports them!
216  const double
217  sec = (double)( count.QuadPart - start_count.QuadPart ) / count_freq.QuadPart;
218  //std::cout << "ticks = " << ticks << ", sec = " << sec << std::endl;
219  return sec;
220 
221 #elif ICL || defined(_WIN32)
222 
223  clock_t start;
224 
225  start = clock();
226  return( (double)( start ) / CLOCKS_PER_SEC );
227 
228 #else
229 
230 # ifndef MINGW
231  struct timeval tp;
232  static long start = 0, startu;
233  if (!start)
234  {
235  gettimeofday(&tp, NULL);
236  start = tp.tv_sec;
237  startu = tp.tv_usec;
238  return(0.0);
239  }
240  gettimeofday(&tp, NULL);
241  return( ((double) (tp.tv_sec - start)) + (tp.tv_usec-startu)/1000000.0 );
242 # else // MINGW
243  return( (double) clock() / CLOCKS_PER_SEC );
244 # endif // MINGW
245 
246 #endif
247 
248 }
249 
250 } // namespace Teuchos
Basic wall-clock timer class.
void enable()
"Enable" this timer, so that it (again) respects calls to start() and stop().
void incrementNumCalls()
Increment the number of times this timer has been called, if the timer is enabled (see disable()).
double totalElapsedTime(bool readCurrentTime=false) const
The total time in seconds accumulated by this timer.
void reset()
Reset the cummulative time and call count.
void start(bool reset=false)
Start the timer, if the timer is enabled (see disable()).
double stop()
Stop the timer, if the timer is enabled (see disable()).
void disable()
"Disable" this timer, so that it ignores calls to start() and stop().
Time(const std::string &name, bool start=false)
Constructor.
static double wallTime()
Current wall-clock time in seconds.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...