LLVM OpenMP* Runtime Library
kmp_stats_timing.h
1 #ifndef KMP_STATS_TIMING_H
2 #define KMP_STATS_TIMING_H
3 
9 //===----------------------------------------------------------------------===//
10 //
11 // The LLVM Compiler Infrastructure
12 //
13 // This file is dual licensed under the MIT and the University of Illinois Open
14 // Source Licenses. See LICENSE.txt for details.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 
19 
20 #include <stdint.h>
21 #include <string>
22 #include <limits>
23 #include "kmp_os.h"
24 #if KMP_HAVE_X86INTRIN_H
25 # include <x86intrin.h>
26 #endif
27 
28 class tsc_tick_count {
29  private:
30  int64_t my_count;
31 
32  public:
33  class tsc_interval_t {
34  int64_t value;
35  explicit tsc_interval_t(int64_t _value) : value(_value) {}
36  public:
37  tsc_interval_t() : value(0) {}; // Construct 0 time duration
38 #if KMP_HAVE_TICK_TIME
39  double seconds() const; // Return the length of a time interval in seconds
40 #endif
41  double ticks() const { return double(value); }
42  int64_t getValue() const { return value; }
43  tsc_interval_t& operator=(int64_t nvalue) { value = nvalue; return *this; }
44 
45  friend class tsc_tick_count;
46 
47  friend tsc_interval_t operator-(const tsc_tick_count& t1,
48  const tsc_tick_count& t0);
49  friend tsc_interval_t operator-(const tsc_tick_count::tsc_interval_t& i1,
50  const tsc_tick_count::tsc_interval_t& i0);
51  friend tsc_interval_t& operator+=(tsc_tick_count::tsc_interval_t& i1,
52  const tsc_tick_count::tsc_interval_t& i0);
53  };
54 
55 #if KMP_HAVE___BUILTIN_READCYCLECOUNTER
56  tsc_tick_count() : my_count(static_cast<int64_t>(__builtin_readcyclecounter())) {}
57 #elif KMP_HAVE___RDTSC
58  tsc_tick_count() : my_count(static_cast<int64_t>(__rdtsc())) {};
59 #else
60 # error Must have high resolution timer defined
61 #endif
62  tsc_tick_count(int64_t value) : my_count(value) {};
63  int64_t getValue() const { return my_count; }
64  tsc_tick_count later (tsc_tick_count const other) const {
65  return my_count > other.my_count ? (*this) : other;
66  }
67  tsc_tick_count earlier(tsc_tick_count const other) const {
68  return my_count < other.my_count ? (*this) : other;
69  }
70 #if KMP_HAVE_TICK_TIME
71  static double tick_time(); // returns seconds per cycle (period) of clock
72 #endif
73  static tsc_tick_count now() { return tsc_tick_count(); } // returns the rdtsc register value
74  friend tsc_tick_count::tsc_interval_t operator-(const tsc_tick_count& t1, const tsc_tick_count& t0);
75 };
76 
77 inline tsc_tick_count::tsc_interval_t operator-(const tsc_tick_count& t1, const tsc_tick_count& t0)
78 {
79  return tsc_tick_count::tsc_interval_t( t1.my_count-t0.my_count );
80 }
81 
82 inline tsc_tick_count::tsc_interval_t operator-(const tsc_tick_count::tsc_interval_t& i1, const tsc_tick_count::tsc_interval_t& i0)
83 {
84  return tsc_tick_count::tsc_interval_t( i1.value-i0.value );
85 }
86 
87 inline tsc_tick_count::tsc_interval_t& operator+=(tsc_tick_count::tsc_interval_t& i1, const tsc_tick_count::tsc_interval_t& i0)
88 {
89  i1.value += i0.value;
90  return i1;
91 }
92 
93 #if KMP_HAVE_TICK_TIME
94 inline double tsc_tick_count::tsc_interval_t::seconds() const
95 {
96  return value*tick_time();
97 }
98 #endif
99 
100 extern std::string formatSI(double interval, int width, char unit);
101 
102 inline std::string formatSeconds(double interval, int width)
103 {
104  return formatSI(interval, width, 'S');
105 }
106 
107 inline std::string formatTicks(double interval, int width)
108 {
109  return formatSI(interval, width, 'T');
110 }
111 
112 #endif // KMP_STATS_TIMING_H