ArmNN  NotReleased
Profiling.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #pragma once
6 
7 #include "ProfilingEvent.hpp"
8 
9 #include "armnn/IProfiler.hpp"
10 
11 #include "WallClockTimer.hpp"
12 
13 #include <chrono>
14 #include <iosfwd>
15 #include <ctime>
16 #include <vector>
17 #include <stack>
18 #include <map>
19 
20 #include <boost/core/ignore_unused.hpp>
21 
22 namespace armnn
23 {
24 
25 // Simple single-threaded profiler.
26 // Tracks events reported by BeginEvent()/EndEvent() and outputs detailed information and stats when
27 // Profiler::AnalyzeEventsAndWriteResults() is called.
28 class Profiler final : public IProfiler
29 {
30 public:
31  Profiler();
32  ~Profiler();
33  using InstrumentPtr = std::unique_ptr<Instrument>;
34 
35  // Marks the beginning of a user-defined event.
36  // No attempt will be made to copy the name string: it must be known at compile time.
37  Event* BeginEvent(const BackendId& backendId, const std::string& name, std::vector<InstrumentPtr>&& instruments);
38 
39  // Marks the end of a user-defined event.
40  void EndEvent(Event* event);
41 
42  // Enables/disables profiling.
43  void EnableProfiling(bool enableProfiling) override;
44 
45  // Checks if profiling is enabled.
46  bool IsProfilingEnabled() override;
47 
48  // Increments the event tag, allowing grouping of events in a user-defined manner (e.g. per inference).
49  void UpdateEventTag();
50 
51  // Analyzes the tracked events and writes the results to the given output stream.
52  // Please refer to the configuration variables in Profiling.cpp to customize the information written.
53  void AnalyzeEventsAndWriteResults(std::ostream& outStream) const override;
54 
55  // Print stats for events in JSON Format to the given output stream.
56  void Print(std::ostream& outStream) const override;
57 
58  // Gets the color to render an event with, based on which device it denotes.
59  uint32_t GetEventColor(const BackendId& backendId) const;
60 
61 private:
62  using EventPtr = std::unique_ptr<Event>;
63  struct Marker
64  {
65  std::size_t m_Id;
66  };
67 
68  struct ProfilingEventStats
69  {
70  double m_TotalMs;
71  double m_MinMs;
72  double m_MaxMs;
73  uint32_t m_Count;
74  };
75 
76  template<typename EventIterType>
77  void AnalyzeEventSequenceAndWriteResults(EventIterType first, EventIterType last, std::ostream& outStream) const;
78 
79  std::map<std::string, ProfilingEventStats> CalculateProfilingEventStats() const;
80  void PopulateInferences(std::vector<const Event*>& outInferences, int& outBaseLevel) const;
81  void PopulateDescendants(std::map<const Event*, std::vector<const Event*>>& outDescendantsMap) const;
82 
83  std::stack<Event*> m_Parents;
84  std::vector<EventPtr> m_EventSequence;
85  bool m_ProfilingEnabled;
86 
87 private:
88  // Friend functions for unit testing, see ProfilerTests.cpp.
89  friend size_t GetProfilerEventSequenceSize(armnn::Profiler* profiler);
90 };
91 
92 // Singleton profiler manager.
93 // Keeps track of all the running profiler instances.
95 {
96 public:
97  // Register the given profiler as a thread local pointer.
98  void RegisterProfiler(Profiler* profiler);
99 
100  // Gets the thread local pointer to the profiler.
101  Profiler* GetProfiler();
102 
103  // Accesses the singleton.
104  static ProfilerManager& GetInstance();
105 
106 private:
107  // The constructor is kept private so that other instances of this class (other that the singleton's)
108  // can't be allocated.
109  ProfilerManager() {}
110 };
111 
112 // Helper to easily add event markers to the codebase.
114 {
115 public:
116  using InstrumentPtr = std::unique_ptr<Instrument>;
117 
118  template<typename... Args>
119  ScopedProfilingEvent(const BackendId& backendId, const std::string& name, Args... args)
120  : m_Event(nullptr)
121  , m_Profiler(ProfilerManager::GetInstance().GetProfiler())
122  {
123  if (m_Profiler && m_Profiler->IsProfilingEnabled())
124  {
125  std::vector<InstrumentPtr> instruments(0);
126  instruments.reserve(sizeof...(args)); //One allocation
127  ConstructNextInVector(instruments, args...);
128  m_Event = m_Profiler->BeginEvent(backendId, name, std::move(instruments));
129  }
130  }
131 
133  {
134  if (m_Profiler && m_Event)
135  {
136  m_Profiler->EndEvent(m_Event);
137  }
138  }
139 
140 private:
141 
142  void ConstructNextInVector(std::vector<InstrumentPtr>& instruments)
143  {
144  boost::ignore_unused(instruments);
145  }
146 
147  template<typename Arg, typename... Args>
148  void ConstructNextInVector(std::vector<InstrumentPtr>& instruments, Arg arg, Args... args)
149  {
150  instruments.emplace_back(std::make_unique<Arg>(arg));
151  ConstructNextInVector(instruments, args...);
152  }
153 
154  Event* m_Event;
155  Profiler* m_Profiler;
156 };
157 
158 } // namespace armnn
159 
160 
161 #include <boost/preprocessor.hpp>
162 
163 #define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(backendId, /*name,*/ ...) \
164  armnn::ScopedProfilingEvent BOOST_PP_CAT(e_,__LINE__)(backendId, /*name,*/ __VA_ARGS__);
165 
166 // The event name must be known at compile time
167 #define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, /*name,*/ ...) \
168  ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(backendId, /*name,*/ __VA_ARGS__);
169 
170 #define ARMNN_SCOPED_PROFILING_EVENT(backendId, name) \
171  ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, name, armnn::WallClockTimer())
Event * BeginEvent(const BackendId &backendId, const std::string &name, std::vector< InstrumentPtr > &&instruments)
Definition: Profiling.cpp:200
void UpdateEventTag()
void EndEvent(Event *event)
Definition: Profiling.cpp:217
uint32_t GetEventColor(const BackendId &backendId) const
Definition: Profiling.cpp:463
void EnableProfiling(bool enableProfiling) override
Definition: Profiling.cpp:195
void Print(std::ostream &outStream) const override
Definition: Profiling.cpp:330
void AnalyzeEventsAndWriteResults(std::ostream &outStream) const override
Definition: Profiling.cpp:380
std::unique_ptr< Instrument > InstrumentPtr
Definition: Profiling.hpp:33
std::unique_ptr< Instrument > InstrumentPtr
Definition: Profiling.hpp:116
friend size_t GetProfilerEventSequenceSize(armnn::Profiler *profiler)
bool IsProfilingEnabled() override
Definition: Profiling.cpp:190
ScopedProfilingEvent(const BackendId &backendId, const std::string &name, Args... args)
Definition: Profiling.hpp:119