ArmNN
 22.08
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 <common/include/ProfilingGuid.hpp>
8 #include "ProfilingEvent.hpp"
9 #include "ProfilingDetails.hpp"
10 #include "armnn/IProfiler.hpp"
11 
12 #include <armnn/Optional.hpp>
14 #include "WallClockTimer.hpp"
15 
16 #include <chrono>
17 #include <iosfwd>
18 #include <ctime>
19 #include <vector>
20 #include <stack>
21 #include <map>
22 
23 namespace armnn
24 {
25 
26 // Simple single-threaded profiler.
27 // Tracks events reported by BeginEvent()/EndEvent() and outputs detailed information and stats when
28 // Profiler::AnalyzeEventsAndWriteResults() is called.
30 {
31 public:
32  ProfilerImpl();
33  ~ProfilerImpl();
34  using InstrumentPtr = std::unique_ptr<Instrument>;
35 
36  // Marks the beginning of a user-defined event.
37  // No attempt will be made to copy the name string: it must be known at compile time.
39  const BackendId& backendId,
40  const std::string& name,
41  std::vector<InstrumentPtr>&& instruments,
43 
44  template<typename DescriptorType>
45  void AddLayerDetails(const std::string& label,
46  const DescriptorType& desc,
47  const WorkloadInfo& infos,
48  const arm::pipe::ProfilingGuid guid)
49  {
50  m_ProfilingDetails->AddDetailsToString(label, desc, infos, guid);
51  }
52 
53  // Marks the end of a user-defined event.
54  void EndEvent(Event* event);
55 
56  // Enables/disables profiling.
57  void EnableProfiling(bool enableProfiling);
58 
59  // Checks if profiling is enabled.
60  bool IsProfilingEnabled();
61 
62  // Enables outputting the layer descriptors and infos to stdout
64 
65  // Increments the event tag, allowing grouping of events in a user-defined manner (e.g. per inference).
66  void UpdateEventTag();
67 
68  // Analyzes the tracked events and writes the results to the given output stream.
69  // Please refer to the configuration variables in Profiling.cpp to customize the information written.
70  void AnalyzeEventsAndWriteResults(std::ostream& outStream) const;
71 
72  // Print stats for events in JSON Format to the given output stream.
73  void Print(std::ostream& outStream) const;
74 
75  // Gets the color to render an event with, based on which device it denotes.
76  uint32_t GetEventColor(const BackendId& backendId) const;
77 
78  using EventPtr = std::unique_ptr<Event>;
79  using DescPtr = std::unique_ptr<ProfilingDetails>;
80 
81  struct Marker
82  {
83  std::size_t m_Id;
84  };
85 
87  {
88  double m_TotalMs;
89  double m_MinMs;
90  double m_MaxMs;
91  uint32_t m_Count;
92  };
93 
94  template<typename EventIterType>
95  void AnalyzeEventSequenceAndWriteResults(EventIterType first, EventIterType last, std::ostream& outStream) const;
96 
97  std::map<std::string, ProfilingEventStats> CalculateProfilingEventStats() const;
98  void PopulateParent(std::vector<const Event*>& outEvents, int& outBaseLevel, std::string parentName) const;
99  void PopulateDescendants(std::map<const Event*, std::vector<const Event*>>& outDescendantsMap) const;
100 
101  std::stack<Event*> m_Parents;
102  std::vector<EventPtr> m_EventSequence;
103  DescPtr m_ProfilingDetails = std::make_unique<ProfilingDetails>();
106 
107 };
108 
109 // Singleton profiler manager.
110 // Keeps track of all the running profiler instances.
112 {
113 public:
114  // Register the given profiler as a thread local pointer.
115  void RegisterProfiler(IProfiler* profiler);
116 
117  // Gets the thread local pointer to the profiler.
118  IProfiler* GetProfiler();
119 
120  // Accesses the singleton.
121  static ProfilerManager& GetInstance();
122 
123 private:
124  // The constructor is kept private so that other instances of this class (other that the singleton's)
125  // can't be allocated.
126  ProfilerManager() {}
127 };
128 
129 // Helper to easily add event markers to the codebase.
131 {
132 public:
133  using InstrumentPtr = std::unique_ptr<Instrument>;
134 
135  template<typename... Args>
136  ScopedProfilingEvent(const BackendId& backendId,
138  const std::string& name,
139  Args&& ... args)
140  : m_Event(nullptr)
141  , m_Profiler(ProfilerManager::GetInstance().GetProfiler())
142  {
143  if (m_Profiler && m_Profiler->IsProfilingEnabled())
144  {
145  std::vector<InstrumentPtr> instruments(0);
146  instruments.reserve(sizeof...(args)); //One allocation
147  ConstructNextInVector(instruments, std::forward<Args>(args)...);
148  m_Event = m_Profiler->BeginEvent(backendId, name, std::move(instruments), guid);
149  }
150  }
151 
153  {
154  if (m_Profiler && m_Event)
155  {
156  m_Profiler->pProfilerImpl->EndEvent(m_Event);
157  }
158  }
159 
160 private:
161 
162  void ConstructNextInVector(std::vector<InstrumentPtr>& instruments)
163  {
164  IgnoreUnused(instruments);
165  }
166 
167  template<typename Arg, typename... Args>
168  void ConstructNextInVector(std::vector<InstrumentPtr>& instruments, Arg&& arg, Args&&... args)
169  {
170  instruments.emplace_back(std::make_unique<Arg>(std::forward<Arg>(arg)));
171  ConstructNextInVector(instruments, std::forward<Args>(args)...);
172  }
173 
174  Event* m_Event; ///< Event to track
175  IProfiler* m_Profiler; ///< Profiler used
176 };
177 
178 // Helper to easily add operator details during profiling.
179 template<typename DescriptorType>
180 inline void ProfilingUpdateDescriptions(const std::string& name,
181  const DescriptorType& desc,
182  const WorkloadInfo& infos,
183  const arm::pipe::ProfilingGuid guid)
184 {
185  IProfiler* profiler(ProfilerManager::GetInstance().GetProfiler()); ///< Profiler used
186  if (profiler && profiler->IsProfilingEnabled())
187  {
188  profiler->AddLayerDetails(name, desc, infos, guid);
189  }
190 }
191 
192 template<typename DescriptorType>
193 void IProfiler::AddLayerDetails(const std::string& name,
194  const DescriptorType& desc,
195  const WorkloadInfo& infos,
196  const arm::pipe::ProfilingGuid guid)
197 {
198  return pProfilerImpl->AddLayerDetails(name, desc, infos, guid);
199 }
200 
201 } // namespace armnn
202 
203 // Event Definitions for profiling
204 #define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC_INNER(lineNumber, backendId, guid, /*name,*/ ...) \
205  armnn::ScopedProfilingEvent e_ ## lineNumber(backendId, guid, /*name,*/ __VA_ARGS__);
206 
207 #define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(lineNumber, backendId, guid, /*name,*/ ...) \
208  ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC_INNER(lineNumber, backendId, guid, /*name,*/ __VA_ARGS__)
209 
210 // The event name must be known at compile time i.e. if you are going to use this version of the macro
211 // in code the first argument you supply after the backendId must be the name.
212 // NOTE: need to pass the line number as an argument from here so by the time it gets to the UNIQUE_LOC_INNER
213 // above it has expanded to a string and will concat (##) correctly with the 'e_' prefix to yield a
214 // legal and unique variable name (so long as you don't use the macro twice on the same line).
215 // The concat preprocessing operator (##) very unhelpfully will not expand macros see
216 // https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html for the gory details.
217 #define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, guid, /*name,*/ ...) \
218  ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(__LINE__,backendId, guid, /*name,*/ __VA_ARGS__)
219 
220 #define ARMNN_SCOPED_PROFILING_EVENT(backendId, name) \
221  ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, armnn::EmptyOptional(), name, armnn::WallClockTimer())
222 
223 #define ARMNN_SCOPED_PROFILING_EVENT_GUID(backendId, name, guid) \
224  ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, guid, name, armnn::WallClockTimer())
225 
226 // Workload Description definitons for profiling
227 #define ARMNN_REPORT_PROFILING_WORKLOAD_DESC(name, desc, infos, guid) \
228  armnn::ProfilingUpdateDescriptions(name, desc, infos, guid);
ScopedProfilingEvent(const BackendId &backendId, const Optional< arm::pipe::ProfilingGuid > &guid, const std::string &name, Args &&... args)
Definition: Profiling.hpp:136
Event class records measurements reported by BeginEvent()/EndEvent() and returns measurements when Ev...
std::unique_ptr< Instrument > InstrumentPtr
Definition: Profiling.hpp:133
void EnableNetworkDetailsToStdOut(ProfilingDetailsMethod detailsMethod)
Definition: Profiling.cpp:200
static ProfilerManager & GetInstance()
Definition: Profiling.cpp:572
uint32_t GetEventColor(const BackendId &backendId) const
Definition: Profiling.cpp:542
std::map< std::string, ProfilingEventStats > CalculateProfilingEventStats() const
Definition: Profiling.cpp:82
void ProfilingUpdateDescriptions(const std::string &name, const DescriptorType &desc, const WorkloadInfo &infos, const arm::pipe::ProfilingGuid guid)
Definition: Profiling.hpp:180
Copyright (c) 2021 ARM Limited and Contributors.
void IgnoreUnused(Ts &&...)
void AnalyzeEventSequenceAndWriteResults(EventIterType first, EventIterType last, std::ostream &outStream) const
ProfilingDetailsMethod
Define the behaviour of the internal profiler when outputting network details.
Definition: Types.hpp:71
void AnalyzeEventsAndWriteResults(std::ostream &outStream) const
Definition: Profiling.cpp:460
Event * BeginEvent(armnn::IProfiler *profiler, const BackendId &backendId, const std::string &name, std::vector< InstrumentPtr > &&instruments, const Optional< arm::pipe::ProfilingGuid > &guid)
Definition: Profiling.cpp:205
bool IsProfilingEnabled()
Checks whether profiling is enabled.
Definition: Profiling.cpp:599
std::unique_ptr< Event > EventPtr
Definition: Profiling.hpp:78
void PopulateParent(std::vector< const Event *> &outEvents, int &outBaseLevel, std::string parentName) const
Definition: Profiling.cpp:257
void EndEvent(Event *event)
Definition: Profiling.cpp:229
void AddLayerDetails(const std::string &label, const DescriptorType &desc, const WorkloadInfo &infos, const arm::pipe::ProfilingGuid guid)
Definition: Profiling.hpp:45
ProfilingDetailsMethod m_DetailsToStdOutMethod
Definition: Profiling.hpp:105
void Print(std::ostream &outStream) const
Definition: Profiling.cpp:360
DescPtr m_ProfilingDetails
Definition: Profiling.hpp:103
std::stack< Event * > m_Parents
Definition: Profiling.hpp:101
Contains information about TensorInfos of a layer.
void PopulateDescendants(std::map< const Event *, std::vector< const Event *>> &outDescendantsMap) const
Definition: Profiling.cpp:271
std::unique_ptr< Instrument > InstrumentPtr
Definition: Profiling.hpp:34
std::vector< EventPtr > m_EventSequence
Definition: Profiling.hpp:102
std::unique_ptr< ProfilingDetails > DescPtr
Definition: Profiling.hpp:79
void EnableProfiling(bool enableProfiling)
Definition: Profiling.cpp:195