• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #ifndef TENSORFLOW_LITE_MICRO_MICRO_PROFILER_H_
17 #define TENSORFLOW_LITE_MICRO_MICRO_PROFILER_H_
18 
19 #include <cstdint>
20 
21 #include "tensorflow/lite/micro/compatibility.h"
22 
23 namespace tflite {
24 
25 // MicroProfiler creates a common way to gain fine-grained insight into runtime
26 // performance. Bottleck operators can be identified along with slow code
27 // sections. This can be used in conjunction with running the relevant micro
28 // benchmark to evaluate end-to-end performance.
29 class MicroProfiler {
30  public:
31   MicroProfiler() = default;
32   virtual ~MicroProfiler() = default;
33 
34   // Marks the start of a new event and returns an event handle that can be used
35   // to mark the end of the event via EndEvent. The lifetime of the tag
36   // parameter must exceed that of the MicroProfiler.
37   virtual uint32_t BeginEvent(const char* tag);
38 
39   // Marks the end of an event associated with event_handle. It is the
40   // responsibility of the caller to ensure than EndEvent is called once and
41   // only once per event_handle.
42   //
43   // If EndEvent is called more than once for the same event_handle, the last
44   // call will be used as the end of event marker.If EndEvent is called 0 times
45   // for a particular event_handle, the duration of that event will be 0 ticks.
46   virtual void EndEvent(uint32_t event_handle);
47 
48   // Clears all the events that have been currently profiled.
ClearEvents()49   void ClearEvents() { num_events_ = 0; }
50 
51   // Returns the sum of the ticks taken across all the events. This number
52   // is only meaningful if all of the events are disjoint (the end time of
53   // event[i] <= start time of event[i+1]).
54   int32_t GetTotalTicks() const;
55 
56   // Prints the profiling information of each of the events.
57   void Log() const;
58 
59  private:
60   // Maximum number of events that this class can keep track of. If we call
61   // AddEvent more than kMaxEvents number of times, then the oldest event's
62   // profiling information will be overwritten.
63   static constexpr int kMaxEvents = 50;
64 
65   const char* tags_[kMaxEvents];
66   int32_t start_ticks_[kMaxEvents];
67   int32_t end_ticks_[kMaxEvents];
68   int num_events_ = 0;
69 
70   TF_LITE_REMOVE_VIRTUAL_DELETE;
71 };
72 
73 #if defined(NDEBUG)
74 // For release builds, the ScopedMicroProfiler is a noop.
75 //
76 // This is done because the ScipedProfiler is used as part of the
77 // MicroInterpreter and we want to ensure zero overhead for the release builds.
78 class ScopedMicroProfiler {
79  public:
ScopedMicroProfiler(const char * tag,MicroProfiler * profiler)80   explicit ScopedMicroProfiler(const char* tag, MicroProfiler* profiler) {}
81 };
82 
83 #else
84 
85 // This class can be used to add events to a MicroProfiler object that span the
86 // lifetime of the ScopedMicroProfiler object.
87 // Usage example:
88 //
89 // MicroProfiler profiler();
90 // ...
91 // {
92 //   ScopedMicroProfiler scoped_profiler("custom_tag", profiler);
93 //   work_to_profile();
94 // }
95 class ScopedMicroProfiler {
96  public:
ScopedMicroProfiler(const char * tag,MicroProfiler * profiler)97   explicit ScopedMicroProfiler(const char* tag, MicroProfiler* profiler)
98       : profiler_(profiler) {
99     if (profiler_ != nullptr) {
100       event_handle_ = profiler_->BeginEvent(tag);
101     }
102   }
103 
~ScopedMicroProfiler()104   ~ScopedMicroProfiler() {
105     if (profiler_ != nullptr) {
106       profiler_->EndEvent(event_handle_);
107     }
108   }
109 
110  private:
111   uint32_t event_handle_ = 0;
112   MicroProfiler* profiler_ = nullptr;
113 };
114 #endif  // !defined(NDEBUG)
115 
116 }  // namespace tflite
117 
118 #endif  // TENSORFLOW_LITE_MICRO_MICRO_PROFILER_H_
119