Agora  1.2.0
Agora project
timer.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 #include <cmath>
5 #include <numeric>
6 #include <vector>
7 
9 static inline size_t rdtsc() {
10  uint64_t rax;
11  uint64_t rdx;
12  asm volatile("rdtsc" : "=a"(rax), "=d"(rdx));
13  return static_cast<size_t>((rdx << 32) | rax);
14 }
15 
17 static const auto& dpath_rdtsc = rdtsc;
18 
19 static void nano_sleep(size_t ns, double freq_ghz) {
20  size_t start = rdtsc();
21  size_t end = start;
22  size_t upp = static_cast<size_t>(freq_ghz * ns);
23  while (end - start < upp) end = rdtsc();
24 }
25 
26 static double measure_rdtsc_freq() {
27  struct timespec start, end;
28  clock_gettime(CLOCK_REALTIME, &start);
29  uint64_t rdtsc_start = rdtsc();
30 
31  // Do not change this loop! The hardcoded value below depends on this loop
32  // and prevents it from being optimized out.
33  uint64_t sum = 5;
34  for (uint64_t i = 0; i < 1000000; i++) {
35  sum += i + (sum + i) * (i % sum);
36  }
37 
38  if (sum != 13580802877818827968ull) {
39  std::exit(-1);
40  }
41 
42  clock_gettime(CLOCK_REALTIME, &end);
43  uint64_t clock_ns =
44  static_cast<uint64_t>(end.tv_sec - start.tv_sec) * 1000000000 +
45  static_cast<uint64_t>(end.tv_nsec - start.tv_nsec);
46  uint64_t rdtsc_cycles = rdtsc() - rdtsc_start;
47 
48  double _freq_ghz = rdtsc_cycles * 1.0 / clock_ns;
49  return _freq_ghz;
50 }
51 
53 static double to_sec(size_t cycles, double freq_ghz) {
54  return (cycles / (freq_ghz * 1000000000));
55 }
56 
58 static double to_msec(size_t cycles, double freq_ghz) {
59  return (cycles / (freq_ghz * 1000000));
60 }
61 
63 static double to_usec(size_t cycles, double freq_ghz) {
64  return (cycles / (freq_ghz * 1000));
65 }
66 
67 static size_t us_to_cycles(double us, double freq_ghz) {
68  return static_cast<size_t>(us * 1000 * freq_ghz);
69 }
70 
71 static size_t ns_to_cycles(double ns, double freq_ghz) {
72  return static_cast<size_t>(ns * freq_ghz);
73 }
74 
76 static double to_nsec(size_t cycles, double freq_ghz) {
77  return (cycles / freq_ghz);
78 }
79 
81 static double sec_since(const struct timespec& t0) {
82  struct timespec t1;
83  clock_gettime(CLOCK_REALTIME, &t1);
84  return (t1.tv_sec - t0.tv_sec) + (t1.tv_nsec - t0.tv_nsec) / 1000000000.0;
85 }
86 
88 static double ns_since(const struct timespec& t0) {
89  struct timespec t1;
90  clock_gettime(CLOCK_REALTIME, &t1);
91  return (t1.tv_sec - t0.tv_sec) * 1000000000.0 + (t1.tv_nsec - t0.tv_nsec);
92 }
93 
94 static double stddev(const std::vector<double> in_vec) {
95  if (in_vec.size() == 0) return 0.0;
96  double sum = std::accumulate(in_vec.begin(), in_vec.end(), 0.0);
97  double mean = sum * 1.0 / in_vec.size();
98  double sq_sum =
99  std::inner_product(in_vec.begin(), in_vec.end(), in_vec.begin(), 0.0);
100  return std::sqrt((sq_sum / in_vec.size()) - (mean * mean));
101 }
102 
103 static double mean(const std::vector<double> in_vec) {
104  if (in_vec.empty()) return 0.0;
105  double sum = std::accumulate(in_vec.begin(), in_vec.end(), 0.0);
106  return sum * 1.0 / in_vec.size();
107 }
108 
110 class TscTimer {
111  public:
112  size_t start_tsc = 0;
113  double freq_ghz;
114  std::vector<double> ms_duration_vec;
115 
116  TscTimer(size_t n_timestamps, double freq_ghz) : freq_ghz(freq_ghz) {
117  ms_duration_vec.reserve(n_timestamps);
118  }
119 
120  inline void start() { start_tsc = rdtsc(); }
121  inline void stop() {
123  }
124 
125  void reset() { ms_duration_vec.clear(); }
126  double stddev_msec() { return stddev(ms_duration_vec); }
127  double avg_msec() { return mean(ms_duration_vec); }
128  double avg_usec() { return 1000 * mean(ms_duration_vec); }
129 };
sqrt
2 sqrt()
to_nsec
static double to_nsec(size_t cycles, double freq_ghz)
Convert cycles measured by rdtsc with frequence freq_ghz to nsec.
Definition: timer.h:76
freq_ghz
double freq_ghz
Definition: bench.cc:10
rdtsc
static size_t rdtsc()
Return the TSC.
Definition: timer.h:9
TscTimer::ms_duration_vec
std::vector< double > ms_duration_vec
Definition: timer.h:114
TscTimer::stddev_msec
double stddev_msec()
Definition: timer.h:126
mean
static double mean(const std::vector< double > in_vec)
Definition: timer.h:103
dpath_rdtsc
static const auto & dpath_rdtsc
An alias for rdtsc() to distinguish calls on the critical path.
Definition: timer.h:17
TscTimer::avg_msec
double avg_msec()
Definition: timer.h:127
us_to_cycles
static size_t us_to_cycles(double us, double freq_ghz)
Definition: timer.h:67
TscTimer::start
void start()
Definition: timer.h:120
nano_sleep
static void nano_sleep(size_t ns, double freq_ghz)
Definition: timer.h:19
to_usec
static double to_usec(size_t cycles, double freq_ghz)
Convert cycles measured by rdtsc with frequence freq_ghz to usec.
Definition: timer.h:63
TscTimer::start_tsc
size_t start_tsc
Definition: timer.h:112
TscTimer::stop
void stop()
Definition: timer.h:121
i
for i
Definition: generate_data.m:107
stddev
static double stddev(const std::vector< double > in_vec)
Definition: timer.h:94
ns_since
static double ns_since(const struct timespec &t0)
Return nanoseconds elapsed since timestamp t0.
Definition: timer.h:88
start
end start
Definition: inspect_agora_results.m:95
TscTimer::TscTimer
TscTimer(size_t n_timestamps, double freq_ghz)
Definition: timer.h:116
TscTimer::avg_usec
double avg_usec()
Definition: timer.h:128
TscTimer::freq_ghz
double freq_ghz
Definition: timer.h:113
ns_to_cycles
static size_t ns_to_cycles(double ns, double freq_ghz)
Definition: timer.h:71
to_sec
static double to_sec(size_t cycles, double freq_ghz)
Convert cycles measured by rdtsc with frequence freq_ghz to seconds.
Definition: timer.h:53
TscTimer::reset
void reset()
Definition: timer.h:125
TscTimer
Simple time that uses RDTSC.
Definition: timer.h:110
measure_rdtsc_freq
static double measure_rdtsc_freq()
Definition: timer.h:26
to_msec
static double to_msec(size_t cycles, double freq_ghz)
Convert cycles measured by rdtsc with frequence freq_ghz to msec.
Definition: timer.h:58
sec_since
static double sec_since(const struct timespec &t0)
Return seconds elapsed since timestamp t0.
Definition: timer.h:81
nlohmann::json_v3_11_1NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON::detail2::end
end_tag end(T &&...)