Intel® OpenMP* Runtime Library
 All Classes Functions Variables Typedefs Enumerations Enumerator Modules Pages
kmp_stats_timing.cpp
1 
5 /* <copyright>
6  Copyright (c) 1997-2015 Intel Corporation. All Rights Reserved.
7 
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions
10  are met:
11 
12  * Redistributions of source code must retain the above copyright
13  notice, this list of conditions and the following disclaimer.
14  * Redistributions in binary form must reproduce the above copyright
15  notice, this list of conditions and the following disclaimer in the
16  documentation and/or other materials provided with the distribution.
17  * Neither the name of Intel Corporation nor the names of its
18  contributors may be used to endorse or promote products derived
19  from this software without specific prior written permission.
20 
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 </copyright> */
34 
35 #include <stdlib.h>
36 #include <unistd.h>
37 
38 #include <iostream>
39 #include <iomanip>
40 #include <sstream>
41 
42 #include "kmp_stats_timing.h"
43 
44 using namespace std;
45 
46 #if KMP_OS_LINUX
47 # if KMP_MIC
48 double tsc_tick_count::tick_time()
49 {
50  // pretty bad assumption of 1GHz clock for MIC
51  return 1/((double)1000*1.e6);
52 }
53 # else
54 # include <string.h>
55 // Extract the value from the CPUID information
56 double tsc_tick_count::tick_time()
57 {
58  static double result = 0.0;
59 
60  if (result == 0.0)
61  {
62  int cpuinfo[4];
63  char brand[256];
64 
65  __cpuid(cpuinfo, 0x80000000);
66  memset(brand, 0, sizeof(brand));
67  int ids = cpuinfo[0];
68 
69  for (unsigned int i=2; i<(ids^0x80000000)+2; i++)
70  __cpuid(brand+(i-2)*sizeof(cpuinfo), i | 0x80000000);
71 
72  char * start = &brand[0];
73  for (;*start == ' '; start++)
74  ;
75 
76  char * end = brand + KMP_STRLEN(brand) - 3;
77  uint64_t multiplier;
78 
79  if (*end == 'M') multiplier = 1000LL*1000LL;
80  else if (*end == 'G') multiplier = 1000LL*1000LL*1000LL;
81  else if (*end == 'T') multiplier = 1000LL*1000LL*1000LL*1000LL;
82  else
83  {
84  cout << "Error determining multiplier '" << *end << "'\n";
85  exit (-1);
86  }
87  *end = 0;
88  while (*end != ' ') end--;
89  end++;
90 
91  double freq = strtod(end, &start);
92  if (freq == 0.0)
93  {
94  cout << "Error calculating frequency " << end << "\n";
95  exit (-1);
96  }
97 
98  result = ((double)1.0)/(freq * multiplier);
99  }
100  return result;
101 }
102 # endif
103 #endif
104 
105 static bool useSI = true;
106 
107 // Return a formatted string after normalising the value into
108 // engineering style and using a suitable unit prefix (e.g. ms, us, ns).
109 std::string formatSI(double interval, int width, char unit)
110 {
111  std::stringstream os;
112 
113  if (useSI)
114  {
115  // Preserve accuracy for small numbers, since we only multiply and the positive powers
116  // of ten are precisely representable.
117  static struct { double scale; char prefix; } ranges[] = {
118  {1.e12,'f'},
119  {1.e9, 'p'},
120  {1.e6, 'n'},
121  {1.e3, 'u'},
122  {1.0, 'm'},
123  {1.e-3,' '},
124  {1.e-6,'k'},
125  {1.e-9,'M'},
126  {1.e-12,'G'},
127  {1.e-15,'T'},
128  {1.e-18,'P'},
129  {1.e-21,'E'},
130  {1.e-24,'Z'},
131  {1.e-27,'Y'}
132  };
133 
134  if (interval == 0.0)
135  {
136  os << std::setw(width-3) << std::right << "0.00" << std::setw(3) << unit;
137  return os.str();
138  }
139 
140  bool negative = false;
141  if (interval < 0.0)
142  {
143  negative = true;
144  interval = -interval;
145  }
146 
147  for (int i=0; i<(int)(sizeof(ranges)/sizeof(ranges[0])); i++)
148  {
149  if (interval*ranges[i].scale < 1.e0)
150  {
151  interval = interval * 1000.e0 * ranges[i].scale;
152  os << std::fixed << std::setprecision(2) << std::setw(width-3) << std::right <<
153  (negative ? -interval : interval) << std::setw(2) << ranges[i].prefix << std::setw(1) << unit;
154 
155  return os.str();
156  }
157  }
158  }
159  os << std::setprecision(2) << std::fixed << std::right << std::setw(width-3) << interval << std::setw(3) << unit;
160 
161  return os.str();
162 }
163 
164 tsc_tick_count::tsc_interval_t computeLastInLastOutInterval(timePair * times, int nTimes)
165 {
166  timePair lastTimes = times[0];
167  tsc_tick_count * startp = lastTimes.get_startp();
168  tsc_tick_count * endp = lastTimes.get_endp();
169 
170  for (int i=1; i<nTimes; i++)
171  {
172  (*startp) = startp->later(times[i].get_start());
173  (*endp) = endp->later (times[i].get_end());
174  }
175 
176  return lastTimes.duration();
177 }
178 
179 std::string timePair::format() const
180 {
181  std::ostringstream oss;
182 
183  oss << start.getValue() << ":" << end.getValue() << " = " << (end-start).getValue();
184 
185  return oss.str();
186 }