Subversion Repositories Games.Chess Giants

Rev

Blame | Last modification | View Log | Download | RSS feed

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