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 /**
13 * @file timing.h
14 * @brief Utility functions for measuring time
15 *
16 * This module contains some utility functions for measuring the time that
17 * various methods take to execute. To use it, we insert the macro
18 * HELIB_TIMER_START at the beginning of the method(s) that we want to time and
19 * HELIB_TIMER_STOP at the end, then the main program needs to call the function
20 * setTimersOn() to activate the timers and setTimersOff() to pause them.
21 * To obtain the value of a given timer (in seconds), the application can
22 * use the function getTime4func(const char *fncName), and the function
23 * printAllTimers() prints the values of all timers to an output stream.
24 *
25 * Using this method we can have at most one timer per method/function, and
26 * the timer is called by the same name as the function itself (using the
27 * built-in macro \_\_func\_\_). We can also use the "lower level" methods
28 * startFHEtimer(name), stopFHEtimer(name), and resetFHEtimer(name) to add
29 * timers with arbitrary names (not necessarily associated with functions).
30 **/
31 #ifndef HELIB_TIMING_H
32 #define HELIB_TIMING_H
33
34 #include <helib/NumbTh.h>
35 #include <helib/multicore.h>
36
37 namespace helib {
38
39 class FHEtimer;
40 void registerTimer(FHEtimer* timer);
41 unsigned long GetTimerClock();
42
43 //! A simple class to accumulate time
44 class FHEtimer
45 {
46 public:
47 const char* name;
48 const char* loc;
49
50 // THREADS: these need to be atomic
51 HELIB_atomic_ulong counter;
52 HELIB_atomic_long numCalls;
53
FHEtimer(const char * _name,const char * _loc)54 FHEtimer(const char* _name, const char* _loc) :
55 name(_name), loc(_loc), counter(0), numCalls(0)
56 {
57 registerTimer(this);
58 }
59
60 void reset();
61 double getTime() const;
62 long getNumCalls() const;
63 };
64
65 // backward compatibility: timers are always on
setTimersOn()66 inline void setTimersOn() {}
setTimersOff()67 inline void setTimersOff() {}
areTimersOn()68 inline bool areTimersOn() { return true; }
69
70 const FHEtimer* getTimerByName(const char* name);
71
72 void resetAllTimers();
73
74 //! Print the value of all timers to stream
75 void printAllTimers(std::ostream& str = std::cerr);
76
77 // return true if timer was found, false otherwise
78 bool printNamedTimer(std::ostream& str, const char* name);
79
80 //! \cond FALSE (make doxygen ignore these classes)
81 class auto_timer
82 {
83 public:
84 FHEtimer* timer;
85 unsigned long amt;
86 bool running;
87
auto_timer(FHEtimer * _timer)88 auto_timer(FHEtimer* _timer) :
89 timer(_timer), amt(GetTimerClock()), running(true)
90 {}
91
stop()92 void stop()
93 {
94 amt = GetTimerClock() - amt;
95 timer->counter += amt;
96 timer->numCalls++;
97 running = false;
98 }
99
~auto_timer()100 ~auto_timer()
101 {
102 if (running)
103 stop();
104 }
105 };
106 //! \endcond
107
108 // NOTE: the STOP functions below are not really needed,
109 // but are provided for backward compatibility
110
111 #define HELIB_STRINGIFY(x) #x
112 #define HELIB_TOSTRING(x) HELIB_STRINGIFY(x)
113 #define HELIB_AT __FILE__ ":" HELIB_TOSTRING(__LINE__)
114
115 #define HELIB_stringify_aux(s) #s
116 #define HELIB_stringify(s) HELIB_stringify_aux(s)
117
118 #define HELIB_TIMER_START \
119 static helib::FHEtimer _local_timer(__func__, HELIB_AT); \
120 helib::auto_timer _local_auto_timer(&_local_timer)
121
122 #define HELIB_TIMER_STOP _local_auto_timer.stop()
123
124 #define HELIB_NTIMER_START(n) \
125 static helib::FHEtimer _named_local_timer##n(#n, HELIB_AT); \
126 helib::auto_timer _named_local_auto_timer##n(&_named_local_timer##n)
127
128 #define HELIB_NTIMER_STOP(n) _named_local_auto_timer##n.stop();
129
130 } // namespace helib
131
132 #endif // ifndef HELIB_TIMING_H
133