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 33namespace Eigen 34{ 35 36enum { 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 */ 48class BenchTimer 49{ 50public: 51 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 62 ~BenchTimer() {} 63 64 inline void reset() 65 { 66 m_bests.fill(1e9); 67 m_worsts.fill(0); 68 m_totals.setZero(); 69 } 70 inline void start() 71 { 72 m_starts[CPU_TIMER] = getCpuTime(); 73 m_starts[REAL_TIMER] = getRealTime(); 74 } 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 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 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 149protected: 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 159public: 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