blob: 785f50521edf513f9daa9c70924262a1b1d49652 [file] [log] [blame]
Laurent Carlier749294b2020-06-01 09:03:17 +01001//
telsoa014fcda012018-03-09 14:13:49 +00002// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5#pragma once
6
telsoa01c577f2c2018-08-31 09:22:23 +01007#include "ProfilingEvent.hpp"
Keith Davis554fa092021-07-20 11:25:22 +01008#include "ProfilingDetails.hpp"
telsoa014fcda012018-03-09 14:13:49 +00009
Jan Eilers8eb25602020-03-09 12:13:48 +000010#include <armnn/utility/IgnoreUnused.hpp>
telsoa01c577f2c2018-08-31 09:22:23 +010011#include "armnn/IProfiler.hpp"
12
13#include "WallClockTimer.hpp"
telsoa014fcda012018-03-09 14:13:49 +000014
15#include <chrono>
16#include <iosfwd>
17#include <ctime>
18#include <vector>
19#include <stack>
20#include <map>
21
22namespace armnn
23{
24
telsoa014fcda012018-03-09 14:13:49 +000025// Simple single-threaded profiler.
26// Tracks events reported by BeginEvent()/EndEvent() and outputs detailed information and stats when
27// Profiler::AnalyzeEventsAndWriteResults() is called.
Francis Murtagh33199c22021-02-15 10:11:28 +000028class ProfilerImpl
telsoa014fcda012018-03-09 14:13:49 +000029{
30public:
Francis Murtagh33199c22021-02-15 10:11:28 +000031 ProfilerImpl();
32 ~ProfilerImpl();
telsoa01c577f2c2018-08-31 09:22:23 +010033 using InstrumentPtr = std::unique_ptr<Instrument>;
34
telsoa014fcda012018-03-09 14:13:49 +000035 // Marks the beginning of a user-defined event.
telsoa01c577f2c2018-08-31 09:22:23 +010036 // No attempt will be made to copy the name string: it must be known at compile time.
Francis Murtagh33199c22021-02-15 10:11:28 +000037 Event* BeginEvent(armnn::IProfiler* profiler,
38 const BackendId& backendId,
39 const std::string& name,
40 std::vector<InstrumentPtr>&& instruments);
telsoa014fcda012018-03-09 14:13:49 +000041
Keith Davis554fa092021-07-20 11:25:22 +010042 template<typename DescriptorType>
43 void AddLayerDetails(const std::string& label,
44 const DescriptorType& desc,
45 const WorkloadInfo& infos)
46 {
47 m_ProfilingDetails->AddDetailsToString(label, desc, infos);
48 }
49
telsoa014fcda012018-03-09 14:13:49 +000050 // Marks the end of a user-defined event.
telsoa01c577f2c2018-08-31 09:22:23 +010051 void EndEvent(Event* event);
52
53 // Enables/disables profiling.
Francis Murtagh33199c22021-02-15 10:11:28 +000054 void EnableProfiling(bool enableProfiling);
telsoa01c577f2c2018-08-31 09:22:23 +010055
56 // Checks if profiling is enabled.
Francis Murtagh33199c22021-02-15 10:11:28 +000057 bool IsProfilingEnabled();
telsoa014fcda012018-03-09 14:13:49 +000058
59 // Increments the event tag, allowing grouping of events in a user-defined manner (e.g. per inference).
telsoa01c577f2c2018-08-31 09:22:23 +010060 void UpdateEventTag();
telsoa014fcda012018-03-09 14:13:49 +000061
62 // Analyzes the tracked events and writes the results to the given output stream.
63 // Please refer to the configuration variables in Profiling.cpp to customize the information written.
Francis Murtagh33199c22021-02-15 10:11:28 +000064 void AnalyzeEventsAndWriteResults(std::ostream& outStream) const;
telsoa014fcda012018-03-09 14:13:49 +000065
telsoa01c577f2c2018-08-31 09:22:23 +010066 // Print stats for events in JSON Format to the given output stream.
Francis Murtagh33199c22021-02-15 10:11:28 +000067 void Print(std::ostream& outStream) const;
telsoa014fcda012018-03-09 14:13:49 +000068
telsoa01c577f2c2018-08-31 09:22:23 +010069 // Gets the color to render an event with, based on which device it denotes.
Matthew Bentham1b63d6c2019-04-05 09:35:15 +010070 uint32_t GetEventColor(const BackendId& backendId) const;
telsoa014fcda012018-03-09 14:13:49 +000071
telsoa01c577f2c2018-08-31 09:22:23 +010072 using EventPtr = std::unique_ptr<Event>;
Keith Davis554fa092021-07-20 11:25:22 +010073 using DescPtr = std::unique_ptr<ProfilingDetails>;
74
telsoa014fcda012018-03-09 14:13:49 +000075 struct Marker
76 {
77 std::size_t m_Id;
telsoa014fcda012018-03-09 14:13:49 +000078 };
79
80 struct ProfilingEventStats
81 {
82 double m_TotalMs;
83 double m_MinMs;
84 double m_MaxMs;
telsoa01c577f2c2018-08-31 09:22:23 +010085 uint32_t m_Count;
telsoa014fcda012018-03-09 14:13:49 +000086 };
87
telsoa01c577f2c2018-08-31 09:22:23 +010088 template<typename EventIterType>
89 void AnalyzeEventSequenceAndWriteResults(EventIterType first, EventIterType last, std::ostream& outStream) const;
telsoa014fcda012018-03-09 14:13:49 +000090
91 std::map<std::string, ProfilingEventStats> CalculateProfilingEventStats() const;
telsoa01c577f2c2018-08-31 09:22:23 +010092 void PopulateInferences(std::vector<const Event*>& outInferences, int& outBaseLevel) const;
93 void PopulateDescendants(std::map<const Event*, std::vector<const Event*>>& outDescendantsMap) const;
telsoa014fcda012018-03-09 14:13:49 +000094
telsoa01c577f2c2018-08-31 09:22:23 +010095 std::stack<Event*> m_Parents;
96 std::vector<EventPtr> m_EventSequence;
Keith Davis554fa092021-07-20 11:25:22 +010097 DescPtr m_ProfilingDetails = std::make_unique<ProfilingDetails>();
telsoa01c577f2c2018-08-31 09:22:23 +010098 bool m_ProfilingEnabled;
telsoa014fcda012018-03-09 14:13:49 +000099};
100
telsoa01c577f2c2018-08-31 09:22:23 +0100101// Singleton profiler manager.
102// Keeps track of all the running profiler instances.
103class ProfilerManager
104{
105public:
106 // Register the given profiler as a thread local pointer.
Francis Murtagh33199c22021-02-15 10:11:28 +0000107 void RegisterProfiler(IProfiler* profiler);
telsoa01c577f2c2018-08-31 09:22:23 +0100108
109 // Gets the thread local pointer to the profiler.
Francis Murtagh33199c22021-02-15 10:11:28 +0000110 IProfiler* GetProfiler();
telsoa01c577f2c2018-08-31 09:22:23 +0100111
112 // Accesses the singleton.
113 static ProfilerManager& GetInstance();
114
115private:
116 // The constructor is kept private so that other instances of this class (other that the singleton's)
117 // can't be allocated.
118 ProfilerManager() {}
119};
120
121// Helper to easily add event markers to the codebase.
telsoa014fcda012018-03-09 14:13:49 +0000122class ScopedProfilingEvent
123{
124public:
telsoa01c577f2c2018-08-31 09:22:23 +0100125 using InstrumentPtr = std::unique_ptr<Instrument>;
126
127 template<typename... Args>
Derek Lambertia08d29b2020-06-19 14:33:05 +0100128 ScopedProfilingEvent(const BackendId& backendId, const std::string& name, Args&&... args)
telsoa01c577f2c2018-08-31 09:22:23 +0100129 : m_Event(nullptr)
130 , m_Profiler(ProfilerManager::GetInstance().GetProfiler())
telsoa014fcda012018-03-09 14:13:49 +0000131 {
telsoa01c577f2c2018-08-31 09:22:23 +0100132 if (m_Profiler && m_Profiler->IsProfilingEnabled())
133 {
134 std::vector<InstrumentPtr> instruments(0);
135 instruments.reserve(sizeof...(args)); //One allocation
Derek Lambertia08d29b2020-06-19 14:33:05 +0100136 ConstructNextInVector(instruments, std::forward<Args>(args)...);
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000137 m_Event = m_Profiler->BeginEvent(backendId, name, std::move(instruments));
telsoa01c577f2c2018-08-31 09:22:23 +0100138 }
telsoa014fcda012018-03-09 14:13:49 +0000139 }
140
141 ~ScopedProfilingEvent()
142 {
telsoa01c577f2c2018-08-31 09:22:23 +0100143 if (m_Profiler && m_Event)
144 {
Francis Murtagh33199c22021-02-15 10:11:28 +0000145 m_Profiler->pProfilerImpl->EndEvent(m_Event);
telsoa01c577f2c2018-08-31 09:22:23 +0100146 }
telsoa014fcda012018-03-09 14:13:49 +0000147 }
148
149private:
telsoa01c577f2c2018-08-31 09:22:23 +0100150
151 void ConstructNextInVector(std::vector<InstrumentPtr>& instruments)
152 {
Jan Eilers8eb25602020-03-09 12:13:48 +0000153 IgnoreUnused(instruments);
telsoa01c577f2c2018-08-31 09:22:23 +0100154 }
155
156 template<typename Arg, typename... Args>
Derek Lambertia08d29b2020-06-19 14:33:05 +0100157 void ConstructNextInVector(std::vector<InstrumentPtr>& instruments, Arg&& arg, Args&&... args)
telsoa01c577f2c2018-08-31 09:22:23 +0100158 {
Derek Lambertia08d29b2020-06-19 14:33:05 +0100159 instruments.emplace_back(std::make_unique<Arg>(std::forward<Arg>(arg)));
160 ConstructNextInVector(instruments, std::forward<Args>(args)...);
telsoa01c577f2c2018-08-31 09:22:23 +0100161 }
162
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000163 Event* m_Event; ///< Event to track
Francis Murtagh33199c22021-02-15 10:11:28 +0000164 IProfiler* m_Profiler; ///< Profiler used
telsoa014fcda012018-03-09 14:13:49 +0000165};
166
Keith Davis554fa092021-07-20 11:25:22 +0100167// Helper to easily add operator details during profiling.
168class ScopedProfilingUpdateDescriptions
169{
170public:
171 template<typename DescriptorType>
172 ScopedProfilingUpdateDescriptions(const std::string& name, const DescriptorType& desc, const WorkloadInfo& infos)
173 : m_Profiler(ProfilerManager::GetInstance().GetProfiler())
174 {
175 if (m_Profiler && m_Profiler->IsProfilingEnabled())
176 {
177 m_Profiler->AddLayerDetails(name, desc, infos);
178 }
179 }
180
181 ~ScopedProfilingUpdateDescriptions()
182 {}
183
184private:
185
186 IProfiler* m_Profiler; ///< Profiler used
187};
188
189template<typename DescriptorType>
190void IProfiler::AddLayerDetails(const std::string& name,
191 const DescriptorType& desc,
192 const WorkloadInfo& infos)
193{
194 return pProfilerImpl->AddLayerDetails(name, desc, infos);
195}
196
telsoa014fcda012018-03-09 14:13:49 +0000197} // namespace armnn
198
Keith Davis554fa092021-07-20 11:25:22 +0100199// Event Definitions for profiling
Jim Flynnc456c312020-10-13 14:40:29 +0100200#define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC_INNER(lineNumber, backendId, /*name,*/ ...) \
201 armnn::ScopedProfilingEvent e_ ## lineNumber(backendId, /*name,*/ __VA_ARGS__);
Derek Lamberti6b4dfc22019-08-07 17:01:57 +0100202
Jim Flynnc456c312020-10-13 14:40:29 +0100203#define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(lineNumber, backendId, /*name,*/ ...) \
204 ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC_INNER(lineNumber, backendId, /*name,*/ __VA_ARGS__)
Derek Lamberti6b4dfc22019-08-07 17:01:57 +0100205
Jim Flynnc456c312020-10-13 14:40:29 +0100206// The event name must be known at compile time i.e. if you are going to use this version of the macro
207// in code the first argument you supply after the backendId must be the name.
208// NOTE: need to pass the line number as an argument from here so by the time it gets to the UNIQUE_LOC_INNER
209// above it has expanded to a string and will concat (##) correctly with the 'e_' prefix to yield a
210// legal and unique variable name (so long as you don't use the macro twice on the same line).
211// The concat preprocessing operator (##) very unhelpfully will not expand macros see
212// https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html for the gory details.
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000213#define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, /*name,*/ ...) \
Jim Flynnc456c312020-10-13 14:40:29 +0100214 ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(__LINE__,backendId, /*name,*/ __VA_ARGS__)
telsoa014fcda012018-03-09 14:13:49 +0000215
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000216#define ARMNN_SCOPED_PROFILING_EVENT(backendId, name) \
217 ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, name, armnn::WallClockTimer())
Keith Davis554fa092021-07-20 11:25:22 +0100218
219// Workload Description definitons for profiling
220#define ARMNN_REPORT_PROFILING_WORKLOAD_DESC_UNIQUE_LOC_INNER(lineNumber, name, desc, infos) \
221 armnn::ScopedProfilingUpdateDescriptions e_ ## lineNumber(name, desc, infos);
222
223#define ARMNN_REPORT_PROFILING_WORKLOAD_DESC_UNIQUE_LOC(lineNumber, name, desc, infos) \
224 ARMNN_REPORT_PROFILING_WORKLOAD_DESC_UNIQUE_LOC_INNER(lineNumber, name, desc, infos)
225
226#define ARMNN_REPORT_PROFILING_WORKLOAD_DESC(name, desc, infos) \
227 ARMNN_REPORT_PROFILING_WORKLOAD_DESC_UNIQUE_LOC(__LINE__, name, desc, infos)