This source file includes following definitions.
- hpctimer_initialize
- hpctimer_finalize
- hpctimer_print_timers
- hpctimer_sanity_check
- hpctimer_wtime
- hpctimer_wtime_gettimeofday
- hpctimer_wtime_tsc
- hpctimer_tsc_initialize
- hpctimer_gettsc
- hpctimer_measure_overhead
- hpctimer_calibrate_sleep
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #include <sys/time.h>
44 #include <unistd.h>
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <strings.h>
49 #include <math.h>
50 #include <inttypes.h>
51
52 #include <mpi.h>
53
54 #include "hpctimer.h"
55
56 #define NELEMS(v) (sizeof(v) / sizeof((v)[0]))
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 #if defined(__GNUC__)
75 # define __inline__ __inline__
76 # define __asm__ __asm__
77 # define __volatile__ __volatile__
78 #elif defined(__SUNPRO_C)
79 # define __inline__ __inline__
80 # define __asm__ __asm__
81 # define __volatile__ __volatile__
82 #endif
83
84 typedef int (*hpctimer_initialize_func_ptr_t)(void);
85 typedef void (*hpctimer_finalize_func_ptr_t)(void);
86 typedef int (*hpctimer_isimplemented_func_ptr_t)(void);
87 typedef double (*hpctimer_wtime_func_ptr_t)(void);
88
89 typedef struct hpctimer {
90 char *name;
91 hpctimer_initialize_func_ptr_t initialize;
92 hpctimer_finalize_func_ptr_t finalize;
93 hpctimer_isimplemented_func_ptr_t isimplemented;
94 hpctimer_wtime_func_ptr_t wtime;
95 } hpctimer_t;
96
97 static uint64_t hpctimer_overhead;
98 static uint64_t hpctimer_freq;
99
100 static double hpctimer_wtime_tsc(void);
101 static int hpctimer_tsc_initialize(void);
102 static __inline__ uint64_t hpctimer_gettsc(void);
103 static uint64_t hpctimer_measure_overhead(void);
104 static uint64_t hpctimer_calibrate_sleep(uint64_t overhead);
105 static double hpctimer_wtime_gettimeofday(void);
106
107
108
109
110 static hpctimer_t hpctimer_timers[] = {
111 {"MPI_Wtime", NULL, NULL, NULL, MPI_Wtime},
112 {"gettimeofday", NULL, NULL, NULL, hpctimer_wtime_gettimeofday},
113 {"tsc", hpctimer_tsc_initialize, NULL, NULL, hpctimer_wtime_tsc}
114 };
115
116 static hpctimer_wtime_func_ptr_t hpctimer_wtime_func_ptr = NULL;
117 static int hpctimer_timer = -1;
118
119
120 int hpctimer_initialize(const char *timername)
121 {
122 hpctimer_wtime_func_ptr = NULL;
123 hpctimer_timer = -1;
124 unsigned int i;
125 for (i = 0; i < NELEMS(hpctimer_timers); i++) {
126 if (hpctimer_timers[i].isimplemented != NULL) {
127 if (!hpctimer_timers[i].isimplemented()) {
128 continue;
129 }
130 }
131 if (strcasecmp(timername, hpctimer_timers[i].name) == 0) {
132 hpctimer_wtime_func_ptr = hpctimer_timers[i].wtime;
133 hpctimer_timer = i;
134 if (hpctimer_timers[i].initialize) {
135 return hpctimer_timers[i].initialize();
136 }
137 return HPCTIMER_SUCCESS;
138 }
139 }
140 return HPCTIMER_FAILURE;
141 }
142
143
144 void hpctimer_finalize(void)
145 {
146 if (hpctimer_timers[hpctimer_timer].finalize) {
147 hpctimer_timers[hpctimer_timer].finalize();
148 }
149 hpctimer_wtime_func_ptr = NULL;
150 }
151
152
153 void hpctimer_print_timers(void)
154 {
155 unsigned int i;
156
157 printf("Supported timers:\n");
158 for (i = 0; i < NELEMS(hpctimer_timers); i++) {
159 if (hpctimer_timers[i].isimplemented != NULL) {
160 if (!hpctimer_timers[i].isimplemented()) {
161 continue;
162 }
163 }
164 printf(" %s\n", hpctimer_timers[i].name);
165 }
166 }
167
168
169
170
171
172 int hpctimer_sanity_check(void)
173 {
174 enum { NTESTS = 4 };
175 double start, stop, currtime, prevtime = 0.0, err = 0.05;
176 int sanity = 1;
177
178 int delay = 0;
179 for (delay = 1; delay < NTESTS; delay++) {
180 start = hpctimer_wtime();
181 sleep(delay);
182 stop = hpctimer_wtime();
183 currtime = stop - start;
184 if (delay > 1) {
185 if (fabs(prevtime - currtime / delay) > prevtime * err) {
186 sanity = 0;
187 }
188
189
190
191
192 }
193 prevtime = currtime / delay;
194 }
195 return sanity;
196 }
197
198
199 double hpctimer_wtime(void)
200 {
201 return hpctimer_wtime_func_ptr();
202 }
203
204
205 static double hpctimer_wtime_gettimeofday(void)
206 {
207 struct timeval tv;
208 gettimeofday(&tv, NULL);
209 return (double)tv.tv_sec + 1E-6 * tv.tv_usec;
210 }
211
212
213
214
215 static double hpctimer_wtime_tsc(void)
216 {
217 return (double)(hpctimer_gettsc() - hpctimer_overhead) / (double)hpctimer_freq;
218 }
219
220
221
222
223
224
225
226 static int hpctimer_tsc_initialize(void)
227 {
228 hpctimer_overhead = hpctimer_measure_overhead();
229 hpctimer_freq = hpctimer_calibrate_sleep(hpctimer_overhead);
230 return HPCTIMER_SUCCESS;
231 }
232
233
234
235
236 static __inline__ uint64_t hpctimer_gettsc(void)
237 {
238 #if defined(__x86_64__)
239 uint32_t low, high;
240 __asm__ __volatile__(
241 "xorl %%eax, %%eax\n"
242 "cpuid\n"
243 ::: "%rax", "%rbx", "%rcx", "%rdx"
244 );
245 __asm__ __volatile__(
246 "rdtsc\n"
247 : "=a" (low), "=d" (high)
248 );
249 return ((uint64_t)high << 32) | low;
250
251 #elif defined(__i386__)
252 uint64_t tsc;
253 __asm__ __volatile__(
254 "xorl %%eax, %%eax\n"
255 "cpuid\n"
256 ::: "%eax", "%ebx", "%ecx", "%edx"
257 );
258 __asm__ __volatile__(
259 "rdtsc\n"
260 : "=A" (tsc)
261 );
262 return tsc;
263 #else
264 # error "Unsupported platform"
265 #endif
266 }
267
268
269 static uint64_t hpctimer_measure_overhead(void)
270 {
271 enum {
272 TSC_OVERHEAD_NTESTS = 10
273 };
274 int i;
275 uint64_t count, overhead = (uint64_t)~0x01;
276
277
278 for (i = 0; i < TSC_OVERHEAD_NTESTS; i++) {
279 count = hpctimer_gettsc();
280 count = hpctimer_gettsc() - count;
281 if (count < overhead) {
282 overhead = count;
283 }
284 }
285 return overhead;
286 }
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320 static uint64_t hpctimer_calibrate_sleep(uint64_t overhead)
321 {
322 uint64_t count;
323 int delay = 3;
324
325 count = hpctimer_gettsc();
326 sleep(delay);
327 count = hpctimer_gettsc() - count - overhead;
328 return count / delay;
329 }
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361