xref: /aosp_15_r20/external/eigen/bench/BenchTimer.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2010 Gael Guennebaud <[email protected]>
5 // Copyright (C) 2009 Benoit Jacob <[email protected]>
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 
escape(void * p)30 static void escape(void *p) {
31 #if EIGEN_COMP_GNUC || EIGEN_COMP_CLANG
32   asm volatile("" : : "g"(p) : "memory");
33 #endif
34 }
35 
clobber()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 
BenchTimer()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 
~BenchTimer()73   ~BenchTimer() {}
74 
reset()75   inline void reset()
76   {
77     m_bests.fill(1e9);
78     m_worsts.fill(0);
79     m_totals.setZero();
80   }
start()81   inline void start()
82   {
83     m_starts[CPU_TIMER]  = getCpuTime();
84     m_starts[REAL_TIMER] = getRealTime();
85   }
stop()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 
getCpuTime()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 
getRealTime()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
200