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>
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
65namespace 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.
Namespace for all elements and tools of MADNESS.
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 d
Definition nonlinschro.cc:121
static const double a
Definition nonlinschro.cc:118
void e()
Definition test_sig.cc:75