• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2018 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 #ifndef TENSORFLOW_LITE_PROFILING_PROFILER_H_
16 #define TENSORFLOW_LITE_PROFILING_PROFILER_H_
17 
18 #include <vector>
19 
20 #include "tensorflow/lite/profiling/profile_buffer.h"
21 
22 #ifdef TFLITE_PROFILING_ENABLED
23 
24 namespace tflite {
25 namespace profiling {
26 class ScopedProfile;
27 class ScopedOperatorProfile;
28 
29 // Controls whether profiling is enabled or disabled and collects profiles.
30 // TFLite is used on platforms that don't have posix threads, so the profiler is
31 // kept as simple as possible. It is designed to be used only on a single
32 // thread.
33 //
34 // Profiles are collected using Scoped*Profile objects that begin and end a
35 // profile event.
36 // An example usage is shown in the example below:
37 //
38 // Say Worker class has a DoWork method and we are interested in profiling
39 // the overall execution time for DoWork and time spent in Task1 and Task2
40 // functions.
41 //
42 // class Worker {
43 //  public:
44 //   void DoWork() {
45 //    ScopedProfile(&controller, "DoWork");
46 //    Task1();
47 //    Task2();
48 //    .....
49 //   }
50 //
51 //   void Task1() {
52 //    ScopedProfile(&controller, "Task1");
53 //    ....
54 //   }
55 //
56 //   void Task2() {
57 //    ScopedProfile(&controller, "Task2");
58 //   }
59 //
60 //    Profiler profiler;
61 // }
62 //
63 // We instrument the functions that need to be profiled.
64 //
65 // Profile can be collected by enable profiling and then getting profile
66 // events.
67 //
68 //  void ProfileWorker() {
69 //    Worker worker;
70 //    worker.profiler.EnableProfiling();
71 //    worker.DoWork();
72 //    worker.profiler.DisableProfiling();
73 //    // Profiling is complete, extract profiles.
74 //    auto profile_events = worker.profiler.GetProfiles();
75 //  }
76 //
77 //
78 class Profiler {
79  public:
Profiler()80   Profiler() : buffer_(1024, false) {}
81 
StartProfiling()82   void StartProfiling() { buffer_.SetEnabled(true); }
StopProfiling()83   void StopProfiling() { buffer_.SetEnabled(false); }
Reset()84   void Reset() { buffer_.Reset(); }
GetProfileEvents()85   std::vector<const ProfileEvent*> GetProfileEvents() {
86     std::vector<const ProfileEvent*> profile_events;
87     profile_events.reserve(buffer_.Size());
88     for (size_t i = 0; i < buffer_.Size(); i++) {
89       profile_events.push_back(buffer_.At(i));
90     }
91     return profile_events;
92   }
93 
94  private:
95   friend class ScopedProfile;
96   friend class ScopedOperatorProfile;
GetProfileBuffer()97   ProfileBuffer* GetProfileBuffer() { return &buffer_; }
98   ProfileBuffer buffer_;
99 };
100 
101 class ScopedProfile {
102  public:
103   // Adds a profile event to profile that begins with the construction
104   // of object and ends when the object goes out of scope.
105   // The lifetime of tag should be at least the lifetime of profiler.
106 
ScopedProfile(Profiler * profiler,const char * tag)107   ScopedProfile(Profiler* profiler, const char* tag)
108       : buffer_(nullptr), event_handle_(0) {
109     if (profiler) {
110       buffer_ = profiler->GetProfileBuffer();
111       event_handle_ =
112           buffer_->BeginEvent(tag, ProfileEvent::EventType::DEFAULT, 0);
113     }
114   }
~ScopedProfile()115   ~ScopedProfile() {
116     if (buffer_) {
117       buffer_->EndEvent(event_handle_);
118     }
119   }
120 
121  private:
122   ProfileBuffer* buffer_;
123   int32_t event_handle_;
124 };
125 
126 class ScopedOperatorProfile {
127  public:
128   // Adds a profile event to profile that begins with the construction
129   // of object and ends when the object goes out of scope.
130   // The lifetime of tag should be at least the lifetime of profiler.
ScopedOperatorProfile(Profiler * profiler,const char * tag,int node_index)131   ScopedOperatorProfile(Profiler* profiler, const char* tag, int node_index)
132       : buffer_(nullptr), event_handle_(0) {
133     if (profiler) {
134       buffer_ = profiler->GetProfileBuffer();
135       event_handle_ = buffer_->BeginEvent(
136           tag, ProfileEvent::EventType::OPERATOR_INVOKE_EVENT, node_index);
137     }
138   }
139 
~ScopedOperatorProfile()140   ~ScopedOperatorProfile() {
141     if (buffer_) {
142       buffer_->EndEvent(event_handle_);
143     }
144   }
145 
146  private:
147   ProfileBuffer* buffer_;
148   int32_t event_handle_;
149 };
150 
151 }  // namespace profiling
152 }  // namespace tflite
153 
154 #define VARNAME_UNIQ(name, ctr) name##ctr
155 
156 #define SCOPED_TAGGED_OPERATOR_PROFILE(profiler, tag, node_index) \
157   tflite::profiling::ScopedOperatorProfile VARNAME_UNIQ(          \
158       _profile_, __COUNTER__)((profiler), (tag), (node_index))
159 #define SCOPED_OPERATOR_PROFILE(profiler, node_index) \
160   SCOPED_TAGGED_OPERATOR_PROFILE((profiler), "OpInvoke", (node_index))
161 #else
162 
163 namespace tflite {
164 namespace profiling {
165 // A noop version of profiler when profiling is disabled.
166 class Profiler {
167  public:
Profiler()168   Profiler() {}
StartProfiling()169   void StartProfiling() {}
StopProfiling()170   void StopProfiling() {}
Reset()171   void Reset() {}
GetProfileEvents()172   std::vector<const ProfileEvent*> GetProfileEvents() { return {}; }
173 };
174 }  // namespace profiling
175 }  // namespace tflite
176 
177 #define SCOPED_TAGGED_OPERATOR_PROFILE(profiler, tag, node_index)
178 #define SCOPED_OPERATOR_PROFILE(profiler, node_index)
179 
180 #endif  // TFLITE_PROFILING_ENABLED
181 
182 #endif  // TENSORFLOW_LITE_PROFILING_PROFILER_H_
183