aboutsummaryrefslogtreecommitdiff
path: root/Carpet/CycleClock/src/cycle.cc
blob: 265021c9d889ff03551ccfc00fa0bd29d65ffb28 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "cycleclock.h"

#ifdef HAVE_TICK_COUNTER

#include <cctk.h>



// Find a good wall clock timer
#ifdef _OPENMP
#  include <omp.h>
#endif
#ifdef HAVE_CAPABILITY_MPI
#  include <mpi.h>
#endif
#ifdef HAVE_SYS_TIME_H
#  include <sys/time.h>
#endif



static double cycleclock_tick = -1.0; // uninitialised



#ifdef HAVE_SYS_TIME_H
static double get_sys_time()
{
  timeval tp;
  gettimeofday(&tp, NULL);
  return tp.tv_sec + 1.0e-6 * tp.tv_usec;
}
#endif



void measure_tick()
{
  // Make a few warm-up measurements
  getticks();
  getticks();
  getticks();
  
#ifdef _OPENMP
  if (cycleclock_tick < 0.0) {
    // Use omp_get_sys_time to calibrate the timer
    CCTK_INFO("Measuring CycleClock tick via OpenMP...");
    ticks const rstart = getticks();
    double const wstart = omp_get_wtime();
    while (omp_get_wtime() < wstart + 0.1) {
      // do nothing, just wait
    }
    ticks const rend = getticks();
    double const wend = omp_get_wtime();
    cycleclock_tick = (wend - wstart) / elapsed(rend, rstart);
  }
#endif
  
#ifdef HAVE_CAPABILITY_MPI
  if (cycleclock_tick < 0.0) {
    // Use MPI_Wtime to calibrate the timer
    CCTK_INFO("Measuring CycleClock tick via MPI...");
    ticks const rstart = getticks();
    double const wstart = MPI_Wtime();
    while (MPI_Wtime() < wstart + 0.1) {
        // do nothing, just wait
    }
    ticks const rend = getticks();
    double const wend = MPI_Wtime();
    cycleclock_tick = (wend - wstart) / elapsed(rend, rstart);
  }
#endif
  
#ifdef HAVE_SYS_TIME_H
  if (cycleclock_tick < 0.0) {
    // Use gettimeofday to calibrate the timer
    CCTK_INFO("Measuring CycleClock tick via gettimeofday...");
    ticks const rstart = getticks();
    double const wstart = get_sys_time();
    while (get_sys_time() < wstart + 0.1) {
      // do nothing, just wait
    }
    ticks const rend = getticks();
    double const wend = get_sys_time();
    cycleclock_tick = (wend - wstart) / elapsed(rend, rstart);
  }
#endif
  
  if (cycleclock_tick < 0.0) {
    // Give up; just set the time scale to 1
    CCTK_INFO("Could not measure CycleClock tick");
    cycleclock_tick = 1.0;
  }
  
  CCTK_VInfo(CCTK_THORNSTRING,
             "Calibrated CycleClock: %g ns per clock tick (%g GHz)",
             1.0e9 * cycleclock_tick, 1.0e-9 / cycleclock_tick);
}



double seconds_per_tick()
{
  // if (CCTK_BUILTIN_EXPECT(cycleclock_tick < 0.0, false)) {
  //   CCTK_WARN(CCTK_WARN_ALERT,
  //             "Thorn CycleClock has not been activated; the first measurements may be wrong");
  //   measure_tick();
  // }
  return cycleclock_tick;
}

#endif