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