Split g96 I/O routines from confio.cpp
[gromacs.git] / src / gromacs / timing / cyclecounter.c
blob780587e11477cca335e5de29aa0139d04aa0088a
1 /*
2 * This file is part of the GROMACS molecular simulation package.
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.
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.
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.
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.
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.
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.
36 #include "gmxpre.h"
38 #include "cyclecounter.h"
40 #include "config.h"
42 #include <time.h>
44 #ifdef HAVE_SYS_TIME_H
45 #include <sys/time.h>
46 #endif
47 #ifdef _MSC_VER
48 #include <windows.h>
49 #endif
51 /*! \brief Calculate number of seconds per cycle tick on host
53 * This routine runs a timer loop to calibrate the number of
54 * seconds per the units returned fro gmx_cycles_read().
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.
63 double
64 gmx_cycles_calibrate(double sampletime)
66 #ifdef _MSC_VER
68 /* Windows does not have gettimeofday, but it provides a special
69 * routine that returns the cycle counter frequency.
71 LARGE_INTEGER i;
73 QueryPerformanceFrequency(&i);
75 return 1.0/((double) i.QuadPart);
76 /* end of MS Windows implementation */
78 #elif (defined HAVE_GETTIMEOFDAY)
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;
87 if (!gmx_cycles_have_counter())
89 return -1;
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.
97 if (sampletime > 2.0)
99 sampletime = 2.0;
101 #endif
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.
107 * We call gettimeofday an extra time at the start to avoid cache misses.
109 gettimeofday(&t1, NULL);
110 gettimeofday(&t1, NULL);
111 c1 = gmx_cycles_read();
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...
119 for (i = 0; i < 10000; i++)
121 d = d/(1.0+(double)i);
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;
129 while (timediff < sampletime);
131 cyclediff = c2-c1;
133 /* Add a very small result so the delay loop cannot be optimized away */
134 if (d < 1e-30)
136 timediff += d;
139 /* Return seconds per cycle */
140 return timediff/cyclediff;
142 #else
143 /* No timing function available */
144 return -1;
145 #endif