Merge release-5-0 into master
[alexxy/gromacs.git] / src / gromacs / timing / cyclecounter.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2006 David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
5  * Copyright (c) 2013,2014, by the GROMACS development team, led by
6  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7  * and including many others, as listed in the AUTHORS file in the
8  * top-level source directory and at http://www.gromacs.org.
9  *
10  * GROMACS is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * as published by the Free Software Foundation; either version 2.1
13  * of the License, or (at your option) any later version.
14  *
15  * GROMACS is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with GROMACS; if not, see
22  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
24  *
25  * If you want to redistribute modifications to GROMACS, please
26  * consider that scientific software is very special. Version
27  * control is crucial - bugs must be traceable. We will be happy to
28  * consider code for inclusion in the official distribution, but
29  * derived work must not be called official GROMACS. Details are found
30  * in the README & COPYING files - if they are missing, get the
31  * official version at http://www.gromacs.org.
32  *
33  * To help us fund GROMACS development, we humbly ask that you cite
34  * the research papers on the package. Check out http://www.gromacs.org.
35  */
36 /*! \libinternal \file
37  * \brief
38  * High-resolution timestamp or CPU clock cycle counters.
39  *
40  * After reading the current value with gmx_cycles_read() you can add or
41  * subtract these numbers as normal integers of type gmx_cycles_t.
42  *
43  * \inlibraryapi
44  */
45 #ifndef GMX_TIMING_CYCLECOUNTER_H
46 #define GMX_TIMING_CYCLECOUNTER_H
47
48 /*
49  * define HAVE_RDTSCP to use the serializing rdtscp instruction instead of rdtsc.
50  * This is only supported on newer Intel/AMD hardware, but provides better accuracy.
51  */
52 #include "config.h"
53
54 #ifdef _MSC_VER
55 #include <intrin.h>
56 #endif
57
58 #ifdef __cplusplus
59 extern "C"
60 {
61 #endif
62 #if 0
63 } /* fixes auto-indentation problems */
64 #endif
65
66 /* Minor implementation note:
67  *
68  * I like to use these counters in other programs too, so to avoid making
69  * it dependent on other Gromacs definitions I use the #ifdef's to set
70  * architecture-specific inline macros instead of using gmx_inline from
71  * gmx_types.h /Erik 2005-12-10
72  */
73
74 #if ((defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__PATHSCALE__) || defined(__PGIC__)) && \
75     (defined(__i386__) || defined(__x86_64__)))
76 /* x86 or x86-64 with GCC inline assembly */
77 typedef unsigned long long
78     gmx_cycles_t;
79
80 #elif defined(_MSC_VER)
81 #include <windows.h>
82 typedef __int64
83     gmx_cycles_t;
84
85 #elif (defined(__hpux) || defined(__HP_cc)) && defined(__ia64)
86 /* HP compiler on ia64 */
87 #include <machine/sys/inline.h>
88 typedef unsigned long
89     gmx_cycles_t;
90
91 #elif (defined(__INTEL_COMPILER) || defined(__ECC)) && defined(__ia64__)
92 /* Intel compiler on ia64 */
93 #include <ia64intrin.h>
94 typedef unsigned long
95     gmx_cycles_t;
96
97 #elif defined(__GNUC__) && defined(__ia64__)
98 /* ia64 with GCC inline assembly */
99 typedef unsigned long
100     gmx_cycles_t;
101
102 #elif ((defined(__hppa__) || defined(__hppa)) && defined (__GNUC__))
103 /* HP PA-RISC, inline asm with gcc */
104 typedef unsigned long
105     gmx_cycles_t;
106
107 #elif ((defined(__hppa__) || defined(__hppa)) && defined (__hpux))
108 /* HP PA-RISC, instruction when using HP compiler */
109 #include <machine/inline.h>
110 typedef unsigned long
111     gmx_cycles_t;
112
113 #elif defined(__GNUC__) && defined(__s390__)
114 /* S390, taken from FFTW who got it from James Treacy */
115 typedef unsigned long long
116     gmx_cycles_t;
117
118 #elif defined(__GNUC__) && defined(__alpha__)
119 /* gcc inline assembly on alpha CPUs */
120 typedef unsigned long
121     gmx_cycles_t;
122
123 #elif defined(__GNUC__) && defined(__sparc_v9__)
124 /* gcc inline assembly on sparc v9 */
125 typedef unsigned long
126     gmx_cycles_t;
127
128 #elif defined(__DECC) && defined(__alpha)
129 /* Digital GEM C compiler on alpha */
130 #include <c_asm.h>
131 typedef unsigned long
132     gmx_cycles_t;
133
134 #elif (defined(__sgi) && defined(CLOCK_SGI_CYCLE))
135 /* Irix compilers on SGI hardware. Get nanoseconds from struct timespec */
136 typedef unsigned long long
137     gmx_cycles_t;
138
139 #elif (defined(__SVR4) && defined (__SUNPRO_CC))
140 /* Solaris high-resolution timers */
141 typedef hrtime_t
142     gmx_cycles_t;
143
144 #elif defined(__xlC__) && defined (_AIX)
145 /* AIX compilers */
146 #include <sys/time.h>
147 #include <sys/systemcfg.h>
148 typedef unsigned long long
149     gmx_cycles_t;
150
151 #elif ( ( defined(__GNUC__) || defined(__IBM_GCC_ASM) || defined(__IBM_STDCPP_ASM) ) && \
152     ( defined(__powerpc__) || defined(__ppc__) ) )
153 /* PowerPC using gcc inline assembly (also works on xlc>=7.0 with -qasm=gcc) */
154 typedef unsigned long long
155     gmx_cycles_t;
156
157 #elif (defined(__MWERKS__) && (defined(MAC) || defined(macintosh)))
158 /* Metrowerks on macintosh */
159 typedef unsigned long long
160     gmx_cycles_t;
161
162 #elif defined(__sun) && defined(__sparcv9)
163
164 typedef unsigned long
165     gmx_cycles_t;
166
167 #else
168 /*! \brief Integer-like datatype for cycle counter values
169  *
170  *  Depending on your system this will usually be something like long long,
171  *  or a special cycle datatype from the system header files. It is NOT
172  *  necessarily real processor cycles - many systems count in nanoseconds
173  *  or a special external time register at fixed frequency (not the CPU freq.)
174  *
175  *  You can subtract or add gmx_cycle_t types just as normal integers, and if
176  *  you run the calibration routine you can also multiply it with a factor to
177  *  translate the cycle data to seconds.
178  */
179 typedef long
180     gmx_cycles_t;
181
182 #endif
183
184 /*! \brief Check if high-resolution cycle counters are available
185  *
186  *  Not all architectures provide any way to read timestep counters
187  *  in the CPU, and on some it is broken. Although we refer to it
188  *  as cycle counters, it is not necessarily given in units of
189  *  cycles.
190  *
191  *  If you notice that system is missing, implement support for it,
192  *  find out how to detect the system during preprocessing, and send us a
193  *  patch.
194  *
195  *  \return 1 if cycle counters are available, 0 if not.
196  *
197  * \note This functions not need to be in the header for performance
198  *       reasons, but it is very important that we get exactly the
199  *       same detection as for gmx_cycles_read() routines. If you
200  *       compile the library with one compiler, and then use a different
201  *       one when later linking to the library it might happen that the
202  *       library supports cyclecounters but not the headers, or vice versa.
203  */
204 #if ((defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__PATHSCALE__) || defined(__PGIC__) || defined(_CRAYC)) && \
205     (defined(__i386__) || defined(__x86_64__)))
206 static __inline__ int gmx_cycles_have_counter(void)
207 {
208     /* x86 or x86-64 with GCC inline assembly - pentium TSC register */
209     return 1;
210 }
211 #elif (defined(_MSC_VER))
212 static __inline int gmx_cycles_have_counter(void)
213 {
214     return 1;
215 }
216 #elif (defined(__hpux) || defined(__HP_cc)) && defined(__ia64)
217 static inline int gmx_cycles_have_counter(void)
218 {
219     /* HP compiler on ia64, use special instruction to read ITC */
220     return 1;
221 }
222 #elif (defined(__INTEL_COMPILER) || defined(__ECC)) && defined(__ia64__)
223 static __inline__ int gmx_cycles_have_counter(void)
224 {
225     /* Intel compiler on ia64, use special instruction to read ITC */
226     return 1;
227 }
228 #elif defined(__GNUC__) && defined(__ia64__)
229 static __inline__ int gmx_cycles_have_counter(void)
230 {
231     /* AMD64 with GCC inline assembly - TSC register */
232     return 1;
233 }
234 #elif ((defined(__hppa__) || defined(__hppa)) && defined (__GNUC__))
235 static __inline__ int gmx_cycles_have_counter(void)
236 {
237     /* HP PA-RISC, inline asm with gcc */
238     return 1;
239 }
240 #elif ((defined(__hppa__) || defined(__hppa)) && defined (__hpux))
241 static inline int gmx_cycles_have_counter(void)
242 {
243     /* HP PA-RISC, instruction when using HP compiler */
244     return 1;
245 }
246 #elif defined(__GNUC__) && defined(__s390__)
247 static __inline__ int gmx_cycles_have_counter(void)
248 {
249     /* S390, taken from FFTW who got it from James Treacy */
250     return 1;
251 }
252 #elif defined(__GNUC__) && defined(__alpha__)
253 static __inline__ int gmx_cycles_have_counter(void)
254 {
255     /* gcc inline assembly on alpha CPUs */
256     return 1;
257 }
258 #elif defined(__GNUC__) && defined(__sparc_v9__)
259 static __inline__ int gmx_cycles_have_counter(void)
260 {
261     /* gcc inline assembly on sparc v9 */
262     return 1;
263 }
264 #elif defined(__DECC) && defined(__alpha)
265 static __inline int gmx_cycles_have_counter(void)
266 {
267     /* Digital GEM C compiler on alpha */
268     return 1;
269 }
270 #elif (defined(__sgi) && defined(CLOCK_SGI_CYCLE))
271 static __inline int gmx_cycles_have_counter(void)
272 {
273     /* Irix compilers on SGI hardware */
274     return 1;
275 }
276 #elif (defined(__SVR4) && defined (__SUNPRO_CC))
277 static inline int gmx_cycles_have_counter(void)
278 {
279     /* Solaris high-resolution timers */
280     return 1;
281 }
282 #elif defined(__xlC__) && defined (_AIX)
283 static inline int gmx_cycles_have_counter(void)
284 {
285     /* AIX compilers */
286     return 1;
287 }
288 #elif ( ( defined(__GNUC__) || defined(__IBM_GCC_ASM) || defined(__IBM_STDCPP_ASM) ) && \
289     ( defined(__powerpc__) || defined(__ppc__) ) )
290 static __inline__ int gmx_cycles_have_counter(void)
291 {
292     /* PowerPC using gcc inline assembly (and xlc>=7.0 with -qasm=gcc) */
293     return 1;
294 }
295 #elif (defined(__MWERKS__) && (defined(MAC) || defined(macintosh)))
296 static __inline__ int gmx_cycles_have_counter(void)
297 {
298     /* Metrowerks on macintosh */
299     return 1;
300 }
301 #elif defined(__sun) && defined(__sparcv9)
302
303 static __inline__ int gmx_cycles_have_counter(void)
304 {
305     /* Solaris on SPARC*/
306     return 1;
307 }
308 #else
309 static int gmx_cycles_have_counter(void)
310 {
311     /* No cycle counter that we know of on this system */
312     return 0;
313 }
314 #endif
315
316 /*! \brief Read CPU cycle counter
317  *
318  *  This routine returns an abstract datatype containing a
319  *  cycle counter timestamp.
320  *
321  *  \return Opaque data corresponding to a cycle reading.
322  *
323  *  Please note that on most systems it takes several cycles
324  *  to read and return the cycle counters. If you are measuring
325  *  small intervals, you can compensate for this time by calling
326  *  the routine twice and calculating what the difference is.
327  *  Subtract this from your other measurements to get an accurate result.
328  *
329  *  Use gmx_cycles_difference() to get a real number corresponding to
330  *  the difference between two gmx_cycles_t values returned from this
331  *  routine.
332  */
333 #if ((defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__PATHSCALE__) || defined(__PGIC__)) && \
334     (defined(__i386__) || defined(__x86_64__)) && !defined(_CRAYC))
335 static __inline__ gmx_cycles_t gmx_cycles_read(void)
336 {
337     /* x86 with GCC inline assembly - pentium TSC register */
338     gmx_cycles_t   cycle;
339     unsigned       low, high;
340
341 #ifdef HAVE_RDTSCP
342     __asm__ __volatile__("rdtscp" : "=a" (low), "=d" (high) :: "ecx" );
343 #else
344     __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high));
345 #endif
346
347     cycle = ((unsigned long long)low) | (((unsigned long long)high)<<32);
348
349     return cycle;
350 }
351 #elif defined(_MSC_VER)
352 static __inline gmx_cycles_t gmx_cycles_read(void)
353 {
354 #ifdef HAVE_RDTSCP
355     unsigned int ui;
356     return __rdtscp(&ui);
357 #else
358     return __rdtsc();
359 #endif
360 }
361 #elif (defined(__hpux) || defined(__HP_cc)) && defined(__ia64)
362 static inline gmx_cycles_t gmx_cycles_read(void)
363 {
364     /* HP compiler on ia64 */
365     gmx_cycles_t ret;
366     ret = _Asm_mov_from_ar (_AREG_ITC);
367     return ret;
368 }
369 #elif (defined(__INTEL_COMPILER) && defined(__ia64__))
370 static __inline__ gmx_cycles_t gmx_cycles_read(void)
371 {
372     /* Intel compiler on ia64 */
373     return __getReg(_IA64_REG_AR_ITC);
374 }
375 #elif defined(__GNUC__) && defined(__ia64__)
376 static __inline__ gmx_cycles_t gmx_cycles_read(void)
377 {
378     /* ia64 with GCC inline assembly */
379     gmx_cycles_t ret;
380     __asm__ __volatile__ ("mov %0=ar.itc" : "=r" (ret));
381     return ret;
382 }
383 #elif ((defined(__hppa__) || defined(__hppa)) && defined (__GNUC__))
384 static __inline__ gmx_cycles_t gmx_cycles_read(void)
385 {
386     /* HP PA-RISC, inline asm with gcc */
387     gmx_cycles_t ret;
388     __asm__ __volatile__("mfctl 16, %0" : "=r" (ret));
389     /* no input, nothing else clobbered */
390     return ret;
391 }
392 #elif ((defined(__hppa__) || defined(__hppa)) && defined (__hpux))
393 static inline gmx_cycles_t gmx_cycles_read(void)
394 {
395     /* HP PA-RISC, instruction when using HP compiler */
396     gmx_cycles_t ret;
397     _MFCTL(16, ret);
398     return ret;
399 }
400 #elif defined(__GNUC__) && defined(__s390__)
401 static __inline__ gmx_cycles_t gmx_cycles_read(void)
402 {
403     /* S390, taken from FFTW who got it from James Treacy */
404     gmx_cycles_t cycle;
405     __asm__("stck 0(%0)" : : "a" (&(cycle)) : "memory", "cc");
406     return cycle;
407 }
408 #elif defined(__GNUC__) && defined(__alpha__)
409 static __inline__ gmx_cycles_t gmx_cycles_read(void)
410 {
411     /* gcc inline assembly on alpha CPUs */
412     unsigned long cycle;
413     __asm__ __volatile__ ("rpcc %0" : "=r" (cycle));
414     return (cycle & 0xFFFFFFFF);
415 }
416 #elif defined(__GNUC__) && defined(__sparc_v9__)
417 static __inline__ gmx_cycles_t gmx_cycles_read(void)
418 {
419     /* gcc inline assembly on sparc v9 */
420     unsigned long ret;
421     __asm__("rd %%tick, %0" : "=r" (ret));
422     return ret;
423 }
424 #elif defined(__DECC) && defined(__alpha)
425 static __inline gmx_cycles_t gmx_cycles_read(void)
426 {
427     /* Digital GEM C compiler on alpha */
428     unsigned long cycle;
429     cycle = asm ("rpcc %v0");
430     return (cycle & 0xFFFFFFFF);
431 }
432 #elif (defined(__sgi) && defined(CLOCK_SGI_CYCLE))
433 static __inline gmx_cycles_t gmx_cycles_read(void)
434 {
435     /* Irix compilers on SGI hardware */
436     struct timespec t;
437     clock_gettime(CLOCK_SGI_CYCLE, &t);
438     /* Return the number of nanoseconds, so we can subtract/add */
439     return ((unsigned long long)t.tv_sec)*1000000000+
440            (unsigned long long)t.tv_nsec;
441 }
442 #elif (defined(__SVR4) && defined (__SUNPRO_CC))
443 static inline gmx_cycles_t gmx_cycles_read(void)
444 {
445     /* Solaris high-resolution timers */
446     return gethrtime();
447 }
448 #elif defined(__xlC__) && defined (_AIX)
449 static inline gmx_cycles_t gmx_cycles_read(void)
450 {
451     /* AIX compilers. Inline the calculation instead of using library functions */
452     timebasestruct_t t1;
453     read_real_time(&t1, TIMEBASE_SZ);
454     /* POWER returns real time (seconds + nanoseconds),
455      * POWER_PC returns high/low 32 bits of a counter.
456      */
457     if (t1.flag == RTC_POWER_PC)
458     {
459         return ((gmx_cycles_t)t1.tb_high)<<32 | (gmx_cycles_t)t1.tb_low;
460     }
461     else
462     {
463         return ((gmx_cycles_t)t1.tb_high)*1000000000+(gmx_cycles_t)t1.tb_low;
464     }
465 }
466 #elif ( ( defined(__GNUC__) || defined(__IBM_GCC_ASM) || defined(__IBM_STDCPP_ASM) ) && \
467     ( defined(__powerpc__) || defined(__ppc__) ) )
468 static __inline__ gmx_cycles_t gmx_cycles_read(void)
469 {
470     /* PowerPC using gcc inline assembly (and xlC>=7.0 with -qasm=gcc) */
471     unsigned long low, high1, high2;
472     do
473     {
474         __asm__ __volatile__ ("mftbu %0" : "=r" (high1) : );
475         __asm__ __volatile__ ("mftb %0" : "=r" (low) : );
476         __asm__ __volatile__ ("mftbu %0" : "=r" (high2) : );
477     }
478     while (high1 != high2);
479
480     return (((gmx_cycles_t)high2) << 32) | (gmx_cycles_t)low;
481 }
482 #elif (defined(__MWERKS__) && (defined(MAC) || defined(macintosh)))
483 static __inline__ gmx_cycles_t gmx_cycles_read(void)
484 {
485     /* Metrowerks on macintosh */
486     unsigned int long low, high1, high2;
487     do
488     {
489         __asm__ __volatile__ ("mftbu %0" : "=r" (high1) : );
490         __asm__ __volatile__ ("mftb %0" : "=r" (low) : );
491         __asm__ __volatile__ ("mftbu %0" : "=r" (high2) : );
492     }
493     while (high1 != high2);
494
495     return (((gmx_cycles_t)high2) << 32) | (gmx_cycles_t)low;
496 }
497 #elif defined(__sun) && defined(__sparcv9)
498
499 static __inline__ gmx_cycles_t gmx_cycles_read(void)
500 {
501     gmx_cycles_t ret;
502     __asm__ __volatile__("rd %%tick, %0" : "=r" (ret));
503     return ret;
504 }
505
506 #elif defined(_CRAYC)
507 #include <intrinsics.h>
508
509 static __inline gmx_cycles_t gmx_cycles_read(void)
510 {
511     return _rtc();
512 }
513 #else
514 static gmx_cycles_t gmx_cycles_read(void)
515 {
516     return 0;
517 }
518 #endif
519
520 /*! \brief Calculate number of seconds per cycle tick on host
521  *
522  *  This routine runs a timer loop to calibrate the number of
523  *  seconds per the units returned fro gmx_cycles_read().
524  *
525  *  \param  sampletime Minimum real sample time. It takes some trial-and-error
526  *          to find the correct delay loop size, so the total runtime of
527  *          this routine is about twice this time.
528  *  \return Number of seconds per cycle unit. If it is not possible to
529  *          calculate on this system (for whatever reason) the return value
530  *          will be -1, so check that it is positive before using it.
531  */
532 double
533 gmx_cycles_calibrate(double sampletime);
534
535 #ifdef __cplusplus
536 }
537 #endif
538
539 #endif