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