1 /** @file kmp_stats_timing.cpp
5 //===----------------------------------------------------------------------===//
7 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8 // See https://llvm.org/LICENSE.txt for license information.
9 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
11 //===----------------------------------------------------------------------===//
21 #include "kmp_stats_timing.h"
25 #if KMP_HAVE_TICK_TIME
27 double tsc_tick_count::tick_time() {
28 // pretty bad assumption of 1GHz clock for MIC
29 return 1 / ((double)1000 * 1.e6
);
31 #elif KMP_ARCH_X86 || KMP_ARCH_X86_64
33 // Extract the value from the CPUID information
34 double tsc_tick_count::tick_time() {
35 static double result
= 0.0;
41 __kmp_x86_cpuid(0x80000000, 0, &cpuinfo
);
42 memset(brand
, 0, sizeof(brand
));
43 int ids
= cpuinfo
.eax
;
45 for (unsigned int i
= 2; i
< (ids
^ 0x80000000) + 2; i
++)
46 __kmp_x86_cpuid(i
| 0x80000000, 0,
47 (kmp_cpuid_t
*)(brand
+ (i
- 2) * sizeof(kmp_cpuid_t
)));
49 char *start
= &brand
[0];
50 for (; *start
== ' '; start
++)
53 char *end
= brand
+ KMP_STRLEN(brand
) - 3;
57 multiplier
= 1000LL * 1000LL;
59 multiplier
= 1000LL * 1000LL * 1000LL;
61 multiplier
= 1000LL * 1000LL * 1000LL * 1000LL;
63 cout
<< "Error determining multiplier '" << *end
<< "'\n";
71 double freq
= strtod(end
, &start
);
73 cout
<< "Error calculating frequency " << end
<< "\n";
77 result
= ((double)1.0) / (freq
* multiplier
);
84 static bool useSI
= true;
86 // Return a formatted string after normalising the value into
87 // engineering style and using a suitable unit prefix (e.g. ms, us, ns).
88 std::string
formatSI(double interval
, int width
, char unit
) {
92 // Preserve accuracy for small numbers, since we only multiply and the
93 // positive powers of ten are precisely representable.
97 } ranges
[] = {{1.e21
, 'y'}, {1.e18
, 'z'}, {1.e15
, 'a'}, {1.e12
, 'f'},
98 {1.e9
, 'p'}, {1.e6
, 'n'}, {1.e3
, 'u'}, {1.0, 'm'},
99 {1.e
-3, ' '}, {1.e
-6, 'k'}, {1.e
-9, 'M'}, {1.e
-12, 'G'},
100 {1.e
-15, 'T'}, {1.e
-18, 'P'}, {1.e
-21, 'E'}, {1.e
-24, 'Z'},
103 if (interval
== 0.0) {
104 os
<< std::setw(width
- 3) << std::right
<< "0.00" << std::setw(3)
109 bool negative
= false;
110 if (interval
< 0.0) {
112 interval
= -interval
;
115 for (int i
= 0; i
< (int)(sizeof(ranges
) / sizeof(ranges
[0])); i
++) {
116 if (interval
* ranges
[i
].scale
< 1.e0
) {
117 interval
= interval
* 1000.e0
* ranges
[i
].scale
;
118 os
<< std::fixed
<< std::setprecision(2) << std::setw(width
- 3)
119 << std::right
<< (negative
? -interval
: interval
) << std::setw(2)
120 << ranges
[i
].prefix
<< std::setw(1) << unit
;
126 os
<< std::setprecision(2) << std::fixed
<< std::right
<< std::setw(width
- 3)
127 << interval
<< std::setw(3) << unit
;