LLVM OpenMP* Runtime Library
kmp_stats_timing.cpp
1 
6 //===----------------------------------------------------------------------===//
7 //
8 // The LLVM Compiler Infrastructure
9 //
10 // This file is dual licensed under the MIT and the University of Illinois Open
11 // Source Licenses. See LICENSE.txt for details.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 
16 #include <stdlib.h>
17 #include <unistd.h>
18 
19 #include <iostream>
20 #include <iomanip>
21 #include <sstream>
22 
23 #include "kmp.h"
24 #include "kmp_stats_timing.h"
25 
26 using namespace std;
27 
28 #if KMP_HAVE_TICK_TIME
29 # if KMP_MIC
30 double tsc_tick_count::tick_time()
31 {
32  // pretty bad assumption of 1GHz clock for MIC
33  return 1/((double)1000*1.e6);
34 }
35 # elif KMP_ARCH_X86 || KMP_ARCH_X86_64
36 # include <string.h>
37 // Extract the value from the CPUID information
38 double tsc_tick_count::tick_time()
39 {
40  static double result = 0.0;
41 
42  if (result == 0.0)
43  {
44  kmp_cpuid_t cpuinfo;
45  char brand[256];
46 
47  __kmp_x86_cpuid(0x80000000, 0, &cpuinfo);
48  memset(brand, 0, sizeof(brand));
49  int ids = cpuinfo.eax;
50 
51  for (unsigned int i=2; i<(ids^0x80000000)+2; i++)
52  __kmp_x86_cpuid(i | 0x80000000, 0, (kmp_cpuid_t*)(brand+(i-2)*sizeof(kmp_cpuid_t)));
53 
54  char * start = &brand[0];
55  for (;*start == ' '; start++)
56  ;
57 
58  char * end = brand + KMP_STRLEN(brand) - 3;
59  uint64_t multiplier;
60 
61  if (*end == 'M') multiplier = 1000LL*1000LL;
62  else if (*end == 'G') multiplier = 1000LL*1000LL*1000LL;
63  else if (*end == 'T') multiplier = 1000LL*1000LL*1000LL*1000LL;
64  else
65  {
66  cout << "Error determining multiplier '" << *end << "'\n";
67  exit (-1);
68  }
69  *end = 0;
70  while (*end != ' ') end--;
71  end++;
72 
73  double freq = strtod(end, &start);
74  if (freq == 0.0)
75  {
76  cout << "Error calculating frequency " << end << "\n";
77  exit (-1);
78  }
79 
80  result = ((double)1.0)/(freq * multiplier);
81  }
82  return result;
83 }
84 # endif
85 #endif
86 
87 static bool useSI = true;
88 
89 // Return a formatted string after normalising the value into
90 // engineering style and using a suitable unit prefix (e.g. ms, us, ns).
91 std::string formatSI(double interval, int width, char unit)
92 {
93  std::stringstream os;
94 
95  if (useSI)
96  {
97  // Preserve accuracy for small numbers, since we only multiply and the positive powers
98  // of ten are precisely representable.
99  static struct { double scale; char prefix; } ranges[] = {
100  {1.e12,'f'},
101  {1.e9, 'p'},
102  {1.e6, 'n'},
103  {1.e3, 'u'},
104  {1.0, 'm'},
105  {1.e-3,' '},
106  {1.e-6,'k'},
107  {1.e-9,'M'},
108  {1.e-12,'G'},
109  {1.e-15,'T'},
110  {1.e-18,'P'},
111  {1.e-21,'E'},
112  {1.e-24,'Z'},
113  {1.e-27,'Y'}
114  };
115 
116  if (interval == 0.0)
117  {
118  os << std::setw(width-3) << std::right << "0.00" << std::setw(3) << unit;
119  return os.str();
120  }
121 
122  bool negative = false;
123  if (interval < 0.0)
124  {
125  negative = true;
126  interval = -interval;
127  }
128 
129  for (int i=0; i<(int)(sizeof(ranges)/sizeof(ranges[0])); i++)
130  {
131  if (interval*ranges[i].scale < 1.e0)
132  {
133  interval = interval * 1000.e0 * ranges[i].scale;
134  os << std::fixed << std::setprecision(2) << std::setw(width-3) << std::right <<
135  (negative ? -interval : interval) << std::setw(2) << ranges[i].prefix << std::setw(1) << unit;
136 
137  return os.str();
138  }
139  }
140  }
141  os << std::setprecision(2) << std::fixed << std::right << std::setw(width-3) << interval << std::setw(3) << unit;
142 
143  return os.str();
144 }
145 
146 tsc_tick_count::tsc_interval_t computeLastInLastOutInterval(timePair * times, int nTimes)
147 {
148  timePair lastTimes = times[0];
149  tsc_tick_count * startp = lastTimes.get_startp();
150  tsc_tick_count * endp = lastTimes.get_endp();
151 
152  for (int i=1; i<nTimes; i++)
153  {
154  (*startp) = startp->later(times[i].get_start());
155  (*endp) = endp->later (times[i].get_end());
156  }
157 
158  return lastTimes.duration();
159 }
160 
161 std::string timePair::format() const
162 {
163  std::ostringstream oss;
164 
165  oss << start.getValue() << ":" << end.getValue() << " = " << (end-start).getValue();
166 
167  return oss.str();
168 }