NEST main@caf0ae8
 
Loading...
Searching...
No Matches
stopwatch.h
Go to the documentation of this file.
1/*
2 * stopwatch.h
3 *
4 * This file is part of NEST.
5 *
6 * Copyright (C) 2004 The NEST Initiative
7 *
8 * NEST is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * NEST is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#ifndef STOPWATCH_H
24#define STOPWATCH_H
25
26// C includes:
27#include <sys/time.h>
28
29// C++ includes:
30#include <chrono>
31#include <iostream>
32#include <vector>
33
34// Includes from libnestutil:
35#include "dictionary.h"
36
37// Includes from nestkernel:
38#include "exceptions.h"
39
40namespace nest
41{
42
43#ifdef TIMER_DETAILED
44constexpr bool use_detailed_timers = true;
45#else
46constexpr bool use_detailed_timers = false;
47#endif
48
49#ifdef THREADED_TIMERS
50constexpr bool use_threaded_timers = true;
51#else
52constexpr bool use_threaded_timers = false;
53#endif
54
56{
57 Normal,
59};
60
62{
65};
66
67/********************************************************************************
68 * Stopwatch *
69 * Accumulates time between start and stop, and provides the elapsed time *
70 * with different time units. Either runs multi-threaded or only on master. *
71 * *
72 * Usage example: *
73 * Stopwatch< StopwatchGranularity::Normal, *
74 * StopwatchParallelism::MasterOnly > x; *
75 * x.start(); *
76 * // ... do computations for 15.34 sec *
77 * x.stop(); // only pauses stopwatch *
78 * x.print("Time needed "); // > Time needed 15.34 sec. *
79 * x.start(); // resumes stopwatch *
80 * // ... next computations for 11.22 sec *
81 * x.stop(); *
82 * x.print("Time needed "); // > Time needed 26,56 sec. *
83 * x.reset(); // reset to default values *
84 * x.start(); // starts the stopwatch from 0 *
85 * // ... computation 5.7 sec *
86 * x.print("Time "); // > Time 5.7 sec. *
87 * // ^ intermediate timing without stopping the stopwatch *
88 * // ... more computations 1.7643 min *
89 * x.stop(); *
90 * x.print("Time needed ", timeunit_t::MINUTES, std::cerr); *
91 * // > Time needed 1,8593 min. (on cerr) *
92 * // other units and output streams possible *
93 ********************************************************************************/
94
95namespace timers
96{
97
98enum class timeunit_t : size_t
99{
100 NANOSEC = 1,
101 MICROSEC = NANOSEC * 1000,
102 MILLISEC = MICROSEC * 1000,
103 SECONDS = MILLISEC * 1000,
104 MINUTES = SECONDS * 60,
105 HOURS = MINUTES * 60,
106 DAYS = HOURS * 24
107};
108
112template < clockid_t clock_type >
114{
115public:
118 {
119 reset();
120 }
121
123 void start();
124
126 void stop();
127
135 double elapsed( timeunit_t timeunit = timeunit_t::SECONDS ) const;
136
138 void reset();
139
141 void
142 print( const std::string& msg = "", timeunit_t timeunit = timeunit_t::SECONDS, std::ostream& os = std::cout ) const;
143
144private:
145 size_t beg_;
146 size_t end_;
149
151 static size_t get_current_time();
152};
153
154template < clockid_t clock_type >
155inline void
157{
158 if ( not is_running_ )
159 {
160 prev_elapsed_ += end_ - beg_; // store prev. time, if we resume
161 end_ = beg_ = get_current_time(); // invariant: end_ >= beg_
162 is_running_ = true; // we start running
163 }
164}
165
166template < clockid_t clock_type >
167inline void
169{
170 if ( is_running_ )
171 {
172 end_ = get_current_time(); // invariant: end_ >= beg_
173 is_running_ = false; // we stopped running
174 }
175}
176
177template < clockid_t clock_type >
178inline double
180{
181 size_t time_elapsed;
182 if ( is_running_ )
183 {
184 // get intermediate elapsed time; do not change end_, to be const
185 time_elapsed = get_current_time() - beg_ + prev_elapsed_;
186 }
187 else
188 {
189 // stopped before, get time of current measurement + last measurements
190 time_elapsed = end_ - beg_ + prev_elapsed_;
191 }
192 return static_cast< double >( time_elapsed ) / static_cast< double >( timeunit );
193}
194
195template < clockid_t clock_type >
196inline void
198{
199 beg_ = 0; // invariant: end_ >= beg_
200 end_ = 0;
201 prev_elapsed_ = 0; // erase all prev. measurements
202 is_running_ = false; // of course not running.
203}
204
205template < clockid_t clock_type >
206inline void
207StopwatchTimer< clock_type >::print( const std::string& msg, timeunit_t timeunit, std::ostream& os ) const
208{
209 os << msg << elapsed( timeunit );
210 switch ( timeunit )
211 {
213 os << " nanosec.";
215 os << " microsec.";
216 break;
218 os << " millisec.";
219 break;
221 os << " sec.";
222 break;
224 os << " min.";
225 break;
227 os << " h.";
228 break;
229 case timeunit_t::DAYS:
230 os << " days.";
231 break;
232 default:
233 throw BadParameter( "Invalid timeunit provided to stopwatch." );
234 }
235 os << std::endl;
236}
237
238template < clockid_t clock_type >
239inline size_t
241{
242 timespec now;
243 clock_gettime( clock_type, &now );
244 return now.tv_nsec + now.tv_sec * static_cast< long >( timeunit_t::SECONDS );
245}
246
247template < clockid_t clock_type >
248inline std::ostream&
249operator<<( std::ostream& os, const StopwatchTimer< clock_type >& stopwatch )
250{
251 stopwatch.print( "", timeunit_t::SECONDS, os );
252 return os;
253}
254
255} // namespace timers
256
258{
259 constexpr void
260 start() noexcept
261 {
262 }
263 constexpr void
264 stop() noexcept
265 {
266 }
267 constexpr void
268 reset() noexcept
269 {
270 }
271 constexpr bool
272 is_running_() const noexcept
273 {
274 return false;
275 }
276 void
277 print( const std::string&, timers::timeunit_t, std::ostream& ) const
278 {
279 }
280 constexpr double
281 elapsed() const noexcept
282 {
283 return std::numeric_limits< double >().quiet_NaN();
284 }
285 constexpr double
286 elapsed( timers::timeunit_t ) const noexcept
287 {
288 return std::numeric_limits< double >().quiet_NaN();
289 }
290};
291
300template < StopwatchGranularity detailed_timer, StopwatchParallelism threaded_timer >
302{
303 static constexpr bool enable_timer = detailed_timer == StopwatchGranularity::Normal or use_detailed_timers;
304 static constexpr bool use_timer_array = threaded_timer == StopwatchParallelism::Threaded and use_threaded_timers;
305
306 // Define StopwatchTimerType< ClockType > depending on timer compilation switches
307 template < clockid_t ClockType >
308 using InternalTimerType = std::conditional_t< use_timer_array,
309 std::vector< timers::StopwatchTimer< ClockType > >,
311 // If enabled, use InternalTimerType, otherwise use NoOpStopwatch.
312 template < clockid_t ClockType >
313 using StopwatchTimerType = std::conditional_t< enable_timer, InternalTimerType< ClockType >, NoOpStopwatch >;
314
315public:
316 void start();
317
318 void stop();
319
320 double elapsed( timers::timeunit_t timeunit = timers::timeunit_t::SECONDS ) const;
321
322 void reset();
323
324 void print( const std::string& msg = "",
326 std::ostream& os = std::cout ) const;
327
328 void get_status( Dictionary& d, const std::string& walltime_name, const std::string& cputime_name ) const;
329
330private:
331 bool is_running_() const;
332
333 // We use a monotonic timer to make sure the stopwatch is not influenced by time jumps (e.g. summer/winter time).
334 // [[no_unique_address]] ensures these take up 0 bytes in case the NoOp version is used.
337};
338
339} /* namespace nest */
340#endif /* STOPWATCH_H */
Dictionary class for interface to Python and C++ API.
Definition dictionary.h:213
Exception to be thrown if a parameter cannot be set.
Definition exceptions.h:717
This template has two template arguments.
Definition stopwatch.h:302
std::conditional_t< enable_timer, InternalTimerType< ClockType >, NoOpStopwatch > StopwatchTimerType
Definition stopwatch.h:313
void reset()
Definition stopwatch_impl.h:190
double elapsed(timers::timeunit_t timeunit=timers::timeunit_t::SECONDS) const
Definition stopwatch_impl.h:110
StopwatchTimerType< CLOCK_THREAD_CPUTIME_ID > cputime_timer_
Definition stopwatch.h:336
static constexpr bool enable_timer
Definition stopwatch.h:303
StopwatchTimerType< CLOCK_MONOTONIC > walltime_timer_
Definition stopwatch.h:335
void stop()
Definition stopwatch_impl.h:63
void print(const std::string &msg="", timers::timeunit_t timeunit=timers::timeunit_t::SECONDS, std::ostream &os=std::cout) const
Definition stopwatch_impl.h:134
void get_status(Dictionary &d, const std::string &walltime_name, const std::string &cputime_name) const
Definition stopwatch_impl.h:157
static constexpr bool use_timer_array
Definition stopwatch.h:304
bool is_running_() const
Definition stopwatch_impl.h:86
std::conditional_t< use_timer_array, std::vector< timers::StopwatchTimer< ClockType > >, timers::StopwatchTimer< ClockType > > InternalTimerType
Definition stopwatch.h:310
void start()
Definition stopwatch_impl.h:36
This class represents a single timer which measures the execution time of a single thread for a given...
Definition stopwatch.h:114
void print(const std::string &msg="", timeunit_t timeunit=timeunit_t::SECONDS, std::ostream &os=std::cout) const
This method prints out the currently elapsed time.
Definition stopwatch.h:207
void start()
Starts or resumes the stopwatch, if it is not running already.
Definition stopwatch.h:156
bool is_running_
true between start() and stop()
Definition stopwatch.h:148
size_t beg_
clock (in ns) at which timer was last started
Definition stopwatch.h:145
void reset()
Resets the stopwatch.
Definition stopwatch.h:197
size_t prev_elapsed_
accumulated time of all start-stop intervals since last reset
Definition stopwatch.h:147
double elapsed(timeunit_t timeunit=timeunit_t::SECONDS) const
Returns the time elapsed between the start and stop of the stopwatch in the given unit.
Definition stopwatch.h:179
void stop()
Stops the stopwatch, if it is not stopped already.
Definition stopwatch.h:168
StopwatchTimer()
Creates a stopwatch that is not running.
Definition stopwatch.h:117
static size_t get_current_time()
Returns current time of clock_type in nanoseconds.
Definition stopwatch.h:240
size_t end_
clock (in ns) at which timer was last stopped (invariant: end_ >= beg_)
Definition stopwatch.h:146
timeunit_t
Definition stopwatch.h:99
std::ostream & operator<<(std::ostream &os, const StopwatchTimer< clock_type > &stopwatch)
Definition stopwatch.h:249
Namespace for the NEST simulation kernel.
Definition beta_normalization_factor.h:33
constexpr bool use_threaded_timers
Definition stopwatch.h:52
constexpr bool use_detailed_timers
Definition stopwatch.h:46
StopwatchParallelism
Definition stopwatch.h:62
@ MasterOnly
Only the master thread owns a stopwatch.
@ Threaded
Every thread measures an individual stopwatch.
StopwatchGranularity
Definition stopwatch.h:56
@ Detailed
Only measure if detailed stopwatches are activated.
@ Normal
Always measure stopwatch.
Definition stopwatch.h:258
void print(const std::string &, timers::timeunit_t, std::ostream &) const
Definition stopwatch.h:277
constexpr double elapsed(timers::timeunit_t) const noexcept
Definition stopwatch.h:286
constexpr void start() noexcept
Definition stopwatch.h:260
constexpr bool is_running_() const noexcept
Definition stopwatch.h:272
constexpr void stop() noexcept
Definition stopwatch.h:264
constexpr double elapsed() const noexcept
Definition stopwatch.h:281
constexpr void reset() noexcept
Definition stopwatch.h:268