BenchTimer.h (4486B)
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 <mach/mach_time.h> 26 #else 27 # include <unistd.h> 28 #endif 29 30 static void escape(void *p) { 31 #if EIGEN_COMP_GNUC || EIGEN_COMP_CLANG 32 asm volatile("" : : "g"(p) : "memory"); 33 #endif 34 } 35 36 static void clobber() { 37 #if EIGEN_COMP_GNUC || EIGEN_COMP_CLANG 38 asm volatile("" : : : "memory"); 39 #endif 40 } 41 42 #include <Eigen/Core> 43 44 namespace Eigen 45 { 46 47 enum { 48 CPU_TIMER = 0, 49 REAL_TIMER = 1 50 }; 51 52 /** Elapsed time timer keeping the best try. 53 * 54 * On POSIX platforms we use clock_gettime with CLOCK_PROCESS_CPUTIME_ID. 55 * On Windows we use QueryPerformanceCounter 56 * 57 * Important: on linux, you must link with -lrt 58 */ 59 class BenchTimer 60 { 61 public: 62 63 BenchTimer() 64 { 65 #if defined(_WIN32) || defined(__CYGWIN__) 66 LARGE_INTEGER freq; 67 QueryPerformanceFrequency(&freq); 68 m_frequency = (double)freq.QuadPart; 69 #endif 70 reset(); 71 } 72 73 ~BenchTimer() {} 74 75 inline void reset() 76 { 77 m_bests.fill(1e9); 78 m_worsts.fill(0); 79 m_totals.setZero(); 80 } 81 inline void start() 82 { 83 m_starts[CPU_TIMER] = getCpuTime(); 84 m_starts[REAL_TIMER] = getRealTime(); 85 } 86 inline void stop() 87 { 88 m_times[CPU_TIMER] = getCpuTime() - m_starts[CPU_TIMER]; 89 m_times[REAL_TIMER] = getRealTime() - m_starts[REAL_TIMER]; 90 #if EIGEN_VERSION_AT_LEAST(2,90,0) 91 m_bests = m_bests.cwiseMin(m_times); 92 m_worsts = m_worsts.cwiseMax(m_times); 93 #else 94 m_bests(0) = std::min(m_bests(0),m_times(0)); 95 m_bests(1) = std::min(m_bests(1),m_times(1)); 96 m_worsts(0) = std::max(m_worsts(0),m_times(0)); 97 m_worsts(1) = std::max(m_worsts(1),m_times(1)); 98 #endif 99 m_totals += m_times; 100 } 101 102 /** Return the elapsed time in seconds between the last start/stop pair 103 */ 104 inline double value(int TIMER = CPU_TIMER) const 105 { 106 return m_times[TIMER]; 107 } 108 109 /** Return the best elapsed time in seconds 110 */ 111 inline double best(int TIMER = CPU_TIMER) const 112 { 113 return m_bests[TIMER]; 114 } 115 116 /** Return the worst elapsed time in seconds 117 */ 118 inline double worst(int TIMER = CPU_TIMER) const 119 { 120 return m_worsts[TIMER]; 121 } 122 123 /** Return the total elapsed time in seconds. 124 */ 125 inline double total(int TIMER = CPU_TIMER) const 126 { 127 return m_totals[TIMER]; 128 } 129 130 inline double getCpuTime() const 131 { 132 #ifdef _WIN32 133 LARGE_INTEGER query_ticks; 134 QueryPerformanceCounter(&query_ticks); 135 return query_ticks.QuadPart/m_frequency; 136 #elif __APPLE__ 137 return double(mach_absolute_time())*1e-9; 138 #else 139 timespec ts; 140 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); 141 return double(ts.tv_sec) + 1e-9 * double(ts.tv_nsec); 142 #endif 143 } 144 145 inline double getRealTime() const 146 { 147 #ifdef _WIN32 148 SYSTEMTIME st; 149 GetSystemTime(&st); 150 return (double)st.wSecond + 1.e-3 * (double)st.wMilliseconds; 151 #elif __APPLE__ 152 return double(mach_absolute_time())*1e-9; 153 #else 154 timespec ts; 155 clock_gettime(CLOCK_REALTIME, &ts); 156 return double(ts.tv_sec) + 1e-9 * double(ts.tv_nsec); 157 #endif 158 } 159 160 protected: 161 #if defined(_WIN32) || defined(__CYGWIN__) 162 double m_frequency; 163 #endif 164 Vector2d m_starts; 165 Vector2d m_times; 166 Vector2d m_bests; 167 Vector2d m_worsts; 168 Vector2d m_totals; 169 170 public: 171 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 172 }; 173 174 #define BENCH(TIMER,TRIES,REP,CODE) { \ 175 TIMER.reset(); \ 176 for(int uglyvarname1=0; uglyvarname1<TRIES; ++uglyvarname1){ \ 177 TIMER.start(); \ 178 for(int uglyvarname2=0; uglyvarname2<REP; ++uglyvarname2){ \ 179 CODE; \ 180 } \ 181 TIMER.stop(); \ 182 clobber(); \ 183 } \ 184 } 185 186 } 187 188 // clean #defined tokens 189 #ifdef EIGEN_BT_UNDEF_NOMINMAX 190 # undef EIGEN_BT_UNDEF_NOMINMAX 191 # undef NOMINMAX 192 #endif 193 194 #ifdef EIGEN_BT_UNDEF_WIN32_LEAN_AND_MEAN 195 # undef EIGEN_BT_UNDEF_WIN32_LEAN_AND_MEAN 196 # undef WIN32_LEAN_AND_MEAN 197 #endif 198 199 #endif // EIGEN_BENCH_TIMERR_H