1 /******************************************************************************
2 * Copyright (c) Intel Corporation - All rights reserved. *
3 * This file is part of the LIBXSMM library. *
4 * *
5 * For information on the license, see the LICENSE file. *
6 * Further information: https://github.com/hfp/libxsmm/ *
7 * SPDX-License-Identifier: BSD-3-Clause *
8 ******************************************************************************/
9 /* Hans Pabst (Intel Corp.)
10 ******************************************************************************/
11 #include <libxsmm_timer.h>
12 #include "libxsmm_main.h"
13
14 #if defined(LIBXSMM_OFFLOAD_TARGET)
15 # pragma offload_attribute(push,target(LIBXSMM_OFFLOAD_TARGET))
16 #endif
17 #if defined(_WIN32)
18 # include <Windows.h>
19 #elif defined(__GNUC__) || defined(__PGI) || defined(_CRAYC)
20 # include <sys/time.h>
21 # include <time.h>
22 #endif
23 #if defined(LIBXSMM_OFFLOAD_TARGET)
24 # pragma offload_attribute(pop)
25 #endif
26
27 #if defined(__powerpc64__) && defined(__GLIBC__)
28 # include <sys/platform/ppc.h>
29 #endif
30
31 #if !defined(LIBXSMM_TIMER_TSC)
32 # define LIBXSMM_TIMER_TSC
33 #endif
34 #if !defined(LIBXSMM_TIMER_WPC)
35 # define LIBXSMM_TIMER_WPC
36 #endif
37
38 #if defined(LIBXSMM_TIMER_TSC)
39 # if defined(__powerpc64__)
40 # if defined(__GLIBC__)
41 # define LIBXSMM_TIMER_RDTSC(CYCLE) { \
42 CYCLE = __ppc_get_timebase(); \
43 }
44 # else
45 # define LIBXSMM_TIMER_RDTSC(CYCLE) asm volatile("mfspr %%r3, 268": "=r" (CYCLE));
46 # endif
47 # elif ((defined(__GNUC__) || defined(LIBXSMM_INTEL_COMPILER) || defined(__PGI)) && (64 <= (LIBXSMM_BITS)))
48 # define LIBXSMM_TIMER_RDTSC(CYCLE) { libxsmm_timer_tickint libxsmm_timer_rdtsc_hi_; \
49 __asm__ __volatile__ ("rdtsc" : "=a"(CYCLE), "=d"(libxsmm_timer_rdtsc_hi_)); \
50 CYCLE |= libxsmm_timer_rdtsc_hi_ << 32; \
51 }
52 # elif (defined(_rdtsc) || defined(_WIN32))
53 # define LIBXSMM_TIMER_RDTSC(CYCLE) (CYCLE = __rdtsc())
54 # endif
55 #endif
56
57
libxsmm_timer_duration_rtc(libxsmm_timer_tickint tick0,libxsmm_timer_tickint tick1)58 LIBXSMM_API_INTERN double libxsmm_timer_duration_rtc(libxsmm_timer_tickint tick0, libxsmm_timer_tickint tick1)
59 {
60 double result = (double)LIBXSMM_DELTA(tick0, tick1);
61 #if defined(_WIN32)
62 # if defined(LIBXSMM_TIMER_WPC)
63 LARGE_INTEGER frequency;
64 QueryPerformanceFrequency(&frequency);
65 result /= (double)frequency.QuadPart;
66 # else /* low resolution */
67 result *= 1E-3;
68 # endif
69 #elif defined(CLOCK_MONOTONIC)
70 result *= 1E-9;
71 #else
72 result *= 1E-6;
73 #endif
74 return result;
75 }
76
77
libxsmm_timer_tick_rtc(void)78 LIBXSMM_API_INTERN libxsmm_timer_tickint libxsmm_timer_tick_rtc(void)
79 {
80 libxsmm_timer_tickint result;
81 #if defined(_WIN32)
82 # if defined(LIBXSMM_TIMER_WPC)
83 LARGE_INTEGER t;
84 QueryPerformanceCounter(&t);
85 result = (libxsmm_timer_tickint)t.QuadPart;
86 # else /* low resolution */
87 result = (libxsmm_timer_tickint)GetTickCount64();
88 # endif
89 #elif defined(CLOCK_MONOTONIC)
90 struct timespec t;
91 clock_gettime(CLOCK_MONOTONIC, &t);
92 result = 1000000000ULL * t.tv_sec + t.tv_nsec;
93 #else
94 struct timeval t;
95 gettimeofday(&t, 0);
96 result = 1000000ULL * t.tv_sec + t.tv_usec;
97 #endif
98 return result;
99 }
100
101
LIBXSMM_INTRINSICS(LIBXSMM_X86_GENERIC)102 LIBXSMM_API_INTERN LIBXSMM_INTRINSICS(LIBXSMM_X86_GENERIC)
103 libxsmm_timer_tickint libxsmm_timer_tick_tsc(void)
104 {
105 libxsmm_timer_tickint result;
106 #if defined(LIBXSMM_TIMER_RDTSC)
107 LIBXSMM_TIMER_RDTSC(result);
108 #else
109 result = libxsmm_timer_tick_rtc();
110 #endif
111 return result;
112 }
113
114
libxsmm_get_timer_info(libxsmm_timer_info * info)115 LIBXSMM_API int libxsmm_get_timer_info(libxsmm_timer_info* info)
116 {
117 int result;
118 if (NULL != info) {
119 #if defined(LIBXSMM_TIMER_RDTSC)
120 if (0 < libxsmm_timer_scale) {
121 info->tsc = 1;
122 }
123 # if !defined(LIBXSMM_INIT_COMPLETED)
124 else if (2 > libxsmm_ninit) {
125 libxsmm_init();
126 if (0 < libxsmm_timer_scale) {
127 info->tsc = 1;
128 }
129 else {
130 info->tsc = 0;
131 }
132 }
133 # endif
134 else {
135 info->tsc = 0;
136 }
137 #else
138 info->tsc = 0;
139 #endif
140 result = EXIT_SUCCESS;
141 }
142 else {
143 static int error_once = 0;
144 if (0 != libxsmm_verbosity /* library code is expected to be mute */
145 && 1 == LIBXSMM_ATOMIC_ADD_FETCH(&error_once, 1, LIBXSMM_ATOMIC_RELAXED))
146 {
147 fprintf(stderr, "LIBXSMM ERROR: invalid argument for libxsmm_get_timer_info specified!\n");
148 }
149 result = EXIT_FAILURE;
150 }
151 return result;
152 }
153
154
libxsmm_timer_tick(void)155 LIBXSMM_API libxsmm_timer_tickint libxsmm_timer_tick(void)
156 {
157 libxsmm_timer_tickint result;
158 #if defined(LIBXSMM_TIMER_RDTSC)
159 if (0 < libxsmm_timer_scale) {
160 LIBXSMM_TIMER_RDTSC(result);
161 }
162 # if !defined(LIBXSMM_INIT_COMPLETED)
163 else if (2 > libxsmm_ninit) {
164 libxsmm_init();
165 if (0 < libxsmm_timer_scale) {
166 LIBXSMM_TIMER_RDTSC(result);
167 }
168 else {
169 result = libxsmm_timer_tick_rtc();
170 }
171 }
172 # endif
173 else {
174 result = libxsmm_timer_tick_rtc();
175 }
176 #else
177 result = libxsmm_timer_tick_rtc();
178 #endif
179 return result;
180 }
181
182
libxsmm_timer_duration(libxsmm_timer_tickint tick0,libxsmm_timer_tickint tick1)183 LIBXSMM_API double libxsmm_timer_duration(libxsmm_timer_tickint tick0, libxsmm_timer_tickint tick1)
184 {
185 double result;
186 #if defined(LIBXSMM_TIMER_RDTSC)
187 if (0 < libxsmm_timer_scale) {
188 result = (double)LIBXSMM_DELTA(tick0, tick1) * libxsmm_timer_scale;
189 }
190 else
191 #endif
192 {
193 result = libxsmm_timer_duration_rtc(tick0, tick1);
194 }
195 return result;
196 }
197
198
199 #if defined(LIBXSMM_BUILD) && (!defined(LIBXSMM_NOFORTRAN) || defined(__clang_analyzer__))
200
201 /* implementation provided for Fortran 77 compatibility */
202 LIBXSMM_API void LIBXSMM_FSYMBOL(libxsmm_timer_ncycles)(libxsmm_timer_tickint* /*ncycles*/, const libxsmm_timer_tickint* /*tick0*/, const libxsmm_timer_tickint* /*tick1*/);
LIBXSMM_FSYMBOL(libxsmm_timer_ncycles)203 LIBXSMM_API void LIBXSMM_FSYMBOL(libxsmm_timer_ncycles)(libxsmm_timer_tickint* ncycles, const libxsmm_timer_tickint* tick0, const libxsmm_timer_tickint* tick1)
204 {
205 #if !defined(NDEBUG)
206 static int error_once = 0;
207 if (NULL != ncycles && NULL != tick0 && NULL != tick1)
208 #endif
209 {
210 *ncycles = libxsmm_timer_ncycles(*tick0, *tick1);
211 }
212 #if !defined(NDEBUG)
213 else if (0 != libxsmm_verbosity /* library code is expected to be mute */
214 && 1 == LIBXSMM_ATOMIC_ADD_FETCH(&error_once, 1, LIBXSMM_ATOMIC_RELAXED))
215 {
216 fprintf(stderr, "LIBXSMM ERROR: invalid arguments for libxsmm_timer_ncycles specified!\n");
217 }
218 #endif
219 }
220
221 #endif /*defined(LIBXSMM_BUILD) && (!defined(LIBXSMM_NOFORTRAN) || defined(__clang_analyzer__))*/
222
223