blob: b493d228ea81d9d307a33d79328b4292639f4c3a [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
Keith Davis5a64f222021-08-04 10:35:20 +01007#include <common/include/ProfilingGuid.hpp>
telsoa01c577f2c2018-08-31 09:22:23 +01008#include "ProfilingEvent.hpp"
Keith Davis554fa092021-07-20 11:25:22 +01009#include "ProfilingDetails.hpp"
telsoa01c577f2c2018-08-31 09:22:23 +010010#include "armnn/IProfiler.hpp"
11
Keith Davis5a64f222021-08-04 10:35:20 +010012#include <armnn/Optional.hpp>
13#include <armnn/utility/IgnoreUnused.hpp>
telsoa01c577f2c2018-08-31 09:22:23 +010014#include "WallClockTimer.hpp"
telsoa014fcda012018-03-09 14:13:49 +000015
16#include <chrono>
17#include <iosfwd>
18#include <ctime>
19#include <vector>
20#include <stack>
21#include <map>
22
23namespace armnn
24{
25
telsoa014fcda012018-03-09 14:13:49 +000026// Simple single-threaded profiler.
27// Tracks events reported by BeginEvent()/EndEvent() and outputs detailed information and stats when
28// Profiler::AnalyzeEventsAndWriteResults() is called.
Francis Murtagh33199c22021-02-15 10:11:28 +000029class ProfilerImpl
telsoa014fcda012018-03-09 14:13:49 +000030{
31public:
Francis Murtagh33199c22021-02-15 10:11:28 +000032 ProfilerImpl();
33 ~ProfilerImpl();
telsoa01c577f2c2018-08-31 09:22:23 +010034 using InstrumentPtr = std::unique_ptr<Instrument>;
35
telsoa014fcda012018-03-09 14:13:49 +000036 // Marks the beginning of a user-defined event.
telsoa01c577f2c2018-08-31 09:22:23 +010037 // No attempt will be made to copy the name string: it must be known at compile time.
Francis Murtagh33199c22021-02-15 10:11:28 +000038 Event* BeginEvent(armnn::IProfiler* profiler,
39 const BackendId& backendId,
40 const std::string& name,
Keith Davis5a64f222021-08-04 10:35:20 +010041 std::vector<InstrumentPtr>&& instruments,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000042 const Optional<arm::pipe::ProfilingGuid>& guid);
telsoa014fcda012018-03-09 14:13:49 +000043
Keith Davis554fa092021-07-20 11:25:22 +010044 template<typename DescriptorType>
45 void AddLayerDetails(const std::string& label,
46 const DescriptorType& desc,
Keith Davis5a64f222021-08-04 10:35:20 +010047 const WorkloadInfo& infos,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000048 const arm::pipe::ProfilingGuid guid)
Keith Davis554fa092021-07-20 11:25:22 +010049 {
Keith Davis5a64f222021-08-04 10:35:20 +010050 m_ProfilingDetails->AddDetailsToString(label, desc, infos, guid);
Keith Davis554fa092021-07-20 11:25:22 +010051 }
52
telsoa014fcda012018-03-09 14:13:49 +000053 // Marks the end of a user-defined event.
telsoa01c577f2c2018-08-31 09:22:23 +010054 void EndEvent(Event* event);
55
56 // Enables/disables profiling.
Francis Murtagh33199c22021-02-15 10:11:28 +000057 void EnableProfiling(bool enableProfiling);
telsoa01c577f2c2018-08-31 09:22:23 +010058
59 // Checks if profiling is enabled.
Francis Murtagh33199c22021-02-15 10:11:28 +000060 bool IsProfilingEnabled();
telsoa014fcda012018-03-09 14:13:49 +000061
Keith Davisf4874862021-08-09 16:49:18 +010062 // Enables outputting the layer descriptors and infos to stdout
Keith Davis4914d0c2021-08-18 17:14:05 +010063 void EnableNetworkDetailsToStdOut(ProfilingDetailsMethod detailsMethod);
Keith Davisf4874862021-08-09 16:49:18 +010064
telsoa014fcda012018-03-09 14:13:49 +000065 // Increments the event tag, allowing grouping of events in a user-defined manner (e.g. per inference).
telsoa01c577f2c2018-08-31 09:22:23 +010066 void UpdateEventTag();
telsoa014fcda012018-03-09 14:13:49 +000067
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.
Francis Murtagh33199c22021-02-15 10:11:28 +000070 void AnalyzeEventsAndWriteResults(std::ostream& outStream) const;
telsoa014fcda012018-03-09 14:13:49 +000071
telsoa01c577f2c2018-08-31 09:22:23 +010072 // Print stats for events in JSON Format to the given output stream.
Francis Murtagh33199c22021-02-15 10:11:28 +000073 void Print(std::ostream& outStream) const;
telsoa014fcda012018-03-09 14:13:49 +000074
telsoa01c577f2c2018-08-31 09:22:23 +010075 // Gets the color to render an event with, based on which device it denotes.
Matthew Bentham1b63d6c2019-04-05 09:35:15 +010076 uint32_t GetEventColor(const BackendId& backendId) const;
telsoa014fcda012018-03-09 14:13:49 +000077
telsoa01c577f2c2018-08-31 09:22:23 +010078 using EventPtr = std::unique_ptr<Event>;
Keith Davis554fa092021-07-20 11:25:22 +010079 using DescPtr = std::unique_ptr<ProfilingDetails>;
80
telsoa014fcda012018-03-09 14:13:49 +000081 struct Marker
82 {
83 std::size_t m_Id;
telsoa014fcda012018-03-09 14:13:49 +000084 };
85
86 struct ProfilingEventStats
87 {
88 double m_TotalMs;
89 double m_MinMs;
90 double m_MaxMs;
telsoa01c577f2c2018-08-31 09:22:23 +010091 uint32_t m_Count;
telsoa014fcda012018-03-09 14:13:49 +000092 };
93
telsoa01c577f2c2018-08-31 09:22:23 +010094 template<typename EventIterType>
95 void AnalyzeEventSequenceAndWriteResults(EventIterType first, EventIterType last, std::ostream& outStream) const;
telsoa014fcda012018-03-09 14:13:49 +000096
97 std::map<std::string, ProfilingEventStats> CalculateProfilingEventStats() const;
Kevin May4692e112021-10-18 14:41:50 +010098 void PopulateParent(std::vector<const Event*>& outEvents, int& outBaseLevel, std::string parentName) const;
telsoa01c577f2c2018-08-31 09:22:23 +010099 void PopulateDescendants(std::map<const Event*, std::vector<const Event*>>& outDescendantsMap) const;
telsoa014fcda012018-03-09 14:13:49 +0000100
telsoa01c577f2c2018-08-31 09:22:23 +0100101 std::stack<Event*> m_Parents;
102 std::vector<EventPtr> m_EventSequence;
Keith Davis554fa092021-07-20 11:25:22 +0100103 DescPtr m_ProfilingDetails = std::make_unique<ProfilingDetails>();
telsoa01c577f2c2018-08-31 09:22:23 +0100104 bool m_ProfilingEnabled;
Keith Davis4914d0c2021-08-18 17:14:05 +0100105 ProfilingDetailsMethod m_DetailsToStdOutMethod;
106
telsoa014fcda012018-03-09 14:13:49 +0000107};
108
telsoa01c577f2c2018-08-31 09:22:23 +0100109// 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.
Francis Murtagh33199c22021-02-15 10:11:28 +0000115 void RegisterProfiler(IProfiler* profiler);
telsoa01c577f2c2018-08-31 09:22:23 +0100116
117 // Gets the thread local pointer to the profiler.
Francis Murtagh33199c22021-02-15 10:11:28 +0000118 IProfiler* GetProfiler();
telsoa01c577f2c2018-08-31 09:22:23 +0100119
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.
telsoa014fcda012018-03-09 14:13:49 +0000130class ScopedProfilingEvent
131{
132public:
telsoa01c577f2c2018-08-31 09:22:23 +0100133 using InstrumentPtr = std::unique_ptr<Instrument>;
134
135 template<typename... Args>
Keith Davis5a64f222021-08-04 10:35:20 +0100136 ScopedProfilingEvent(const BackendId& backendId,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000137 const Optional<arm::pipe::ProfilingGuid>& guid,
Keith Davis5a64f222021-08-04 10:35:20 +0100138 const std::string& name,
139 Args&& ... args)
telsoa01c577f2c2018-08-31 09:22:23 +0100140 : m_Event(nullptr)
141 , m_Profiler(ProfilerManager::GetInstance().GetProfiler())
telsoa014fcda012018-03-09 14:13:49 +0000142 {
telsoa01c577f2c2018-08-31 09:22:23 +0100143 if (m_Profiler && m_Profiler->IsProfilingEnabled())
144 {
145 std::vector<InstrumentPtr> instruments(0);
146 instruments.reserve(sizeof...(args)); //One allocation
Derek Lambertia08d29b2020-06-19 14:33:05 +0100147 ConstructNextInVector(instruments, std::forward<Args>(args)...);
Keith Davis5a64f222021-08-04 10:35:20 +0100148 m_Event = m_Profiler->BeginEvent(backendId, name, std::move(instruments), guid);
telsoa01c577f2c2018-08-31 09:22:23 +0100149 }
telsoa014fcda012018-03-09 14:13:49 +0000150 }
151
152 ~ScopedProfilingEvent()
153 {
telsoa01c577f2c2018-08-31 09:22:23 +0100154 if (m_Profiler && m_Event)
155 {
Francis Murtagh33199c22021-02-15 10:11:28 +0000156 m_Profiler->pProfilerImpl->EndEvent(m_Event);
telsoa01c577f2c2018-08-31 09:22:23 +0100157 }
telsoa014fcda012018-03-09 14:13:49 +0000158 }
159
160private:
telsoa01c577f2c2018-08-31 09:22:23 +0100161
162 void ConstructNextInVector(std::vector<InstrumentPtr>& instruments)
163 {
Jan Eilers8eb25602020-03-09 12:13:48 +0000164 IgnoreUnused(instruments);
telsoa01c577f2c2018-08-31 09:22:23 +0100165 }
166
167 template<typename Arg, typename... Args>
Derek Lambertia08d29b2020-06-19 14:33:05 +0100168 void ConstructNextInVector(std::vector<InstrumentPtr>& instruments, Arg&& arg, Args&&... args)
telsoa01c577f2c2018-08-31 09:22:23 +0100169 {
Derek Lambertia08d29b2020-06-19 14:33:05 +0100170 instruments.emplace_back(std::make_unique<Arg>(std::forward<Arg>(arg)));
171 ConstructNextInVector(instruments, std::forward<Args>(args)...);
telsoa01c577f2c2018-08-31 09:22:23 +0100172 }
173
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000174 Event* m_Event; ///< Event to track
Francis Murtagh33199c22021-02-15 10:11:28 +0000175 IProfiler* m_Profiler; ///< Profiler used
telsoa014fcda012018-03-09 14:13:49 +0000176};
177
Keith Davis554fa092021-07-20 11:25:22 +0100178// Helper to easily add operator details during profiling.
Keith Davis5a64f222021-08-04 10:35:20 +0100179template<typename DescriptorType>
180inline void ProfilingUpdateDescriptions(const std::string& name,
181 const DescriptorType& desc,
182 const WorkloadInfo& infos,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000183 const arm::pipe::ProfilingGuid guid)
Keith Davis554fa092021-07-20 11:25:22 +0100184{
Keith Davis5a64f222021-08-04 10:35:20 +0100185 IProfiler* profiler(ProfilerManager::GetInstance().GetProfiler()); ///< Profiler used
186 if (profiler && profiler->IsProfilingEnabled())
Keith Davis554fa092021-07-20 11:25:22 +0100187 {
Keith Davis5a64f222021-08-04 10:35:20 +0100188 profiler->AddLayerDetails(name, desc, infos, guid);
Keith Davis554fa092021-07-20 11:25:22 +0100189 }
Keith Davis5a64f222021-08-04 10:35:20 +0100190}
Keith Davis554fa092021-07-20 11:25:22 +0100191
192template<typename DescriptorType>
193void IProfiler::AddLayerDetails(const std::string& name,
194 const DescriptorType& desc,
Keith Davis5a64f222021-08-04 10:35:20 +0100195 const WorkloadInfo& infos,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000196 const arm::pipe::ProfilingGuid guid)
Keith Davis554fa092021-07-20 11:25:22 +0100197{
Keith Davis5a64f222021-08-04 10:35:20 +0100198 return pProfilerImpl->AddLayerDetails(name, desc, infos, guid);
Keith Davis554fa092021-07-20 11:25:22 +0100199}
200
telsoa014fcda012018-03-09 14:13:49 +0000201} // namespace armnn
202
Keith Davis554fa092021-07-20 11:25:22 +0100203// Event Definitions for profiling
Keith Davis5a64f222021-08-04 10:35:20 +0100204#define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC_INNER(lineNumber, backendId, guid, /*name,*/ ...) \
205 armnn::ScopedProfilingEvent e_ ## lineNumber(backendId, guid, /*name,*/ __VA_ARGS__);
Derek Lamberti6b4dfc22019-08-07 17:01:57 +0100206
Keith Davis5a64f222021-08-04 10:35:20 +0100207#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__)
Derek Lamberti6b4dfc22019-08-07 17:01:57 +0100209
Jim Flynnc456c312020-10-13 14:40:29 +0100210// 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.
Keith Davis5a64f222021-08-04 10:35:20 +0100217#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__)
telsoa014fcda012018-03-09 14:13:49 +0000219
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000220#define ARMNN_SCOPED_PROFILING_EVENT(backendId, name) \
Keith Davis5a64f222021-08-04 10:35:20 +0100221 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())
Keith Davis554fa092021-07-20 11:25:22 +0100225
226// Workload Description definitons for profiling
Keith Davis5a64f222021-08-04 10:35:20 +0100227#define ARMNN_REPORT_PROFILING_WORKLOAD_DESC(name, desc, infos, guid) \
228 armnn::ProfilingUpdateDescriptions(name, desc, infos, guid);