ArmNN
 20.05
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 "ProfilingEvent.hpp"
8 
10 #include "armnn/IProfiler.hpp"
11 
12 #include "WallClockTimer.hpp"
13 
14 #include <chrono>
15 #include <iosfwd>
16 #include <ctime>
17 #include <vector>
18 #include <stack>
19 #include <map>
20 
21 namespace armnn
22 {
23 
24 // Simple single-threaded profiler.
25 // Tracks events reported by BeginEvent()/EndEvent() and outputs detailed information and stats when
26 // Profiler::AnalyzeEventsAndWriteResults() is called.
27 class Profiler final : public IProfiler
28 {
29 public:
30  Profiler();
31  ~Profiler();
32  using InstrumentPtr = std::unique_ptr<Instrument>;
33 
34  // Marks the beginning of a user-defined event.
35  // No attempt will be made to copy the name string: it must be known at compile time.
36  Event* BeginEvent(const BackendId& backendId, const std::string& name, std::vector<InstrumentPtr>&& instruments);
37 
38  // Marks the end of a user-defined event.
39  void EndEvent(Event* event);
40 
41  // Enables/disables profiling.
42  void EnableProfiling(bool enableProfiling) override;
43 
44  // Checks if profiling is enabled.
45  bool IsProfilingEnabled() override;
46 
47  // Increments the event tag, allowing grouping of events in a user-defined manner (e.g. per inference).
48  void UpdateEventTag();
49 
50  // Analyzes the tracked events and writes the results to the given output stream.
51  // Please refer to the configuration variables in Profiling.cpp to customize the information written.
52  void AnalyzeEventsAndWriteResults(std::ostream& outStream) const override;
53 
54  // Print stats for events in JSON Format to the given output stream.
55  void Print(std::ostream& outStream) const override;
56 
57  // Gets the color to render an event with, based on which device it denotes.
58  uint32_t GetEventColor(const BackendId& backendId) const;
59 
60 private:
61  using EventPtr = std::unique_ptr<Event>;
62  struct Marker
63  {
64  std::size_t m_Id;
65  };
66 
67  struct ProfilingEventStats
68  {
69  double m_TotalMs;
70  double m_MinMs;
71  double m_MaxMs;
72  uint32_t m_Count;
73  };
74 
75  template<typename EventIterType>
76  void AnalyzeEventSequenceAndWriteResults(EventIterType first, EventIterType last, std::ostream& outStream) const;
77 
78  std::map<std::string, ProfilingEventStats> CalculateProfilingEventStats() const;
79  void PopulateInferences(std::vector<const Event*>& outInferences, int& outBaseLevel) const;
80  void PopulateDescendants(std::map<const Event*, std::vector<const Event*>>& outDescendantsMap) const;
81 
82  std::stack<Event*> m_Parents;
83  std::vector<EventPtr> m_EventSequence;
84  bool m_ProfilingEnabled;
85 
86 private:
87  // Friend functions for unit testing, see ProfilerTests.cpp.
88  friend size_t GetProfilerEventSequenceSize(armnn::Profiler* profiler);
89 };
90 
91 // Singleton profiler manager.
92 // Keeps track of all the running profiler instances.
94 {
95 public:
96  // Register the given profiler as a thread local pointer.
97  void RegisterProfiler(Profiler* profiler);
98 
99  // Gets the thread local pointer to the profiler.
100  Profiler* GetProfiler();
101 
102  // Accesses the singleton.
103  static ProfilerManager& GetInstance();
104 
105 private:
106  // The constructor is kept private so that other instances of this class (other that the singleton's)
107  // can't be allocated.
108  ProfilerManager() {}
109 };
110 
111 // Helper to easily add event markers to the codebase.
113 {
114 public:
115  using InstrumentPtr = std::unique_ptr<Instrument>;
116 
117  template<typename... Args>
118  ScopedProfilingEvent(const BackendId& backendId, const std::string& name, Args... args)
119  : m_Event(nullptr)
120  , m_Profiler(ProfilerManager::GetInstance().GetProfiler())
121  {
122  if (m_Profiler && m_Profiler->IsProfilingEnabled())
123  {
124  std::vector<InstrumentPtr> instruments(0);
125  instruments.reserve(sizeof...(args)); //One allocation
126  ConstructNextInVector(instruments, args...);
127  m_Event = m_Profiler->BeginEvent(backendId, name, std::move(instruments));
128  }
129  }
130 
132  {
133  if (m_Profiler && m_Event)
134  {
135  m_Profiler->EndEvent(m_Event);
136  }
137  }
138 
139 private:
140 
141  void ConstructNextInVector(std::vector<InstrumentPtr>& instruments)
142  {
143  IgnoreUnused(instruments);
144  }
145 
146  template<typename Arg, typename... Args>
147  void ConstructNextInVector(std::vector<InstrumentPtr>& instruments, Arg arg, Args... args)
148  {
149  instruments.emplace_back(std::make_unique<Arg>(arg));
150  ConstructNextInVector(instruments, args...);
151  }
152 
153  Event* m_Event; ///< Event to track
154  Profiler* m_Profiler; ///< Profiler used
155 };
156 
157 } // namespace armnn
158 
159 
160 #include <boost/preprocessor.hpp>
161 
162 #define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(backendId, /*name,*/ ...) \
163  armnn::ScopedProfilingEvent BOOST_PP_CAT(e_,__LINE__)(backendId, /*name,*/ __VA_ARGS__);
164 
165 // The event name must be known at compile time
166 #define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, /*name,*/ ...) \
167  ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS_UNIQUE_LOC(backendId, /*name,*/ __VA_ARGS__);
168 
169 #define ARMNN_SCOPED_PROFILING_EVENT(backendId, name) \
170  ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(backendId, name, armnn::WallClockTimer())
void EndEvent(Event *event)
Definition: Profiling.cpp:217
Event class records measurements reported by BeginEvent()/EndEvent() and returns measurements when Ev...
ScopedProfilingEvent(const BackendId &backendId, const std::string &name, Args... args)
Definition: Profiling.hpp:118
std::unique_ptr< Instrument > InstrumentPtr
Definition: Profiling.hpp:115
void EnableProfiling(bool enableProfiling) override
Enables/disables profiling for this profiler.
Definition: Profiling.cpp:195
Copyright (c) 2020 ARM Limited.
void IgnoreUnused(Ts &&...)
void AnalyzeEventsAndWriteResults(std::ostream &outStream) const override
Analyzes the tracked events and writes the results to the given output stream.
Definition: Profiling.cpp:380
bool IsProfilingEnabled() override
Checks whether profiling is enabled.
Definition: Profiling.cpp:190
Event * BeginEvent(const BackendId &backendId, const std::string &name, std::vector< InstrumentPtr > &&instruments)
Definition: Profiling.cpp:200
friend size_t GetProfilerEventSequenceSize(armnn::Profiler *profiler)
uint32_t GetEventColor(const BackendId &backendId) const
Definition: Profiling.cpp:463
void UpdateEventTag()
void Print(std::ostream &outStream) const override
Print stats for events in JSON Format to the given output stream.
Definition: Profiling.cpp:330
std::unique_ptr< Instrument > InstrumentPtr
Definition: Profiling.hpp:32