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,2015,2016,2017 by the GROMACS development team.
6 * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
39 #include "cyclecounter.h"
45 #ifdef HAVE_SYS_TIME_H
46 # include <sys/time.h>
52 #include "gromacs/utility/basedefinitions.h"
54 /*! \brief Calculate number of seconds per cycle tick on host
56 * This routine runs a timer loop to calibrate the number of
57 * seconds per the units returned fro gmx_cycles_read().
59 * \param sampletime Minimum real sample time. It takes some trial-and-error
60 * to find the correct delay loop size, so the total runtime of
61 * this routine is about twice this time.
62 * \return Number of seconds per cycle unit. If it is not possible to
63 * calculate on this system (for whatever reason) the return value
64 * will be -1, so check that it is positive before using it.
66 double gmx_cycles_calibrate(double sampletime)
70 /* Windows does not have gettimeofday, but it provides a special
71 * routine that returns the cycle counter frequency.
75 QueryPerformanceFrequency(&i);
77 return 1.0 / static_cast<double>(i.QuadPart);
78 /* end of MS Windows implementation */
80 #elif HAVE_GETTIMEOFDAY
82 /* generic implementation with gettimeofday() */
83 struct timeval t1, t2;
85 double timediff, cyclediff;
86 double d = 0.1; /* Dummy variable so we don't optimize away delay loop */
88 if (!gmx_cycles_have_counter())
93 # if (defined(__alpha__) || defined(__alpha))
94 /* Alpha cannot count to more than 4e9, but I don't expect
95 * that the architecture will go over 2GHz before it dies, so
96 * up to 2.0 seconds of sampling should be safe.
104 /* Start a timing loop. We want this to be largely independent
105 * of machine speed, so we need to start with a very small number
106 * of iterations and repeat it until we reach the requested time.
108 * We call gettimeofday an extra time at the start to avoid cache misses.
110 gettimeofday(&t1, nullptr);
111 gettimeofday(&t1, nullptr);
112 c1 = gmx_cycles_read();
116 /* just a delay loop. To avoid optimizing it away, we calculate a number
117 * that will underflow to zero in most cases. By conditionally adding it
118 * to a result at the end it cannot be removed. n=10000 is arbitrary...
120 for (int i = 0; i < 10000; i++)
122 d = d / (1.0 + static_cast<double>(i));
124 /* Read the time again */
125 gettimeofday(&t2, nullptr);
126 c2 = gmx_cycles_read();
127 timediff = static_cast<double>(t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) * 1e-6;
128 } while (timediff < sampletime);
132 /* Add a very small result so the delay loop cannot be optimized away */
138 /* Return seconds per cycle */
139 return timediff / cyclediff;
142 /* No timing function available */
144 GMX_UNUSED_VALUE(sampletime);