1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 
5 #ifndef OPENCV_TRACE_PRIVATE_HPP
6 #define OPENCV_TRACE_PRIVATE_HPP
7 
8 #ifdef OPENCV_TRACE
9 
10 #include <opencv2/core/utils/logger.hpp>
11 
12 #include <opencv2/core/utils/tls.hpp>
13 
14 #include "trace.hpp"
15 
16 //! @cond IGNORED
17 
18 #include <deque>
19 #include <ostream>
20 
21 #define INTEL_ITTNOTIFY_API_PRIVATE 1
22 #ifdef OPENCV_WITH_ITT
23 #include "ittnotify.h"
24 #endif
25 
26 #ifndef DEBUG_ONLY
27 #ifdef _DEBUG
28 #define DEBUG_ONLY(...) __VA_ARGS__
29 #else
30 #define DEBUG_ONLY(...) (void)0
31 #endif
32 #endif
33 
34 #ifndef DEBUG_ONLY_
35 #ifdef _DEBUG
36 #define DEBUG_ONLY_(...) __VA_ARGS__
37 #else
38 #define DEBUG_ONLY_(...)
39 #endif
40 #endif
41 
42 
43 namespace cv {
44 namespace utils {
45 namespace trace {
46 namespace details {
47 
48 #define CV__TRACE_OPENCV_FUNCTION_NAME_(name, flags) \
49     CV__TRACE_DEFINE_LOCATION_FN(name, flags); \
50     const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn));
51 
52 
53 enum RegionFlag {
54     REGION_FLAG__NEED_STACK_POP = (1 << 0),
55     REGION_FLAG__ACTIVE = (1 << 1),
56 
57     ENUM_REGION_FLAG_IMPL_FORCE_INT = INT_MAX
58 };
59 
60 
61 class TraceMessage;
62 
63 class TraceStorage {
64 public:
TraceStorage()65     TraceStorage() {}
~TraceStorage()66     virtual ~TraceStorage() {};
67 
68     virtual bool put(const TraceMessage& msg) const = 0;
69 };
70 
71 struct RegionStatistics
72 {
73     int currentSkippedRegions;
74 
75     int64 duration;
76 #ifdef HAVE_IPP
77     int64 durationImplIPP;
78 #endif
79 #ifdef HAVE_OPENCL
80     int64 durationImplOpenCL;
81 #endif
82 #ifdef HAVE_OPENVX
83     int64 durationImplOpenVX;
84 #endif
85 
RegionStatisticscv::utils::trace::details::RegionStatistics86     RegionStatistics() :
87         currentSkippedRegions(0),
88         duration(0)
89 #ifdef HAVE_IPP
90         ,durationImplIPP(0)
91 #endif
92 #ifdef HAVE_OPENCL
93         ,durationImplOpenCL(0)
94 #endif
95 #ifdef HAVE_OPENVX
96         ,durationImplOpenVX(0)
97 #endif
98     {}
99 
grabcv::utils::trace::details::RegionStatistics100     void grab(RegionStatistics& result)
101     {
102         result.currentSkippedRegions = currentSkippedRegions; currentSkippedRegions = 0;
103         result.duration = duration; duration = 0;
104 #ifdef HAVE_IPP
105         result.durationImplIPP = durationImplIPP; durationImplIPP = 0;
106 #endif
107 #ifdef HAVE_OPENCL
108         result.durationImplOpenCL = durationImplOpenCL; durationImplOpenCL = 0;
109 #endif
110 #ifdef HAVE_OPENVX
111         result.durationImplOpenVX = durationImplOpenVX; durationImplOpenVX = 0;
112 #endif
113     }
114 
appendcv::utils::trace::details::RegionStatistics115     void append(RegionStatistics& stat)
116     {
117         currentSkippedRegions += stat.currentSkippedRegions;
118         duration += stat.duration;
119 #ifdef HAVE_IPP
120         durationImplIPP += stat.durationImplIPP;
121 #endif
122 #ifdef HAVE_OPENCL
123         durationImplOpenCL += stat.durationImplOpenCL;
124 #endif
125 #ifdef HAVE_OPENVX
126         durationImplOpenVX += stat.durationImplOpenVX;
127 #endif
128     }
129 
multiplycv::utils::trace::details::RegionStatistics130     void multiply(const float c)
131     {
132         duration = (int64)(duration * c);
133 #ifdef HAVE_IPP
134         durationImplIPP = (int64)(durationImplIPP * c);
135 #endif
136 #ifdef HAVE_OPENCL
137         durationImplOpenCL = (int64)(durationImplOpenCL * c);
138 #endif
139 #ifdef HAVE_OPENVX
140         durationImplOpenVX = (int64)(durationImplOpenVX * c);
141 #endif
142     }
143 };
144 
145 static inline
operator <<(std::ostream & out,const RegionStatistics & stat)146 std::ostream& operator<<(std::ostream& out, const RegionStatistics& stat)
147 {
148     out << "skip=" << stat.currentSkippedRegions
149         << " duration=" << stat.duration
150 #ifdef HAVE_IPP
151         << " durationImplIPP=" << stat.durationImplIPP
152 #endif
153 #ifdef HAVE_OPENCL
154         << " durationImplOpenCL=" << stat.durationImplOpenCL
155 #endif
156 #ifdef HAVE_OPENVX
157         << " durationImplOpenVX=" << stat.durationImplOpenVX
158 #endif
159     ;
160     return out;
161 }
162 
163 struct RegionStatisticsStatus
164 {
165     int _skipDepth;
166 #ifdef HAVE_IPP
167     int ignoreDepthImplIPP;
168 #endif
169 #ifdef HAVE_OPENCL
170     int ignoreDepthImplOpenCL;
171 #endif
172 #ifdef HAVE_OPENVX
173     int ignoreDepthImplOpenVX;
174 #endif
175 
RegionStatisticsStatuscv::utils::trace::details::RegionStatisticsStatus176     RegionStatisticsStatus() { reset(); }
177 
resetcv::utils::trace::details::RegionStatisticsStatus178     void reset()
179     {
180         _skipDepth = -1;
181 #ifdef HAVE_IPP
182         ignoreDepthImplIPP = 0;
183 #endif
184 #ifdef HAVE_OPENCL
185         ignoreDepthImplOpenCL = 0;
186 #endif
187 #ifdef HAVE_OPENVX
188         ignoreDepthImplOpenVX = 0;
189 #endif
190     }
191 
propagateFromcv::utils::trace::details::RegionStatisticsStatus192     void propagateFrom(const RegionStatisticsStatus& src)
193     {
194         _skipDepth = -1;
195         if (src._skipDepth >= 0)
196             enableSkipMode(0);
197 #ifdef HAVE_IPP
198         ignoreDepthImplIPP = src.ignoreDepthImplIPP ? 1 : 0;
199 #endif
200 #ifdef HAVE_OPENCL
201         ignoreDepthImplOpenCL = src.ignoreDepthImplOpenCL ? 1 : 0;
202 #endif
203 #ifdef HAVE_OPENVX
204         ignoreDepthImplOpenVX = src.ignoreDepthImplOpenVX ? 1 : 0;
205 #endif
206     }
207 
208     void enableSkipMode(int depth);
209     void checkResetSkipMode(int leaveDepth);
210 };
211 
212 static inline
operator <<(std::ostream & out,const RegionStatisticsStatus & s)213 std::ostream& operator<<(std::ostream& out, const RegionStatisticsStatus& s)
214 {
215     out << "ignore={";
216     if (s._skipDepth >= 0)
217         out << " SKIP=" << s._skipDepth;
218 #ifdef HAVE_IPP
219     if (s.ignoreDepthImplIPP)
220         out << " IPP=" << s.ignoreDepthImplIPP;
221 #endif
222 #ifdef HAVE_OPENCL
223     if (s.ignoreDepthImplOpenCL)
224         out << " OpenCL=" << s.ignoreDepthImplOpenCL;
225 #endif
226 #ifdef HAVE_OPENVX
227     if (s.ignoreDepthImplOpenVX)
228         out << " OpenVX=" << s.ignoreDepthImplOpenVX;
229 #endif
230     out << "}";
231     return out;
232 }
233 
234 //! TraceManager for local thread
235 struct TraceManagerThreadLocal
236 {
237     const int threadID;
238     int region_counter;
239 
240     size_t totalSkippedEvents;
241 
242     Region* currentActiveRegion;
243 
244     struct StackEntry
245     {
246         Region* region;
247         const Region::LocationStaticStorage* location;
248         int64 beginTimestamp;
StackEntrycv::utils::trace::details::TraceManagerThreadLocal::StackEntry249         StackEntry(Region* region_, const Region::LocationStaticStorage* location_, int64 beginTimestamp_) :
250             region(region_), location(location_), beginTimestamp(beginTimestamp_)
251         {}
StackEntrycv::utils::trace::details::TraceManagerThreadLocal::StackEntry252         StackEntry() : region(NULL), location(NULL), beginTimestamp(-1) {}
253     };
254     std::deque<StackEntry> stack;
255 
256     int regionDepth;                   // functions only (no named regions)
257     int regionDepthOpenCV;             // functions from OpenCV library
258 
259     RegionStatistics stat;
260     RegionStatisticsStatus stat_status;
261 
262     StackEntry dummy_stack_top;        // parallel_for root region
263     RegionStatistics parallel_for_stat;
264     RegionStatisticsStatus parallel_for_stat_status;
265     size_t parallel_for_stack_size;
266 
267 
268     mutable cv::Ptr<TraceStorage> storage;
269 
TraceManagerThreadLocalcv::utils::trace::details::TraceManagerThreadLocal270     TraceManagerThreadLocal() :
271         threadID(cv::utils::getThreadID()),
272         region_counter(0), totalSkippedEvents(0),
273         currentActiveRegion(NULL),
274         regionDepth(0),
275         regionDepthOpenCV(0),
276         parallel_for_stack_size(0)
277     {
278     }
279 
280     ~TraceManagerThreadLocal();
281 
282     TraceStorage* getStorage() const;
283 
284     void recordLocation(const Region::LocationStaticStorage& location);
285     void recordRegionEnter(const Region& region);
286     void recordRegionLeave(const Region& region, const RegionStatistics& result);
287     void recordRegionArg(const Region& region, const TraceArg& arg, const char& value);
288 
stackPushcv::utils::trace::details::TraceManagerThreadLocal289     inline void stackPush(Region* region, const Region::LocationStaticStorage* location, int64 beginTimestamp)
290     {
291         stack.push_back(StackEntry(region, location, beginTimestamp));
292     }
stackTopRegioncv::utils::trace::details::TraceManagerThreadLocal293     inline Region* stackTopRegion() const
294     {
295         if (stack.empty())
296             return dummy_stack_top.region;
297         return stack.back().region;
298     }
stackTopLocationcv::utils::trace::details::TraceManagerThreadLocal299     inline const Region::LocationStaticStorage* stackTopLocation() const
300     {
301         if (stack.empty())
302             return dummy_stack_top.location;
303         return stack.back().location;
304     }
stackTopBeginTimestampcv::utils::trace::details::TraceManagerThreadLocal305     inline int64 stackTopBeginTimestamp() const
306     {
307         if (stack.empty())
308             return dummy_stack_top.beginTimestamp;
309         return stack.back().beginTimestamp;
310     }
stackPopcv::utils::trace::details::TraceManagerThreadLocal311     inline void stackPop()
312     {
313         CV_DbgAssert(!stack.empty());
314         stack.pop_back();
315     }
316     void dumpStack(std::ostream& out, bool onlyFunctions) const;
317 
getCurrentActiveRegioncv::utils::trace::details::TraceManagerThreadLocal318     inline Region* getCurrentActiveRegion()
319     {
320         return currentActiveRegion;
321     }
322 
getCurrentDepthcv::utils::trace::details::TraceManagerThreadLocal323     inline int getCurrentDepth() const { return (int)stack.size(); }
324 };
325 
326 class CV_EXPORTS TraceManager
327 {
328 public:
329     TraceManager();
330     ~TraceManager();
331 
332     static bool isActivated();
333 
334     Mutex mutexCreate;
335     Mutex mutexCount;
336 
337     TLSDataAccumulator<TraceManagerThreadLocal> tls;
338 
339     cv::Ptr<TraceStorage> trace_storage;
340 private:
341     // disable copying
342     TraceManager(const TraceManager&);
343     TraceManager& operator=(const TraceManager&);
344 };
345 
346 CV_EXPORTS TraceManager& getTraceManager();
getCurrentActiveRegion()347 inline Region* getCurrentActiveRegion() { return getTraceManager().tls.get()->getCurrentActiveRegion(); }
getCurrentRegion()348 inline Region* getCurrentRegion() { return getTraceManager().tls.get()->stackTopRegion(); }
349 
350 void parallelForSetRootRegion(const Region& rootRegion, const TraceManagerThreadLocal& root_ctx);
351 void parallelForAttachNestedRegion(const Region& rootRegion);
352 void parallelForFinalize(const Region& rootRegion);
353 
354 
355 
356 
357 
358 
359 
360 struct Region::LocationExtraData
361 {
362     int global_location_id; // 0 - region is disabled
363 #ifdef OPENCV_WITH_ITT
364     // Special fields for ITT
365     __itt_string_handle* volatile ittHandle_name;
366     __itt_string_handle* volatile ittHandle_filename;
367 #endif
368     LocationExtraData(const LocationStaticStorage& location);
369 
370     static Region::LocationExtraData* init(const Region::LocationStaticStorage& location);
371 };
372 
373 class Region::Impl
374 {
375 public:
376     const LocationStaticStorage& location;
377 
378     Region& region;
379     Region* const parentRegion;
380 
381     const int threadID;
382     const int global_region_id;
383 
384     const int64 beginTimestamp;
385     int64 endTimestamp;
386 
387     int directChildrenCount;
388 
389     enum OptimizationPath {
390         CODE_PATH_PLAIN = 0,
391         CODE_PATH_IPP,
392         CODE_PATH_OPENCL,
393         CODE_PATH_OPENVX
394     };
395 
396 #ifdef OPENCV_WITH_ITT
397     bool itt_id_registered;
398     __itt_id itt_id;
399 #endif
400 
401     Impl(TraceManagerThreadLocal& ctx, Region* parentRegion_, Region& region_, const LocationStaticStorage& location_, int64 beginTimestamp_);
402 
403     void enterRegion(TraceManagerThreadLocal& ctx);
404     void leaveRegion(TraceManagerThreadLocal& ctx);
405 
406     void registerRegion(TraceManagerThreadLocal& ctx);
407 
408     void release();
409 protected:
410     ~Impl();
411 };
412 
413 
414 
415 }}}} // namespace
416 
417 //! @endcond
418 
419 #endif
420 
421 #endif // OPENCV_TRACE_PRIVATE_HPP
422