blob: 8a0dbbe817109329a0e7a49fdc4f8a9afe120634 [file] [log] [blame]
Brian Silverman72890c22015-09-19 14:37:37 -04001// 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__)
Brian Silverman72890c22015-09-19 14:37:37 -040025#include <mach/mach_time.h>
26#else
27# include <unistd.h>
28#endif
29
Austin Schuh189376f2018-12-20 22:11:15 +110030static void escape(void *p) {
Austin Schuhc55b0172022-02-20 17:52:35 -080031#if EIGEN_COMP_GNUC || EIGEN_COMP_CLANG
Austin Schuh189376f2018-12-20 22:11:15 +110032 asm volatile("" : : "g"(p) : "memory");
Austin Schuhc55b0172022-02-20 17:52:35 -080033#endif
Austin Schuh189376f2018-12-20 22:11:15 +110034}
35
36static void clobber() {
Austin Schuhc55b0172022-02-20 17:52:35 -080037#if EIGEN_COMP_GNUC || EIGEN_COMP_CLANG
Austin Schuh189376f2018-12-20 22:11:15 +110038 asm volatile("" : : : "memory");
Austin Schuhc55b0172022-02-20 17:52:35 -080039#endif
Austin Schuh189376f2018-12-20 22:11:15 +110040}
41
Brian Silverman72890c22015-09-19 14:37:37 -040042#include <Eigen/Core>
43
44namespace Eigen
45{
46
47enum {
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 */
59class BenchTimer
60{
61public:
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
160protected:
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
170public:
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(); \
Austin Schuh189376f2018-12-20 22:11:15 +1100182 clobber(); \
Brian Silverman72890c22015-09-19 14:37:37 -0400183 } \
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