Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
99 | pmbaty | 1 | /* |
2 | Texel - A UCI chess engine. |
||
3 | Copyright (C) 2013 Peter Ă–sterlund, peterosterlund2@gmail.com |
||
4 | |||
5 | This program is free software: you can redistribute it and/or modify |
||
6 | it under the terms of the GNU General Public License as published by |
||
7 | the Free Software Foundation, either version 3 of the License, or |
||
8 | (at your option) any later version. |
||
9 | |||
10 | This program is distributed in the hope that it will be useful, |
||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
13 | GNU General Public License for more details. |
||
14 | |||
15 | You should have received a copy of the GNU General Public License |
||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
17 | */ |
||
18 | |||
19 | /* |
||
20 | * timeUtil.hpp |
||
21 | * |
||
22 | * Created on: Sep 20, 2013 |
||
23 | * Author: petero |
||
24 | */ |
||
25 | |||
26 | #ifndef TIMEUTIL_HPP_ |
||
27 | #define TIMEUTIL_HPP_ |
||
28 | |||
29 | #include "util.hpp" |
||
30 | |||
31 | #include <array> |
||
32 | #include <cmath> |
||
33 | #include <cassert> |
||
34 | |||
35 | |||
36 | /** Return current wall clock time in milliseconds, starting at some arbitrary point in time. */ |
||
37 | S64 currentTimeMillis(); |
||
38 | |||
39 | /** Return current wall clock time in seconds, starting at some arbitrary point in time. */ |
||
40 | double currentTime(); |
||
41 | |||
42 | |||
43 | |||
44 | /** Class that measures average CPU utilization. */ |
||
45 | class UtilizationTimer { |
||
46 | public: |
||
47 | /** Constructor. All times start at zero. */ |
||
48 | UtilizationTimer(); |
||
49 | |||
50 | /** Reset times to zero. */ |
||
51 | void reset(); |
||
52 | |||
53 | /** Set the current CPU efficiency factor to p. |
||
54 | * A negative p indicates the CPU is idle. */ |
||
55 | void setPUseful(double p); |
||
56 | |||
57 | /** Return elapsed time size last reset, the amount of useful time spent, |
||
58 | * and the amount of time the CPU has been idle. */ |
||
59 | void getStats(double& elapsed, double& useful, double& sleep); |
||
60 | |||
61 | private: |
||
62 | /** Update tElapsed, tUseful, tSleep and increase t0 to current time. */ |
||
63 | void update(); |
||
64 | |||
65 | double t0; // Time stand for last update() |
||
66 | double pUseful; // Current CPU efficiency factor |
||
67 | |||
68 | double tElapsed; // Total elapsed time since reset() |
||
69 | double tUseful; // Total spent useful time |
||
70 | double tSleep; // total idle time. |
||
71 | }; |
||
72 | |||
73 | /** Class that tracks statistics for a set of samples. */ |
||
74 | class SampleStatistics { |
||
75 | public: |
||
76 | /** Constructor. */ |
||
77 | SampleStatistics(); |
||
78 | |||
79 | /** Remove all samples. */ |
||
80 | void reset(); |
||
81 | |||
82 | /** Add a sample. */ |
||
83 | void addSample(double value); |
||
84 | |||
85 | /** Return number of samples. */ |
||
86 | int numSamples() const; |
||
87 | /** Return average sample value. */ |
||
88 | double avg() const; |
||
89 | /** Return standard deviation of samples. */ |
||
90 | double std() const; |
||
91 | |||
92 | /** Add other to *this. */ |
||
93 | SampleStatistics& operator+=(const SampleStatistics& other); |
||
94 | |||
95 | private: |
||
96 | int nSamples; |
||
97 | double sum; |
||
98 | double sqSum; |
||
99 | }; |
||
100 | |||
101 | /** Gather statistics about time samples. */ |
||
102 | class TimeSampleStatistics { |
||
103 | public: |
||
104 | /** Constructor. */ |
||
105 | TimeSampleStatistics(); |
||
106 | |||
107 | /** Start timer. */ |
||
108 | void start(); |
||
109 | |||
110 | /** Stop timer and add elapsed time as a sample. */ |
||
111 | void stop(); |
||
112 | |||
113 | /** Remove all time samples. */ |
||
114 | void reset(); |
||
115 | |||
116 | /** Return true if timer is currently running. */ |
||
117 | bool isStarted() const; |
||
118 | |||
119 | /** Return number of time samples. */ |
||
120 | int numSamples() const; |
||
121 | /** Return average sample time. */ |
||
122 | double avg() const; |
||
123 | /** Return standard deviation of time samples. */ |
||
124 | double std() const; |
||
125 | |||
126 | /** Print to "os", time values displayed in nanoseconds. */ |
||
127 | void printNs(std::ostream& os) const; |
||
128 | |||
129 | private: |
||
130 | double t0; |
||
131 | bool started; |
||
132 | SampleStatistics stats; |
||
133 | }; |
||
134 | |||
135 | /** A fixed size vector of TimeSampleStatistics objects. */ |
||
136 | template <int N> |
||
137 | class TimeSampleStatisticsVector { |
||
138 | private: |
||
139 | std::array<TimeSampleStatistics, N> vec; |
||
140 | |||
141 | public: |
||
142 | TimeSampleStatistics& operator[](int i); |
||
143 | |||
144 | using iterator = typename std::array<TimeSampleStatistics, N>::iterator; |
||
145 | iterator begin(); |
||
146 | iterator end(); |
||
147 | }; |
||
148 | |||
149 | /** Utility function to add a time sample to a TimeSampleStatistics object. |
||
150 | * The sample value is equal to the amount of time this object is in scope. */ |
||
151 | class ScopedTimeSample { |
||
152 | public: |
||
153 | ScopedTimeSample(TimeSampleStatistics& tStat); |
||
154 | ~ScopedTimeSample(); |
||
155 | ScopedTimeSample(ScopedTimeSample&) = delete; |
||
156 | ScopedTimeSample& operator=(const ScopedTimeSample&) = delete; |
||
157 | private: |
||
158 | TimeSampleStatistics& timeStat; |
||
159 | }; |
||
160 | |||
161 | |||
162 | inline |
||
163 | UtilizationTimer::UtilizationTimer() { |
||
164 | reset(); |
||
165 | } |
||
166 | |||
167 | inline void |
||
168 | UtilizationTimer::reset() { |
||
169 | t0 = currentTime(); |
||
170 | pUseful = -1; |
||
171 | tElapsed = 0; |
||
172 | tUseful = 0; |
||
173 | tSleep = 0; |
||
174 | } |
||
175 | |||
176 | inline void |
||
177 | UtilizationTimer::setPUseful(double p) { |
||
178 | update(); |
||
179 | pUseful = p; |
||
180 | } |
||
181 | |||
182 | inline void |
||
183 | UtilizationTimer::getStats(double& elapsed, double& useful, double& sleep) { |
||
184 | update(); |
||
185 | elapsed = tElapsed; |
||
186 | useful = tUseful; |
||
187 | sleep = tSleep; |
||
188 | } |
||
189 | |||
190 | inline void |
||
191 | UtilizationTimer::update() { |
||
192 | double tNow = currentTime(); |
||
193 | double dt = tNow - t0; |
||
194 | tElapsed += dt; |
||
195 | if (pUseful >= 0) |
||
196 | tUseful += dt * pUseful; |
||
197 | else |
||
198 | tSleep += dt; |
||
199 | t0 = tNow; |
||
200 | } |
||
201 | |||
202 | |||
203 | inline |
||
204 | SampleStatistics::SampleStatistics() { |
||
205 | reset(); |
||
206 | } |
||
207 | |||
208 | inline void |
||
209 | SampleStatistics::reset() { |
||
210 | nSamples = 0; |
||
211 | sum = 0.0; |
||
212 | sqSum = 0.0; |
||
213 | } |
||
214 | |||
215 | inline void |
||
216 | SampleStatistics::addSample(double value) { |
||
217 | nSamples++; |
||
218 | sum += value; |
||
219 | sqSum += value * value; |
||
220 | } |
||
221 | |||
222 | inline int |
||
223 | SampleStatistics::numSamples() const { |
||
224 | return nSamples; |
||
225 | } |
||
226 | |||
227 | inline double |
||
228 | SampleStatistics::avg() const { |
||
229 | return nSamples > 0 ? sum / nSamples : 0; |
||
230 | } |
||
231 | |||
232 | inline double |
||
233 | SampleStatistics::std() const { |
||
234 | if (nSamples < 2) |
||
235 | return 0; |
||
236 | return ::sqrt((sqSum - sum*sum / nSamples) / (nSamples - 1)); |
||
237 | } |
||
238 | |||
239 | inline void |
||
240 | TimeSampleStatistics::printNs(std::ostream& os) const { |
||
241 | os << numSamples() |
||
242 | << ' ' << static_cast<int>(avg() * 1e9) |
||
243 | << ' ' << static_cast<int>(std() * 1e9); |
||
244 | } |
||
245 | |||
246 | |||
247 | inline |
||
248 | TimeSampleStatistics::TimeSampleStatistics() { |
||
249 | reset(); |
||
250 | } |
||
251 | |||
252 | inline void |
||
253 | TimeSampleStatistics::start() { |
||
254 | t0 = currentTime(); |
||
255 | started = true; |
||
256 | } |
||
257 | |||
258 | inline void |
||
259 | TimeSampleStatistics::stop() { |
||
260 | double now = currentTime(); |
||
261 | stats.addSample(now - t0); |
||
262 | started = false; |
||
263 | } |
||
264 | |||
265 | inline void |
||
266 | TimeSampleStatistics::reset() { |
||
267 | stats.reset(); |
||
268 | started = false; |
||
269 | } |
||
270 | |||
271 | inline bool |
||
272 | TimeSampleStatistics::isStarted() const { |
||
273 | return started; |
||
274 | } |
||
275 | |||
276 | inline int |
||
277 | TimeSampleStatistics::numSamples() const { |
||
278 | return stats.numSamples(); |
||
279 | } |
||
280 | |||
281 | inline double |
||
282 | TimeSampleStatistics::avg() const { |
||
283 | return stats.avg(); |
||
284 | } |
||
285 | |||
286 | inline double |
||
287 | TimeSampleStatistics::std() const { |
||
288 | return stats.std(); |
||
289 | } |
||
290 | |||
291 | template <int N> |
||
292 | inline TimeSampleStatistics& |
||
293 | TimeSampleStatisticsVector<N>::operator[](int i) { |
||
294 | return vec[i]; |
||
295 | } |
||
296 | |||
297 | template <int N> |
||
298 | inline typename TimeSampleStatisticsVector<N>::iterator |
||
299 | TimeSampleStatisticsVector<N>::begin() { |
||
300 | return vec.begin(); |
||
301 | } |
||
302 | |||
303 | template <int N> |
||
304 | inline typename TimeSampleStatisticsVector<N>::iterator |
||
305 | TimeSampleStatisticsVector<N>::end() { |
||
306 | return vec.end(); |
||
307 | } |
||
308 | |||
309 | |||
310 | inline |
||
311 | ScopedTimeSample::ScopedTimeSample(TimeSampleStatistics& tStat) |
||
312 | : timeStat(tStat) { |
||
313 | assert(!timeStat.isStarted()); |
||
314 | timeStat.start(); |
||
315 | } |
||
316 | |||
317 | inline |
||
318 | ScopedTimeSample::~ScopedTimeSample() { |
||
319 | assert(timeStat.isStarted()); |
||
320 | timeStat.stop(); |
||
321 | } |
||
322 | |||
323 | |||
324 | #endif /* TIMEUTIL_HPP_ */ |