a48bf35aa1c42d69ca54fa6154cf1ac83bc7b036
[alexxy/gromacs.git] / src / gromacs / timing / cyclecounter.c
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 #include "gmxpre.h"
37
38 #include "cyclecounter.h"
39
40 #include <time.h>
41
42 #include "config.h"
43
44 #ifdef HAVE_SYS_TIME_H
45 #include <sys/time.h>
46 #endif
47 #ifdef _MSC_VER
48 #include <windows.h>
49 #endif
50
51 /*! \brief Calculate number of seconds per cycle tick on host
52  *
53  *  This routine runs a timer loop to calibrate the number of
54  *  seconds per the units returned fro gmx_cycles_read().
55  *
56  *  \param  sampletime Minimum real sample time. It takes some trial-and-error
57  *          to find the correct delay loop size, so the total runtime of
58  *          this routine is about twice this time.
59  *  \return Number of seconds per cycle unit. If it is not possible to
60  *          calculate on this system (for whatever reason) the return value
61  *          will be -1, so check that it is positive before using it.
62  */
63 double
64 gmx_cycles_calibrate(double sampletime)
65 {
66 #ifdef _MSC_VER
67
68     /* Windows does not have gettimeofday, but it provides a special
69      * routine that returns the cycle counter frequency.
70      */
71     LARGE_INTEGER i;
72
73     QueryPerformanceFrequency(&i);
74
75     return 1.0/((double) i.QuadPart);
76     /* end of MS Windows implementation */
77
78 #elif (defined HAVE_GETTIMEOFDAY)
79
80     /*  generic implementation with gettimeofday() */
81     struct timeval t1, t2;
82     gmx_cycles_t   c1, c2;
83     double         timediff, cyclediff;
84     double         d = 0.1; /* Dummy variable so we don't optimize away delay loop */
85     int            i;
86
87     if (!gmx_cycles_have_counter())
88     {
89         return -1;
90     }
91
92 #if (defined(__alpha__) || defined(__alpha))
93     /* Alpha cannot count to more than 4e9, but I don't expect
94      * that the architecture will go over 2GHz before it dies, so
95      * up to 2.0 seconds of sampling should be safe.
96      */
97     if (sampletime > 2.0)
98     {
99         sampletime = 2.0;
100     }
101 #endif
102
103     /* Start a timing loop. We want this to be largely independent
104      * of machine speed, so we need to start with a very small number
105      * of iterations and repeat it until we reach the requested time.
106      *
107      * We call gettimeofday an extra time at the start to avoid cache misses.
108      */
109     gettimeofday(&t1, NULL);
110     gettimeofday(&t1, NULL);
111     c1 = gmx_cycles_read();
112
113     do
114     {
115         /* just a delay loop. To avoid optimizing it away, we calculate a number
116          * that will underflow to zero in most cases. By conditionally adding it
117          * to a result at the end it cannot be removed. n=10000 is arbitrary...
118          */
119         for (i = 0; i < 10000; i++)
120         {
121             d = d/(1.0+(double)i);
122         }
123         /* Read the time again */
124         gettimeofday(&t2, NULL);
125         c2       = gmx_cycles_read();
126         timediff = (double)(t2.tv_sec-t1.tv_sec)+
127             (double)(t2.tv_usec-t1.tv_usec)*1e-6;
128     }
129     while (timediff < sampletime);
130
131     cyclediff = c2-c1;
132
133     /* Add a very small result so the delay loop cannot be optimized away */
134     if (d < 1e-30)
135     {
136         timediff += d;
137     }
138
139     /* Return seconds per cycle */
140     return timediff/cyclediff;
141
142 #else
143     /* No timing function available */
144     return -1;
145 #endif
146 }