blob: a336a0ee2a9bc1a49f6d89a11980d7a6a279d38c [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
62 // Increments the event tag, allowing grouping of events in a user-defined manner (e.g. per inference).
telsoa01c577f2c2018-08-31 09:22:23 +010063 void UpdateEventTag();
telsoa014fcda012018-03-09 14:13:49 +000064
65 // Analyzes the tracked events and writes the results to the given output stream.
66 // Please refer to the configuration variables in Profiling.cpp to customize the information written.
Francis Murtagh33199c22021-02-15 10:11:28 +000067 void AnalyzeEventsAndWriteResults(std::ostream& outStream) const;
telsoa014fcda012018-03-09 14:13:49 +000068
telsoa01c577f2c2018-08-31 09:22:23 +010069 // Print stats for events in JSON Format to the given output stream.
Francis Murtagh33199c22021-02-15 10:11:28 +000070 void Print(std::ostream& outStream) const;
telsoa014fcda012018-03-09 14:13:49 +000071
telsoa01c577f2c2018-08-31 09:22:23 +010072 // Gets the color to render an event with, based on which device it denotes.
Matthew Bentham1b63d6c2019-04-05 09:35:15 +010073 uint32_t GetEventColor(const BackendId& backendId) const;
telsoa014fcda012018-03-09 14:13:49 +000074
telsoa01c577f2c2018-08-31 09:22:23 +010075 using EventPtr = std::unique_ptr<Event>;
Keith Davis554fa092021-07-20 11:25:22 +010076 using DescPtr = std::unique_ptr<ProfilingDetails>;
77
telsoa014fcda012018-03-09 14:13:49 +000078 struct Marker
79 {
80 std::size_t m_Id;
telsoa014fcda012018-03-09 14:13:49 +000081 };
82
83 struct ProfilingEventStats
84 {
85 double m_TotalMs;
86 double m_MinMs;
87 double m_MaxMs;
telsoa01c577f2c2018-08-31 09:22:23 +010088 uint32_t m_Count;
telsoa014fcda012018-03-09 14:13:49 +000089 };
90
telsoa01c577f2c2018-08-31 09:22:23 +010091 template<typename EventIterType>
92 void AnalyzeEventSequenceAndWriteResults(EventIterType first, EventIterType last, std::ostream& outStream) const;
telsoa014fcda012018-03-09 14:13:49 +000093
94 std::map<std::string, ProfilingEventStats> CalculateProfilingEventStats() const;
telsoa01c577f2c2018-08-31 09:22:23 +010095 void PopulateInferences(std::vector<const Event*>& outInferences, int& outBaseLevel) const;
96 void PopulateDescendants(std::map<const Event*, std::vector<const Event*>>& outDescendantsMap) const;
telsoa014fcda012018-03-09 14:13:49 +000097
telsoa01c577f2c2018-08-31 09:22:23 +010098 std::stack<Event*> m_Parents;
99 std::vector<EventPtr> m_EventSequence;
Keith Davis554fa092021-07-20 11:25:22 +0100100 DescPtr m_ProfilingDetails = std::make_unique<ProfilingDetails>();
telsoa01c577f2c2018-08-31 09:22:23 +0100101 bool m_ProfilingEnabled;
telsoa014fcda012018-03-09 14:13:49 +0000102};
103
telsoa01c577f2c2018-08-31 09:22:23 +0100104// Singleton profiler manager.
105// Keeps track of all the running profiler instances.
106class ProfilerManager
107{
108public:
109 // Register the given profiler as a thread local pointer.
Francis Murtagh33199c22021-02-15 10:11:28 +0000110 void RegisterProfiler(IProfiler* profiler);
telsoa01c577f2c2018-08-31 09:22:23 +0100111
112 // Gets the thread local pointer to the profiler.
Francis Murtagh33199c22021-02-15 10:11:28 +0000113 IProfiler* GetProfiler();
telsoa01c577f2c2018-08-31 09:22:23 +0100114
115 // Accesses the singleton.
116 static ProfilerManager& GetInstance();
117
118private:
119 // The constructor is kept private so that other instances of this class (other that the singleton's)
120 // can't be allocated.
121 ProfilerManager() {}
122};
123
124// Helper to easily add event markers to the codebase.
telsoa014fcda012018-03-09 14:13:49 +0000125class ScopedProfilingEvent
126{
127public:
telsoa01c577f2c2018-08-31 09:22:23 +0100128 using InstrumentPtr = std::unique_ptr<Instrument>;
129
130 template<typename... Args>
Keith Davis5a64f222021-08-04 10:35:20 +0100131 ScopedProfilingEvent(const BackendId& backendId,
132 const Optional<profiling::ProfilingGuid>& guid,
133 const std::string& name,
134 Args&& ... args)
telsoa01c577f2c2018-08-31 09:22:23 +0100135 : m_Event(nullptr)
136 , m_Profiler(ProfilerManager::GetInstance().GetProfiler())
telsoa014fcda012018-03-09 14:13:49 +0000137 {
telsoa01c577f2c2018-08-31 09:22:23 +0100138 if (m_Profiler && m_Profiler->IsProfilingEnabled())
139 {
140 std::vector<InstrumentPtr> instruments(0);
141 instruments.reserve(sizeof...(args)); //One allocation
Derek Lambertia08d29b2020-06-19 14:33:05 +0100142 ConstructNextInVector(instruments, std::forward<Args>(args)...);
Keith Davis5a64f222021-08-04 10:35:20 +0100143 m_Event = m_Profiler->BeginEvent(backendId, name, std::move(instruments), guid);
telsoa01c577f2c2018-08-31 09:22:23 +0100144 }
telsoa014fcda012018-03-09 14:13:49 +0000145 }
146
147 ~ScopedProfilingEvent()
148 {
telsoa01c577f2c2018-08-31 09:22:23 +0100149 if (m_Profiler && m_Event)
150 {
Francis Murtagh33199c22021-02-15 10:11:28 +0000151 m_Profiler->pProfilerImpl->EndEvent(m_Event);
telsoa01c577f2c2018-08-31 09:22:23 +0100152 }
telsoa014fcda012018-03-09 14:13:49 +0000153 }
154
155private:
telsoa01c577f2c2018-08-31 09:22:23 +0100156
157 void ConstructNextInVector(std::vector<InstrumentPtr>& instruments)
158 {
Jan Eilers8eb25602020-03-09 12:13:48 +0000159 IgnoreUnused(instruments);
telsoa01c577f2c2018-08-31 09:22:23 +0100160 }
161
162 template<typename Arg, typename... Args>
Derek Lambertia08d29b2020-06-19 14:33:05 +0100163 void ConstructNextInVector(std::vector<InstrumentPtr>& instruments, Arg&& arg, Args&&... args)
telsoa01c577f2c2018-08-31 09:22:23 +0100164 {
Derek Lambertia08d29b2020-06-19 14:33:05 +0100165 instruments.emplace_back(std::make_unique<Arg>(std::forward<Arg>(arg)));
166 ConstructNextInVector(instruments, std::forward<Args>(args)...);
telsoa01c577f2c2018-08-31 09:22:23 +0100167 }
168
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000169 Event* m_Event; ///< Event to track
Francis Murtagh33199c22021-02-15 10:11:28 +0000170 IProfiler* m_Profiler; ///< Profiler used
telsoa014fcda012018-03-09 14:13:49 +0000171};
172
Keith Davis554fa092021-07-20 11:25:22 +0100173// Helper to easily add operator details during profiling.
Keith Davis5a64f222021-08-04 10:35:20 +0100174template<typename DescriptorType>
175inline void ProfilingUpdateDescriptions(const std::string& name,
176 const DescriptorType& desc,
177 const WorkloadInfo& infos,
178 const profiling::ProfilingGuid guid)
Keith Davis554fa092021-07-20 11:25:22 +0100179{
Keith Davis5a64f222021-08-04 10:35:20 +0100180 IProfiler* profiler(ProfilerManager::GetInstance().GetProfiler()); ///< Profiler used
181 if (profiler && profiler->IsProfilingEnabled())
Keith Davis554fa092021-07-20 11:25:22 +0100182 {
Keith Davis5a64f222021-08-04 10:35:20 +0100183 profiler->AddLayerDetails(name, desc, infos, guid);
Keith Davis554fa092021-07-20 11:25:22 +0100184 }
Keith Davis5a64f222021-08-04 10:35:20 +0100185}
Keith Davis554fa092021-07-20 11:25:22 +0100186
187template<typename DescriptorType>
188void IProfiler::AddLayerDetails(const std::string& name,
189 const DescriptorType& desc,
Keith Davis5a64f222021-08-04 10:35:20 +0100190 const WorkloadInfo& infos,
191 const profiling::ProfilingGuid guid)
Keith Davis554fa092021-07-20 11:25:22 +0100192{
Keith Davis5a64f222021-08-04 10:35:20 +0100193 return pProfilerImpl->AddLayerDetails(name, desc, infos, guid);
Keith Davis554fa092021-07-20 11:25:22 +0100194}
195
telsoa014fcda012018-03-09 14:13:49 +0000196} // namespace armnn
197
Keith Davis554fa092021-07-20 11:25:22 +0100198// Event Definitions for profiling
Keith Davis5a64f222021-08-04 10:35:20 +0100199#define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC_INNER(lineNumber, backendId, guid, /*name,*/ ...) \
200 armnn::ScopedProfilingEvent e_ ## lineNumber(backendId, guid, /*name,*/ __VA_ARGS__);
Derek Lamberti6b4dfc22019-08-07 17:01:57 +0100201
Keith Davis5a64f222021-08-04 10:35:20 +0100202#define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(lineNumber, backendId, guid, /*name,*/ ...) \
203 ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC_INNER(lineNumber, backendId, guid, /*name,*/ __VA_ARGS__)
Derek Lamberti6b4dfc22019-08-07 17:01:57 +0100204
Jim Flynnc456c312020-10-13 14:40:29 +0100205// The event name must be known at compile time i.e. if you are going to use this version of the macro
206// in code the first argument you supply after the backendId must be the name.
207// NOTE: need to pass the line number as an argument from here so by the time it gets to the UNIQUE_LOC_INNER
208// above it has expanded to a string and will concat (##) correctly with the 'e_' prefix to yield a
209// legal and unique variable name (so long as you don't use the macro twice on the same line).
210// The concat preprocessing operator (##) very unhelpfully will not expand macros see
211// https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html for the gory details.
Keith Davis5a64f222021-08-04 10:35:20 +0100212#define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, guid, /*name,*/ ...) \
213 ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(__LINE__,backendId, guid, /*name,*/ __VA_ARGS__)
telsoa014fcda012018-03-09 14:13:49 +0000214
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000215#define ARMNN_SCOPED_PROFILING_EVENT(backendId, name) \
Keith Davis5a64f222021-08-04 10:35:20 +0100216 ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, armnn::EmptyOptional(), name, armnn::WallClockTimer())
217
218#define ARMNN_SCOPED_PROFILING_EVENT_GUID(backendId, name, guid) \
219 ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, guid, name, armnn::WallClockTimer())
Keith Davis554fa092021-07-20 11:25:22 +0100220
221// Workload Description definitons for profiling
Keith Davis5a64f222021-08-04 10:35:20 +0100222#define ARMNN_REPORT_PROFILING_WORKLOAD_DESC(name, desc, infos, guid) \
223 armnn::ProfilingUpdateDescriptions(name, desc, infos, guid);