ArmNN
 25.11
Loading...
Searching...
No Matches
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"
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
23namespace 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{
31public:
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).
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.
111class ProfilerManager
112{
113public:
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.
119
120 // Accesses the singleton.
121 static ProfilerManager& GetInstance();
122
123private:
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{
132public:
133 using InstrumentPtr = std::unique_ptr<Instrument>;
134
135 template<typename... Args>
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
160private:
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.
179template<typename DescriptorType>
180inline 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
192template<typename DescriptorType>
193void 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);
Event class records measurements reported by BeginEvent()/EndEvent() and returns measurements when Ev...
bool IsProfilingEnabled()
Checks whether profiling is enabled.
void AddLayerDetails(const std::string &label, const DescriptorType &desc, const WorkloadInfo &infos, const arm::pipe::ProfilingGuid guid)
Definition Profiling.hpp:45
void Print(std::ostream &outStream) const
std::map< std::string, ProfilingEventStats > CalculateProfilingEventStats() const
Definition Profiling.cpp:82
std::unique_ptr< Event > EventPtr
Definition Profiling.hpp:78
void EnableNetworkDetailsToStdOut(ProfilingDetailsMethod detailsMethod)
std::unique_ptr< ProfilingDetails > DescPtr
Definition Profiling.hpp:79
std::vector< EventPtr > m_EventSequence
std::unique_ptr< Instrument > InstrumentPtr
Definition Profiling.hpp:34
std::stack< Event * > m_Parents
Event * BeginEvent(armnn::IProfiler *profiler, const BackendId &backendId, const std::string &name, std::vector< InstrumentPtr > &&instruments, const Optional< arm::pipe::ProfilingGuid > &guid)
void EndEvent(Event *event)
void PopulateParent(std::vector< const Event * > &outEvents, int &outBaseLevel, std::string parentName) const
void PopulateDescendants(std::map< const Event *, std::vector< const Event * > > &outDescendantsMap) const
uint32_t GetEventColor(const BackendId &backendId) const
void AnalyzeEventsAndWriteResults(std::ostream &outStream) const
void AnalyzeEventSequenceAndWriteResults(EventIterType first, EventIterType last, std::ostream &outStream) const
ProfilingDetailsMethod m_DetailsToStdOutMethod
void EnableProfiling(bool enableProfiling)
IProfiler * GetProfiler()
void RegisterProfiler(IProfiler *profiler)
static ProfilerManager & GetInstance()
std::unique_ptr< Instrument > InstrumentPtr
ScopedProfilingEvent(const BackendId &backendId, const Optional< arm::pipe::ProfilingGuid > &guid, const std::string &name, Args &&... args)
Copyright (c) 2021 ARM Limited and Contributors.
void ProfilingUpdateDescriptions(const std::string &name, const DescriptorType &desc, const WorkloadInfo &infos, const arm::pipe::ProfilingGuid guid)
ProfilingDetailsMethod
Define the behaviour of the internal profiler when outputting network details.
Definition Types.hpp:72
void IgnoreUnused(Ts &&...)
Contains information about TensorInfos of a layer.