1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr> 5 // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com> 6 // 7 // This Source Code Form is subject to the terms of the Mozilla 8 // Public License v. 2.0. If a copy of the MPL was not distributed 9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 10 11 #ifndef EIGEN_BENCH_TIMERR_H 12 #define EIGEN_BENCH_TIMERR_H 13 14 #if defined(_WIN32) || defined(__CYGWIN__) 15 # ifndef NOMINMAX 16 # define NOMINMAX 17 # define EIGEN_BT_UNDEF_NOMINMAX 18 # endif 19 # ifndef WIN32_LEAN_AND_MEAN 20 # define WIN32_LEAN_AND_MEAN 21 # define EIGEN_BT_UNDEF_WIN32_LEAN_AND_MEAN 22 # endif 23 # include <windows.h> 24 #elif defined(__APPLE__) 25 #include <CoreServices/CoreServices.h> 26 #include <mach/mach_time.h> 27 #else 28 # include <unistd.h> 29 #endif 30 31 #include <Eigen/Core> 32 33 namespace Eigen 34 { 35 36 enum { 37 CPU_TIMER = 0, 38 REAL_TIMER = 1 39 }; 40 41 /** Elapsed time timer keeping the best try. 42 * 43 * On POSIX platforms we use clock_gettime with CLOCK_PROCESS_CPUTIME_ID. 44 * On Windows we use QueryPerformanceCounter 45 * 46 * Important: on linux, you must link with -lrt 47 */ 48 class BenchTimer 49 { 50 public: 51 BenchTimer()52 BenchTimer() 53 { 54 #if defined(_WIN32) || defined(__CYGWIN__) 55 LARGE_INTEGER freq; 56 QueryPerformanceFrequency(&freq); 57 m_frequency = (double)freq.QuadPart; 58 #endif 59 reset(); 60 } 61 ~BenchTimer()62 ~BenchTimer() {} 63 reset()64 inline void reset() 65 { 66 m_bests.fill(1e9); 67 m_worsts.fill(0); 68 m_totals.setZero(); 69 } start()70 inline void start() 71 { 72 m_starts[CPU_TIMER] = getCpuTime(); 73 m_starts[REAL_TIMER] = getRealTime(); 74 } stop()75 inline void stop() 76 { 77 m_times[CPU_TIMER] = getCpuTime() - m_starts[CPU_TIMER]; 78 m_times[REAL_TIMER] = getRealTime() - m_starts[REAL_TIMER]; 79 #if EIGEN_VERSION_AT_LEAST(2,90,0) 80 m_bests = m_bests.cwiseMin(m_times); 81 m_worsts = m_worsts.cwiseMax(m_times); 82 #else 83 m_bests(0) = std::min(m_bests(0),m_times(0)); 84 m_bests(1) = std::min(m_bests(1),m_times(1)); 85 m_worsts(0) = std::max(m_worsts(0),m_times(0)); 86 m_worsts(1) = std::max(m_worsts(1),m_times(1)); 87 #endif 88 m_totals += m_times; 89 } 90 91 /** Return the elapsed time in seconds between the last start/stop pair 92 */ 93 inline double value(int TIMER = CPU_TIMER) const 94 { 95 return m_times[TIMER]; 96 } 97 98 /** Return the best elapsed time in seconds 99 */ 100 inline double best(int TIMER = CPU_TIMER) const 101 { 102 return m_bests[TIMER]; 103 } 104 105 /** Return the worst elapsed time in seconds 106 */ 107 inline double worst(int TIMER = CPU_TIMER) const 108 { 109 return m_worsts[TIMER]; 110 } 111 112 /** Return the total elapsed time in seconds. 113 */ 114 inline double total(int TIMER = CPU_TIMER) const 115 { 116 return m_totals[TIMER]; 117 } 118 getCpuTime()119 inline double getCpuTime() const 120 { 121 #ifdef _WIN32 122 LARGE_INTEGER query_ticks; 123 QueryPerformanceCounter(&query_ticks); 124 return query_ticks.QuadPart/m_frequency; 125 #elif __APPLE__ 126 return double(mach_absolute_time())*1e-9; 127 #else 128 timespec ts; 129 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); 130 return double(ts.tv_sec) + 1e-9 * double(ts.tv_nsec); 131 #endif 132 } 133 getRealTime()134 inline double getRealTime() const 135 { 136 #ifdef _WIN32 137 SYSTEMTIME st; 138 GetSystemTime(&st); 139 return (double)st.wSecond + 1.e-3 * (double)st.wMilliseconds; 140 #elif __APPLE__ 141 return double(mach_absolute_time())*1e-9; 142 #else 143 timespec ts; 144 clock_gettime(CLOCK_REALTIME, &ts); 145 return double(ts.tv_sec) + 1e-9 * double(ts.tv_nsec); 146 #endif 147 } 148 149 protected: 150 #if defined(_WIN32) || defined(__CYGWIN__) 151 double m_frequency; 152 #endif 153 Vector2d m_starts; 154 Vector2d m_times; 155 Vector2d m_bests; 156 Vector2d m_worsts; 157 Vector2d m_totals; 158 159 public: 160 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 161 }; 162 163 #define BENCH(TIMER,TRIES,REP,CODE) { \ 164 TIMER.reset(); \ 165 for(int uglyvarname1=0; uglyvarname1<TRIES; ++uglyvarname1){ \ 166 TIMER.start(); \ 167 for(int uglyvarname2=0; uglyvarname2<REP; ++uglyvarname2){ \ 168 CODE; \ 169 } \ 170 TIMER.stop(); \ 171 } \ 172 } 173 174 } 175 176 // clean #defined tokens 177 #ifdef EIGEN_BT_UNDEF_NOMINMAX 178 # undef EIGEN_BT_UNDEF_NOMINMAX 179 # undef NOMINMAX 180 #endif 181 182 #ifdef EIGEN_BT_UNDEF_WIN32_LEAN_AND_MEAN 183 # undef EIGEN_BT_UNDEF_WIN32_LEAN_AND_MEAN 184 # undef WIN32_LEAN_AND_MEAN 185 #endif 186 187 #endif // EIGEN_BENCH_TIMERR_H 188