MADNESS  0.10.1
timers.h
Go to the documentation of this file.
1 /*
2  This file is part of MADNESS.
3 
4  Copyright (C) 2007,2010 Oak Ridge National Laboratory
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20  For more information please contact:
21 
22  Robert J. Harrison
23  Oak Ridge National Laboratory
24  One Bethel Valley Road
25  P.O. Box 2008, MS-6367
26 
27  email: harrisonrj@ornl.gov
28  tel: 865-241-3937
29  fax: 865-572-0680
30 */
31 
32 /**
33  \file timers.h
34  \brief Wrappers around platform dependent timers and performance info.
35  \ingroup parallel_runtime
36 */
37 
38 #ifndef MADNESS_WORLD_TIMERS_H__INCLUDED
39 #define MADNESS_WORLD_TIMERS_H__INCLUDED
40 
41 #include <chrono>
42 #include <cstdint>
43 #include <ctime>
44 #include <sys/time.h>
45 #include <unistd.h>
46 #include <madness/madness_config.h>
47 
48 #ifdef _CRAY
49 #include <catamount/dclock.h>
50 #endif
51 
52 #ifdef HAVE_IBMBGP
53 # define BG_CYCLES_PER_MICROSECOND 850
54 # define BG_SECONDS_PER_CYCLE 1.176470588235294033e-09
55 # include </bgsys/drivers/ppcfloor/arch/include/bpcore/ppc450_inlines.h>
56 #endif
57 
58 #ifdef HAVE_IBMBGQ
59 # define BG_CYCLES_PER_MICROSECOND 1600
60 # define BG_SECONDS_PER_CYCLE 6.25e-10
61 # include <hwi/include/bqc/A2_inlines.h>
62 #endif
63 
64 
65 namespace madness {
66 
67  /// Returns the wall time in seconds relative to an arbitrary origin.
68 
69  /// As accurate and lightweight as we can get it, but may not
70  /// be any better than the gettime of day system call.
71  /// \return The wall time (in seconds).
72  double wall_time();
73 
74  /// On some machines we have access to a cycle count.
75 
76  /// For small intervals this is probably the most lightweight and accurate timer
77  /// but may not be meaningful over long intervals due to O/S scheduling,
78  /// migration to different cores, frequency shifts, etc. On x86 uses rtdsc.
79  /// Otherwise uses wall_time() in nanoseconds.
80  /// \return Timing, in cycle count.
81  static inline uint64_t cycle_count() {
82  uint64_t x;
83 #if defined(HAVE_IBMBGP)
84  unsigned int rx, ry, rz;
85  do
86  {
87  asm volatile ( "mftbu %0" : "=r"(rx) );
88  asm volatile ( "mftb %0" : "=r"(ry) );
89  asm volatile ( "mftbu %0" : "=r"(rz) );
90  }
91  while ( rx != rz );
92  x = rx;
93  x = (x << 32) | ry;
94 #elif defined(HAVE_IBMBGQ)
95 /* Jeff could use the asm above but is pretending this is more portable */
96  x = GetTimeBase();
97 #elif defined(X86_32)
98  __asm__ volatile(".byte 0x0f, 0x31" : "=A"(x));
99 #elif defined(X86_64)
100  unsigned int a,d;
101  __asm__ volatile("rdtsc" : "=a"(a), "=d"(d));
102  x = ((uint64_t)a) | (((uint64_t)d)<<32);
103 #else
104  x = wall_time()*1e9;
105 #endif
106  return x;
107  }
108 
109  /// Estimate the processor frequency, in Hz.
110 
111  /// First call may take about 0.1s to execute. Subsequent
112  /// calls return the value, cached from the first call, so it does
113  /// not respond to changing processor frequency.
114  ///
115  /// If \c cycle_count() returns \c wall_time() in nanoseconds,
116  /// this will return 1GHz.
117  ///
118  /// If not available returns 0.
119  /// \return CPU frequency, in Hz.
120  double cpu_frequency();
121 
122  /// Returns the cpu time in seconds relative to an arbitrary origin.
123 
124  /// As accurate and lightweight as we can get it, but may not
125  /// be any better than the clock system call.
126  /// \return The cpu time, in second.
127  static inline double cpu_time() {
128 #if defined(X86_32) || defined(X86_64) || defined(HAVE_IBMBGP)
129  static const double rfreq = 1.0/cpu_frequency();
130  return cycle_count()*rfreq;
131 #elif defined(_CRAY)
132  return dclock();
133 #elif defined(HAVE_IBMBGP)
134  return BG_SECONDS_PER_CYCLE * _bgp_GetTimeBase();
135 #elif defined(HAVE_IBMBGQ)
136  return BG_SECONDS_PER_CYCLE * GetTimeBase();
137 #else
138  const auto now = std::chrono::steady_clock::now();
139  const auto nanoseconds_since_epoch = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
140  return nanoseconds_since_epoch / 1e9;
141 #endif
142  }
143 
144 
145  /// Do nothing and especially do not touch memory.
146 
147  /// \todo Can we provide some context for this function?
148  inline void cpu_relax() {
149 #if defined(X86_32) || defined(X86_64)
150  asm volatile("rep;nop" : : : "memory");
151 #elif defined(HAVE_IBMBGP) || defined(HAVE_IBMBGQ)
152  asm volatile ("nop\n");
153 #else
154  /* Jeff has no idea if this is actually portable.
155  * See https://en.wikipedia.org/wiki/NOP for details. */
156  asm volatile ("nop\n");
157 #endif
158  }
159 
160  /// Sleep or spin for specified number of microseconds.
161 
162  /// Wrapper to ensure desired behavior across various platforms.
163  /// \param[in] us The number of microseconds.
164  static inline void myusleep(unsigned int us) {
165 #if defined(HAVE_CRAYXT)
166  double secs = us*1e-6;
167  double start = cpu_time();
168  while (cpu_time()-start < secs) {
169  for (int i=0; i<100; ++i) cpu_relax();
170  }
171 #elif defined(HAVE_IBMBGP) || defined(HAVE_IBMBGQ)
172  int count = BG_CYCLES_PER_MICROSECOND*us; // ??????
173  for (int i=0; i<count; i++) {
174  asm volatile ("nop\n");
175  }
176 #else
177  usleep(us);
178 #endif
179  }
180 }
181 
182 #endif // MADNESS_WORLD_TIMERS_H__INCLUDED
Macros and tools pertaining to the configuration of MADNESS.
File holds all helper structures necessary for the CC_Operator and CC2 class.
Definition: DFParameters.h:10
static double cpu_time()
Returns the cpu time in seconds relative to an arbitrary origin.
Definition: timers.h:127
static void myusleep(unsigned int us)
Sleep or spin for specified number of microseconds.
Definition: timers.h:164
double cpu_frequency()
Estimate the processor frequency, in Hz.
Definition: timers.cc:79
double wall_time()
Returns the wall time in seconds relative to an arbitrary origin.
Definition: timers.cc:48
void cpu_relax()
Do nothing and especially do not touch memory.
Definition: timers.h:148
static uint64_t cycle_count()
On some machines we have access to a cycle count.
Definition: timers.h:81
static const double a
Definition: nonlinschro.cc:118
void d()
Definition: test_sig.cc:79
void e()
Definition: test_sig.cc:75