T-SIMD v31.1.0
A C++ template SIMD library
Loading...
Searching...
No Matches
time_measurement.H
1// ===========================================================================
2//
3// functions for time measurement
4//
5// This source code file is part of the following software:
6//
7// - the low-level C++ template SIMD library
8// - the SIMD implementation of the MinWarping and the 2D-Warping methods
9// for local visual homing.
10//
11// The software is provided based on the accompanying license agreement in the
12// file LICENSE.md.
13// The software is provided "as is" without any warranty by the licensor and
14// without any liability of the licensor, and the software may not be
15// distributed by the licensee; see the license agreement for details.
16//
17// (C) Ralf Möller
18// Computer Engineering
19// Faculty of Technology
20// Bielefeld University
21// www.ti.uni-bielefeld.de
22//
23// ===========================================================================
24
25// 02. Mar 23 (Jonas Keller): added doxygen documentation
26
27// https://
28// en.wikibooks.org/wiki/C%2B%2B_Programming/Code/Design_Patterns#Factory
29
30#pragma once
31#ifndef TIME_MEASUREMENT_H_
32#define TIME_MEASUREMENT_H_
33
34#include <ctime>
35// 20. Apr 18 (rm): thanks to Benedikt Volkmer
36#include <cassert>
37
38// 20. Sep 22 (Jonas Keller): add clock_gettime replacement implementation for
39// Windows
40// TODO: doesn't differentiate between CLOCK_REALTIME, CLOCK_MONOTONIC and
41// CLOCK_PROCESS_CPUTIME_ID from:
42// https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-libraries/winpthreads/src/clock.c
43#ifdef _WIN32
44#include <errno.h>
45#include <stdint.h>
46// windows.h typedefs PATTERN, which causes a redifinition error in
47// TiltSearchDemo.C
48#define PATTERN something_not_named_PATTERN
49#include <windows.h>
50#undef PATTERN
51// max and min are defined as macros in Windows.h, which causes problems
52#undef max
53#undef min
54
55#define POW10_7 10000000
56#define POW10_9 1000000000
57
58using clockid_t = int;
59
60#define CLOCK_REALTIME 0
61#define CLOCK_MONOTONIC 1
62#define CLOCK_PROCESS_CPUTIME_ID 2
63#define CLOCK_THREAD_CPUTIME_ID 3
64
65/* Number of 100ns-seconds between the beginning of the Windows epoch
66 * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970)
67 */
68#define DELTA_EPOCH_IN_100NS INT64_C(116444736000000000)
69
70static int lc_set_errno(int result)
71{
72 if (result != 0) {
73 errno = result;
74 return -1;
75 }
76 return 0;
77}
78
97int clock_gettime(clockid_t clock_id, struct timespec *tp)
98{
99 uint64_t t;
100 LARGE_INTEGER pf, pc;
101 union {
102 uint64_t u64;
103 FILETIME ft;
104 } ct, et, kt, ut;
105
106 switch (clock_id) {
107 case CLOCK_REALTIME: {
108 GetSystemTimeAsFileTime(&ct.ft);
109 t = ct.u64 - DELTA_EPOCH_IN_100NS;
110 tp->tv_sec = t / POW10_7;
111 tp->tv_nsec = ((int) (t % POW10_7)) * 100;
112
113 return 0;
114 }
115
116 case CLOCK_MONOTONIC: {
117 if (QueryPerformanceFrequency(&pf) == 0) return lc_set_errno(EINVAL);
118
119 if (QueryPerformanceCounter(&pc) == 0) return lc_set_errno(EINVAL);
120
121 tp->tv_sec = pc.QuadPart / pf.QuadPart;
122 tp->tv_nsec =
123 (int) (((pc.QuadPart % pf.QuadPart) * POW10_9 + (pf.QuadPart >> 1)) /
124 pf.QuadPart);
125 if (tp->tv_nsec >= POW10_9) {
126 tp->tv_sec++;
127 tp->tv_nsec -= POW10_9;
128 }
129
130 return 0;
131 }
132
133 case CLOCK_PROCESS_CPUTIME_ID: {
134 if (0 ==
135 GetProcessTimes(GetCurrentProcess(), &ct.ft, &et.ft, &kt.ft, &ut.ft))
136 return lc_set_errno(EINVAL);
137 t = kt.u64 + ut.u64;
138 tp->tv_sec = t / POW10_7;
139 tp->tv_nsec = ((int) (t % POW10_7)) * 100;
140
141 return 0;
142 }
143
144 case CLOCK_THREAD_CPUTIME_ID: {
145 if (0 == GetThreadTimes(GetCurrentThread(), &ct.ft, &et.ft, &kt.ft, &ut.ft))
146 return lc_set_errno(EINVAL);
147 t = kt.u64 + ut.u64;
148 tp->tv_sec = t / POW10_7;
149 tp->tv_nsec = ((int) (t % POW10_7)) * 100;
150
151 return 0;
152 }
153
154 default: break;
155 }
156
157 return lc_set_errno(EINVAL);
158}
159#endif
160
161namespace simd {
162/* long long not supported everywhere
163signed long long
164getTimeUsec()
165{
166 signed long long sec, nsec;
167 struct timespec ts;
168 assert(!clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts));
169 sec = ts.tv_sec;
170 nsec = ts.tv_nsec;
171 return 1000000LL * sec + nsec / 1000LL;
172}
173*/
174
183struct timespec getTimeSpec()
184{
185 struct timespec ts;
186 assert(!clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts));
187 return ts;
188}
189
195struct timespec getTimeSpecMonotonic()
196{
197 struct timespec ts;
198 assert(!clock_gettime(CLOCK_MONOTONIC, &ts));
199 return ts;
200}
201
202// https://www.gnu.org/
203// software/libc/manual/html_node/Calculating-Elapsed-Time.html
204// adapted, computes x - y for timespec instead of timeval
205
214int timespec_subtract(const struct timespec &xx, const struct timespec &yy,
215 struct timespec &result)
216{
217 struct timespec x = xx, y = yy;
218 /* Perform the carry for the later subtraction by updating y. */
219 if (x.tv_nsec < y.tv_nsec) {
220 int nsec = (y.tv_nsec - x.tv_nsec) / 1000000000L + 1;
221 y.tv_nsec -= 1000000000L * nsec;
222 y.tv_sec += nsec;
223 }
224 if (x.tv_nsec - y.tv_nsec > 1000000000L) {
225 int nsec = (x.tv_nsec - y.tv_nsec) / 1000000000L;
226 y.tv_nsec += 1000000000L * nsec;
227 y.tv_sec -= nsec;
228 }
229 /* Compute the time remaining to wait. tv_nsec is certainly positive. */
230 result.tv_sec = x.tv_sec - y.tv_sec;
231 result.tv_nsec = x.tv_nsec - y.tv_nsec;
232 /* Return 1 if result is negative. */
233 return x.tv_sec < y.tv_sec;
234}
235
236// convert to us (intended for results of timespec_subtract!)
237
246double timespec_usec(const struct timespec &x)
247{
248 return 1E6 * x.tv_sec + x.tv_nsec / 1E3;
249}
250
258double timeSpecDiffUsec(const struct timespec &x, const struct timespec &y)
259{
260 struct timespec diff;
261 timespec_subtract(x, y, diff);
262 return timespec_usec(diff);
263}
264
265// 09. Oct 22 (Jonas Keller): added timeSpecDiffNsec
266
267// warning: may overflow if the difference is more than 2 seconds on platforms
268// where long is 32 bits
269
280long int timeSpecDiffNsec(const struct timespec &x, const struct timespec &y)
281{
282 struct timespec diff;
283 timespec_subtract(x, y, diff);
284 return 1000000000L * diff.tv_sec + diff.tv_nsec;
285}
286
287} // namespace simd
288
289#endif
Namespace for T-SIMD.
Definition time_measurement.H:161
int timespec_subtract(const struct timespec &xx, const struct timespec &yy, struct timespec &result)
Subtracts two timespecs.
Definition time_measurement.H:214
double timespec_usec(const struct timespec &x)
Converts a timespec to microseconds. Intended for results of timespec_subtract.
Definition time_measurement.H:246
struct timespec getTimeSpec()
Get the current value of this processes CPU time clock.
Definition time_measurement.H:183
struct timespec getTimeSpecMonotonic()
Get the current value of the system-wide real-time clock.
Definition time_measurement.H:195
long int timeSpecDiffNsec(const struct timespec &x, const struct timespec &y)
Computes the difference between two timespec's in nanoseconds.
Definition time_measurement.H:280
double timeSpecDiffUsec(const struct timespec &x, const struct timespec &y)
Computes the difference between two timespec's in microseconds.
Definition time_measurement.H:258