2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // See LICENSE file in the project root for full license information.
7 #include "ProfilingEvent.hpp"
9 #include "armnn/ArmNN.hpp"
10 #include "armnn/IProfiler.hpp"
12 #include "WallClockTimer.hpp"
21 #include <boost/core/ignore_unused.hpp>
26 // Simple single-threaded profiler.
27 // Tracks events reported by BeginEvent()/EndEvent() and outputs detailed information and stats when
28 // Profiler::AnalyzeEventsAndWriteResults() is called.
29 class Profiler final : public IProfiler
34 using InstrumentPtr = std::unique_ptr<Instrument>;
36 // Marks the beginning of a user-defined event.
37 // No attempt will be made to copy the name string: it must be known at compile time.
38 Event* BeginEvent(Compute compute, const std::string& name, std::vector<InstrumentPtr>&& instruments);
40 // Marks the end of a user-defined event.
41 void EndEvent(Event* event);
43 // Enables/disables profiling.
44 void EnableProfiling(bool enableProfiling) override;
46 // Checks if profiling is enabled.
47 bool IsProfilingEnabled() override;
49 // Increments the event tag, allowing grouping of events in a user-defined manner (e.g. per inference).
50 void UpdateEventTag();
52 // Analyzes the tracked events and writes the results to the given output stream.
53 // Please refer to the configuration variables in Profiling.cpp to customize the information written.
54 void AnalyzeEventsAndWriteResults(std::ostream& outStream) const override;
56 // Print stats for events in JSON Format to the given output stream.
57 void Print(std::ostream& outStream) const override;
59 // Gets the color to render an event with, based on which device it denotes.
60 uint32_t GetEventColor(Compute compute) const;
63 using EventPtr = std::unique_ptr<Event>;
69 struct ProfilingEventStats
77 // Waits for a compute device to finish working to guarantee correct timings.
78 // Currently used exclusively when emitting profiling events denoting GPU work.
79 void WaitForDevice(Compute compute) const;
81 template<typename EventIterType>
82 void AnalyzeEventSequenceAndWriteResults(EventIterType first, EventIterType last, std::ostream& outStream) const;
84 std::map<std::string, ProfilingEventStats> CalculateProfilingEventStats() const;
85 void PopulateInferences(std::vector<const Event*>& outInferences, int& outBaseLevel) const;
86 void PopulateDescendants(std::map<const Event*, std::vector<const Event*>>& outDescendantsMap) const;
88 std::stack<Event*> m_Parents;
89 std::vector<EventPtr> m_EventSequence;
90 bool m_ProfilingEnabled;
93 // Friend functions for unit testing, see ProfilerTests.cpp.
94 friend size_t GetProfilerEventSequenceSize(armnn::Profiler* profiler);
97 // Singleton profiler manager.
98 // Keeps track of all the running profiler instances.
102 // Register the given profiler as a thread local pointer.
103 void RegisterProfiler(Profiler* profiler);
105 // Gets the thread local pointer to the profiler.
106 Profiler* GetProfiler();
108 // Accesses the singleton.
109 static ProfilerManager& GetInstance();
112 // The constructor is kept private so that other instances of this class (other that the singleton's)
113 // can't be allocated.
117 // Helper to easily add event markers to the codebase.
118 class ScopedProfilingEvent
121 using InstrumentPtr = std::unique_ptr<Instrument>;
123 template<typename... Args>
124 ScopedProfilingEvent(Compute compute, const std::string& name, Args... args)
126 , m_Profiler(ProfilerManager::GetInstance().GetProfiler())
128 if (m_Profiler && m_Profiler->IsProfilingEnabled())
130 std::vector<InstrumentPtr> instruments(0);
131 instruments.reserve(sizeof...(args)); //One allocation
132 ConstructNextInVector(instruments, args...);
133 m_Event = m_Profiler->BeginEvent(compute, name, std::move(instruments));
137 ~ScopedProfilingEvent()
139 if (m_Profiler && m_Event)
141 m_Profiler->EndEvent(m_Event);
147 void ConstructNextInVector(std::vector<InstrumentPtr>& instruments)
149 boost::ignore_unused(instruments);
152 template<typename Arg, typename... Args>
153 void ConstructNextInVector(std::vector<InstrumentPtr>& instruments, Arg arg, Args... args)
155 instruments.emplace_back(std::make_unique<Arg>(arg));
156 ConstructNextInVector(instruments, args...);
159 Event* m_Event; ///< Event to track
160 Profiler* m_Profiler; ///< Profiler used
165 // The event name must be known at compile time
166 #define ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(compute, /*name,*/ ...) \
167 armnn::ScopedProfilingEvent e_##__FILE__##__LINE__(compute, /*name,*/ __VA_ARGS__);
169 #define ARMNN_SCOPED_PROFILING_EVENT(compute, name) \
170 ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(compute, name, armnn::WallClockTimer())