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_ */ |