blob: 372b489abf4b7a0ed056b3b6ee3d022b7c826d04 [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,
42 const Optional<profiling::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,
48 const profiling::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
63 void EnableNetworkDetailsToStdOut();
64
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;
telsoa01c577f2c2018-08-31 09:22:23 +010098 void PopulateInferences(std::vector<const Event*>& outInferences, int& outBaseLevel) const;
99 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 Davisf4874862021-08-09 16:49:18 +0100105 bool m_EnableDetailsToStdOut;
telsoa014fcda012018-03-09 14:13:49 +0000106};
107
telsoa01c577f2c2018-08-31 09:22:23 +0100108// Singleton profiler manager.
109// Keeps track of all the running profiler instances.
110class ProfilerManager
111{
112public:
113 // Register the given profiler as a thread local pointer.
Francis Murtagh33199c22021-02-15 10:11:28 +0000114 void RegisterProfiler(IProfiler* profiler);
telsoa01c577f2c2018-08-31 09:22:23 +0100115
116 // Gets the thread local pointer to the profiler.
Francis Murtagh33199c22021-02-15 10:11:28 +0000117 IProfiler* GetProfiler();
telsoa01c577f2c2018-08-31 09:22:23 +0100118
119 // Accesses the singleton.
120 static ProfilerManager& GetInstance();
121
122private:
123 // The constructor is kept private so that other instances of this class (other that the singleton's)
124 // can't be allocated.
125 ProfilerManager() {}
126};
127
128// Helper to easily add event markers to the codebase.
telsoa014fcda012018-03-09 14:13:49 +0000129class ScopedProfilingEvent
130{
131public:
telsoa01c577f2c2018-08-31 09:22:23 +0100132 using InstrumentPtr = std::unique_ptr<Instrument>;
133
134 template<typename... Args>
Keith Davis5a64f222021-08-04 10:35:20 +0100135 ScopedProfilingEvent(const BackendId& backendId,
136 const Optional<profiling::ProfilingGuid>& guid,
137 const std::string& name,
138 Args&& ... args)
telsoa01c577f2c2018-08-31 09:22:23 +0100139 : m_Event(nullptr)
140 , m_Profiler(ProfilerManager::GetInstance().GetProfiler())
telsoa014fcda012018-03-09 14:13:49 +0000141 {
telsoa01c577f2c2018-08-31 09:22:23 +0100142 if (m_Profiler && m_Profiler->IsProfilingEnabled())
143 {
144 std::vector<InstrumentPtr> instruments(0);
145 instruments.reserve(sizeof...(args)); //One allocation
Derek Lambertia08d29b2020-06-19 14:33:05 +0100146 ConstructNextInVector(instruments, std::forward<Args>(args)...);
Keith Davis5a64f222021-08-04 10:35:20 +0100147 m_Event = m_Profiler->BeginEvent(backendId, name, std::move(instruments), guid);
telsoa01c577f2c2018-08-31 09:22:23 +0100148 }
telsoa014fcda012018-03-09 14:13:49 +0000149 }
150
151 ~ScopedProfilingEvent()
152 {
telsoa01c577f2c2018-08-31 09:22:23 +0100153 if (m_Profiler && m_Event)
154 {
Francis Murtagh33199c22021-02-15 10:11:28 +0000155 m_Profiler->pProfilerImpl->EndEvent(m_Event);
telsoa01c577f2c2018-08-31 09:22:23 +0100156 }
telsoa014fcda012018-03-09 14:13:49 +0000157 }
158
159private:
telsoa01c577f2c2018-08-31 09:22:23 +0100160
161 void ConstructNextInVector(std::vector<InstrumentPtr>& instruments)
162 {
Jan Eilers8eb25602020-03-09 12:13:48 +0000163 IgnoreUnused(instruments);
telsoa01c577f2c2018-08-31 09:22:23 +0100164 }
165
166 template<typename Arg, typename... Args>
Derek Lambertia08d29b2020-06-19 14:33:05 +0100167 void ConstructNextInVector(std::vector<InstrumentPtr>& instruments, Arg&& arg, Args&&... args)
telsoa01c577f2c2018-08-31 09:22:23 +0100168 {
Derek Lambertia08d29b2020-06-19 14:33:05 +0100169 instruments.emplace_back(std::make_unique<Arg>(std::forward<Arg>(arg)));
170 ConstructNextInVector(instruments, std::forward<Args>(args)...);
telsoa01c577f2c2018-08-31 09:22:23 +0100171 }
172
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000173 Event* m_Event; ///< Event to track
Francis Murtagh33199c22021-02-15 10:11:28 +0000174 IProfiler* m_Profiler; ///< Profiler used
telsoa014fcda012018-03-09 14:13:49 +0000175};
176
Keith Davis554fa092021-07-20 11:25:22 +0100177// Helper to easily add operator details during profiling.
Keith Davis5a64f222021-08-04 10:35:20 +0100178template<typename DescriptorType>
179inline void ProfilingUpdateDescriptions(const std::string& name,
180 const DescriptorType& desc,
181 const WorkloadInfo& infos,
182 const profiling::ProfilingGuid guid)
Keith Davis554fa092021-07-20 11:25:22 +0100183{
Keith Davis5a64f222021-08-04 10:35:20 +0100184 IProfiler* profiler(ProfilerManager::GetInstance().GetProfiler()); ///< Profiler used
185 if (profiler && profiler->IsProfilingEnabled())
Keith Davis554fa092021-07-20 11:25:22 +0100186 {
Keith Davis5a64f222021-08-04 10:35:20 +0100187 profiler->AddLayerDetails(name, desc, infos, guid);
Keith Davis554fa092021-07-20 11:25:22 +0100188 }
Keith Davis5a64f222021-08-04 10:35:20 +0100189}
Keith Davis554fa092021-07-20 11:25:22 +0100190
191template<typename DescriptorType>
192void IProfiler::AddLayerDetails(const std::string& name,
193 const DescriptorType& desc,
Keith Davis5a64f222021-08-04 10:35:20 +0100194 const WorkloadInfo& infos,
195 const profiling::ProfilingGuid guid)
Keith Davis554fa092021-07-20 11:25:22 +0100196{
Keith Davis5a64f222021-08-04 10:35:20 +0100197 return pProfilerImpl->AddLayerDetails(name, desc, infos, guid);
Keith Davis554fa092021-07-20 11:25:22 +0100198}
199
telsoa014fcda012018-03-09 14:13:49 +0000200} // namespace armnn
201
Keith Davis554fa092021-07-20 11:25:22 +0100202// Event Definitions for profiling
Keith Davis5a64f222021-08-04 10:35:20 +0100203#define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC_INNER(lineNumber, backendId, guid, /*name,*/ ...) \
204 armnn::ScopedProfilingEvent e_ ## lineNumber(backendId, guid, /*name,*/ __VA_ARGS__);
Derek Lamberti6b4dfc22019-08-07 17:01:57 +0100205
Keith Davis5a64f222021-08-04 10:35:20 +0100206#define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(lineNumber, backendId, guid, /*name,*/ ...) \
207 ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC_INNER(lineNumber, backendId, guid, /*name,*/ __VA_ARGS__)
Derek Lamberti6b4dfc22019-08-07 17:01:57 +0100208
Jim Flynnc456c312020-10-13 14:40:29 +0100209// The event name must be known at compile time i.e. if you are going to use this version of the macro
210// in code the first argument you supply after the backendId must be the name.
211// NOTE: need to pass the line number as an argument from here so by the time it gets to the UNIQUE_LOC_INNER
212// above it has expanded to a string and will concat (##) correctly with the 'e_' prefix to yield a
213// legal and unique variable name (so long as you don't use the macro twice on the same line).
214// The concat preprocessing operator (##) very unhelpfully will not expand macros see
215// https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html for the gory details.
Keith Davis5a64f222021-08-04 10:35:20 +0100216#define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, guid, /*name,*/ ...) \
217 ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(__LINE__,backendId, guid, /*name,*/ __VA_ARGS__)
telsoa014fcda012018-03-09 14:13:49 +0000218
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000219#define ARMNN_SCOPED_PROFILING_EVENT(backendId, name) \
Keith Davis5a64f222021-08-04 10:35:20 +0100220 ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, armnn::EmptyOptional(), name, armnn::WallClockTimer())
221
222#define ARMNN_SCOPED_PROFILING_EVENT_GUID(backendId, name, guid) \
223 ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, guid, name, armnn::WallClockTimer())
Keith Davis554fa092021-07-20 11:25:22 +0100224
225// Workload Description definitons for profiling
Keith Davis5a64f222021-08-04 10:35:20 +0100226#define ARMNN_REPORT_PROFILING_WORKLOAD_DESC(name, desc, infos, guid) \
227 armnn::ProfilingUpdateDescriptions(name, desc, infos, guid);