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