ArmNN
 21.02
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 
10 #include "armnn/IProfiler.hpp"
11 
12 #include "WallClockTimer.hpp"
13 
14 #include <chrono>
15 #include <iosfwd>
16 #include <ctime>
17 #include <vector>
18 #include <stack>
19 #include <map>
20 
21 namespace armnn
22 {
23 
24 // Simple single-threaded profiler.
25 // Tracks events reported by BeginEvent()/EndEvent() and outputs detailed information and stats when
26 // Profiler::AnalyzeEventsAndWriteResults() is called.
28 {
29 public:
30  ProfilerImpl();
31  ~ProfilerImpl();
32  using InstrumentPtr = std::unique_ptr<Instrument>;
33 
34  // Marks the beginning of a user-defined event.
35  // No attempt will be made to copy the name string: it must be known at compile time.
37  const BackendId& backendId,
38  const std::string& name,
39  std::vector<InstrumentPtr>&& instruments);
40 
41  // Marks the end of a user-defined event.
42  void EndEvent(Event* event);
43 
44  // Enables/disables profiling.
45  void EnableProfiling(bool enableProfiling);
46 
47  // Checks if profiling is enabled.
48  bool IsProfilingEnabled();
49 
50  // Increments the event tag, allowing grouping of events in a user-defined manner (e.g. per inference).
51  void UpdateEventTag();
52 
53  // Analyzes the tracked events and writes the results to the given output stream.
54  // Please refer to the configuration variables in Profiling.cpp to customize the information written.
55  void AnalyzeEventsAndWriteResults(std::ostream& outStream) const;
56 
57  // Print stats for events in JSON Format to the given output stream.
58  void Print(std::ostream& outStream) const;
59 
60  // Gets the color to render an event with, based on which device it denotes.
61  uint32_t GetEventColor(const BackendId& backendId) const;
62 
63  using EventPtr = std::unique_ptr<Event>;
64  struct Marker
65  {
66  std::size_t m_Id;
67  };
68 
70  {
71  double m_TotalMs;
72  double m_MinMs;
73  double m_MaxMs;
74  uint32_t m_Count;
75  };
76 
77  template<typename EventIterType>
78  void AnalyzeEventSequenceAndWriteResults(EventIterType first, EventIterType last, std::ostream& outStream) const;
79 
80  std::map<std::string, ProfilingEventStats> CalculateProfilingEventStats() const;
81  void PopulateInferences(std::vector<const Event*>& outInferences, int& outBaseLevel) const;
82  void PopulateDescendants(std::map<const Event*, std::vector<const Event*>>& outDescendantsMap) const;
83 
84  std::stack<Event*> m_Parents;
85  std::vector<EventPtr> m_EventSequence;
87 };
88 
89 // Singleton profiler manager.
90 // Keeps track of all the running profiler instances.
92 {
93 public:
94  // Register the given profiler as a thread local pointer.
95  void RegisterProfiler(IProfiler* profiler);
96 
97  // Gets the thread local pointer to the profiler.
98  IProfiler* GetProfiler();
99 
100  // Accesses the singleton.
101  static ProfilerManager& GetInstance();
102 
103 private:
104  // The constructor is kept private so that other instances of this class (other that the singleton's)
105  // can't be allocated.
106  ProfilerManager() {}
107 };
108 
109 // Helper to easily add event markers to the codebase.
111 {
112 public:
113  using InstrumentPtr = std::unique_ptr<Instrument>;
114 
115  template<typename... Args>
116  ScopedProfilingEvent(const BackendId& backendId, const std::string& name, Args&&... args)
117  : m_Event(nullptr)
118  , m_Profiler(ProfilerManager::GetInstance().GetProfiler())
119  {
120  if (m_Profiler && m_Profiler->IsProfilingEnabled())
121  {
122  std::vector<InstrumentPtr> instruments(0);
123  instruments.reserve(sizeof...(args)); //One allocation
124  ConstructNextInVector(instruments, std::forward<Args>(args)...);
125  m_Event = m_Profiler->BeginEvent(backendId, name, std::move(instruments));
126  }
127  }
128 
130  {
131  if (m_Profiler && m_Event)
132  {
133  m_Profiler->pProfilerImpl->EndEvent(m_Event);
134  }
135  }
136 
137 private:
138 
139  void ConstructNextInVector(std::vector<InstrumentPtr>& instruments)
140  {
141  IgnoreUnused(instruments);
142  }
143 
144  template<typename Arg, typename... Args>
145  void ConstructNextInVector(std::vector<InstrumentPtr>& instruments, Arg&& arg, Args&&... args)
146  {
147  instruments.emplace_back(std::make_unique<Arg>(std::forward<Arg>(arg)));
148  ConstructNextInVector(instruments, std::forward<Args>(args)...);
149  }
150 
151  Event* m_Event; ///< Event to track
152  IProfiler* m_Profiler; ///< Profiler used
153 };
154 
155 } // namespace armnn
156 
157 #define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC_INNER(lineNumber, backendId, /*name,*/ ...) \
158  armnn::ScopedProfilingEvent e_ ## lineNumber(backendId, /*name,*/ __VA_ARGS__);
159 
160 #define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(lineNumber, backendId, /*name,*/ ...) \
161  ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC_INNER(lineNumber, backendId, /*name,*/ __VA_ARGS__)
162 
163 // The event name must be known at compile time i.e. if you are going to use this version of the macro
164 // in code the first argument you supply after the backendId must be the name.
165 // NOTE: need to pass the line number as an argument from here so by the time it gets to the UNIQUE_LOC_INNER
166 // above it has expanded to a string and will concat (##) correctly with the 'e_' prefix to yield a
167 // legal and unique variable name (so long as you don't use the macro twice on the same line).
168 // The concat preprocessing operator (##) very unhelpfully will not expand macros see
169 // https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html for the gory details.
170 #define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, /*name,*/ ...) \
171  ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(__LINE__,backendId, /*name,*/ __VA_ARGS__)
172 
173 #define ARMNN_SCOPED_PROFILING_EVENT(backendId, name) \
174  ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, name, armnn::WallClockTimer())
Event class records measurements reported by BeginEvent()/EndEvent() and returns measurements when Ev...
std::unique_ptr< Instrument > InstrumentPtr
Definition: Profiling.hpp:113
uint32_t GetEventColor(const BackendId &backendId) const
Definition: Profiling.cpp:464
std::map< std::string, ProfilingEventStats > CalculateProfilingEventStats() const
Definition: Profiling.cpp:83
Copyright (c) 2021 ARM Limited and Contributors.
void IgnoreUnused(Ts &&...)
ScopedProfilingEvent(const BackendId &backendId, const std::string &name, Args &&... args)
Definition: Profiling.hpp:116
void AnalyzeEventSequenceAndWriteResults(EventIterType first, EventIterType last, std::ostream &outStream) const
void AnalyzeEventsAndWriteResults(std::ostream &outStream) const
Definition: Profiling.cpp:381
std::unique_ptr< Event > EventPtr
Definition: Profiling.hpp:63
void EndEvent(Event *event)
Definition: Profiling.cpp:218
void Print(std::ostream &outStream) const
Definition: Profiling.cpp:331
Event * BeginEvent(armnn::IProfiler *profiler, const BackendId &backendId, const std::string &name, std::vector< InstrumentPtr > &&instruments)
Definition: Profiling.cpp:200
void PopulateInferences(std::vector< const Event *> &outInferences, int &outBaseLevel) const
Definition: Profiling.cpp:246
std::stack< Event * > m_Parents
Definition: Profiling.hpp:84
void PopulateDescendants(std::map< const Event *, std::vector< const Event *>> &outDescendantsMap) const
Definition: Profiling.cpp:260
std::unique_ptr< Instrument > InstrumentPtr
Definition: Profiling.hpp:32
std::vector< EventPtr > m_EventSequence
Definition: Profiling.hpp:85
void EnableProfiling(bool enableProfiling)
Definition: Profiling.cpp:195