1 /* Copyright (C) 2012-2020 IBM Corp.
2 * This program is Licensed under the Apache License, Version 2.0
3 * (the "License"); you may not use this file except in compliance
4 * with the License. You may obtain a copy of the License at
5 * http://www.apache.org/licenses/LICENSE-2.0
6 * Unless required by applicable law or agreed to in writing, software
7 * distributed under the License is distributed on an "AS IS" BASIS,
8 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 * See the License for the specific language governing permissions and
10 * limitations under the License. See accompanying LICENSE file.
11 */
12 #include <algorithm>
13 #include <utility>
14 #include <cstring>
15 #include <ctime>
16 #include <helib/timing.h>
17
18 namespace helib {
19
20 #ifdef CLOCK_MONOTONIC
GetTimerClock()21 unsigned long GetTimerClock()
22 {
23 timespec ts;
24
25 clock_gettime(CLOCK_MONOTONIC, &ts);
26 // clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
27 // clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
28
29 return ((unsigned long)ts.tv_sec) * 1000000UL +
30 ((unsigned long)ts.tv_nsec / 1000);
31 }
32
33 const unsigned long CLOCK_SCALE = 1000000UL;
34
35 #else
36 #warning "using low-resolution clock"
37
38 // NOTE: the clock used by clock_gettime seems to be much higher
39 // resolution than that used by clock.
40
GetTimerClock()41 unsigned long GetTimerClock() { return clock(); }
42
43 const unsigned long CLOCK_SCALE = (unsigned long)CLOCKS_PER_SEC;
44 #endif
45
timer_compare(const FHEtimer * a,const FHEtimer * b)46 bool timer_compare(const FHEtimer* a, const FHEtimer* b)
47 {
48 return strcmp(a->name, b->name) < 0;
49 }
50
51 static std::vector<FHEtimer*> timerMap;
52 static HELIB_MUTEX_TYPE timerMapMx;
53
registerTimer(FHEtimer * timer)54 void registerTimer(FHEtimer* timer)
55 {
56 HELIB_MUTEX_GUARD(timerMapMx);
57 timerMap.push_back(timer);
58 }
59
60 // Reset a timer for some label to zero
reset()61 void FHEtimer::reset()
62 {
63 numCalls = 0;
64 counter = 0;
65 }
66
67 // Read the value of a timer (in seconds)
getTime() const68 double FHEtimer::getTime() const // returns time in seconds
69 {
70 // If the counter is currently counting, add the clock() value
71 return ((double)counter) / CLOCK_SCALE;
72 }
73
74 // Returns number of calls for that timer
getNumCalls() const75 long FHEtimer::getNumCalls() const { return numCalls; }
76
resetAllTimers()77 void resetAllTimers()
78 {
79 for (long i = 0; i < long(timerMap.size()); i++)
80 timerMap[i]->reset();
81 }
82
83 // Print the value of all timers to stream
printAllTimers(std::ostream & str)84 void printAllTimers(std::ostream& str)
85 {
86
87 sort(timerMap.begin(), timerMap.end(), timer_compare);
88
89 for (long i = 0; i < long(timerMap.size()); i++) {
90 const char* name = timerMap[i]->name;
91 const char* loc = timerMap[i]->loc;
92 double t = timerMap[i]->getTime();
93 long n = timerMap[i]->getNumCalls();
94 double ave;
95 if (n > 0) {
96 ave = t / n;
97 } else {
98 continue;
99 }
100
101 str << " " << name << ": " << t << " / " << n << " = " << ave << " ["
102 << loc << "]\n";
103 }
104 }
105
getTimerByName(const char * name)106 const FHEtimer* getTimerByName(const char* name)
107 {
108 for (long i = 0; i < long(timerMap.size()); i++) {
109 if (strcmp(name, timerMap[i]->name) == 0)
110 return timerMap[i];
111 }
112
113 return 0;
114 }
115
printNamedTimer(std::ostream & str,const char * name)116 bool printNamedTimer(std::ostream& str, const char* name)
117 {
118 for (long i = 0; i < long(timerMap.size()); i++) {
119 if (strcmp(name, timerMap[i]->name) == 0) {
120
121 long n = timerMap[i]->getNumCalls();
122 if (n > 0) {
123 double t = timerMap[i]->getTime();
124 double ave = t / n;
125
126 str << " " << name << ": " << t << " / " << n << " = " << ave << " ["
127 << timerMap[i]->loc << "]\n";
128 } else {
129 str << " " << name << " -- [" << timerMap[i]->loc << "]\n";
130 }
131 return true;
132 }
133 }
134 return false;
135 }
136
137 } // namespace helib
138