From 33199c25e5af1553e474a6f6eede07e888cd45ee Mon Sep 17 00:00:00 2001 From: Francis Murtagh Date: Mon, 15 Feb 2021 10:11:28 +0000 Subject: IVGCVSW-5675 Implement Pimpl Idiom for IProfiler (lower priority) Signed-off-by: Francis Murtagh Change-Id: If716f5f4e9b5433586b8a939d326830482da2f74 --- include/armnn/IProfiler.hpp | 29 +++++++-- src/armnn/LoadedNetwork.cpp | 2 +- src/armnn/LoadedNetwork.hpp | 4 +- src/armnn/Profiling.cpp | 68 ++++++++++++++++------ src/armnn/Profiling.hpp | 32 +++++----- src/armnn/ProfilingEvent.cpp | 4 +- src/armnn/ProfilingEvent.hpp | 8 +-- src/armnn/test/ProfilerTests.cpp | 14 ++--- src/armnn/test/UnitTests.hpp | 4 +- .../layerTests/DetectionPostProcessTestImpl.hpp | 2 +- tests/InferenceTest.cpp | 2 +- 11 files changed, 109 insertions(+), 60 deletions(-) diff --git a/include/armnn/IProfiler.hpp b/include/armnn/IProfiler.hpp index 5e6f5087ca..ac422b714f 100644 --- a/include/armnn/IProfiler.hpp +++ b/include/armnn/IProfiler.hpp @@ -6,33 +6,50 @@ #pragma once #include +#include +#include namespace armnn { +class ProfilerImpl; +class BackendId; +class Instrument; +class Event; class IProfiler { public: /// Enables/disables profiling for this profiler. /// @param [in] enableProfiling A flag that indicates whether profiling should be enabled or not. - virtual void EnableProfiling(bool enableProfiling) = 0; + void EnableProfiling(bool enableProfiling); /// Checks whether profiling is enabled. /// Profiling is disabled by default. /// @return true if profiling is enabled, false otherwise. - virtual bool IsProfilingEnabled() = 0; + bool IsProfilingEnabled(); /// Analyzes the tracked events and writes the results to the given output stream. /// Please refer to the configuration variables in Profiling.cpp to customize the information written. /// @param [out] outStream The stream where to write the profiling results to. - virtual void AnalyzeEventsAndWriteResults(std::ostream& outStream) const = 0; + void AnalyzeEventsAndWriteResults(std::ostream& outStream) const; /// Print stats for events in JSON Format to the given output stream. /// @param [out] outStream The stream where to write the profiling results to. - virtual void Print(std::ostream& outStream) const = 0; + void Print(std::ostream& outStream) const; -protected: - ~IProfiler() {} + ~IProfiler(); + IProfiler(); + +private: + using InstrumentPtr = std::unique_ptr; + Event* BeginEvent(const BackendId& backendId, + const std::string& label, + std::vector&& instruments); + std::unique_ptr pProfilerImpl; + friend class ScopedProfilingEvent; + + // Friend functions for unit testing, see ProfilerTests.cpp. + friend size_t GetProfilerEventSequenceSize(armnn::IProfiler* profiler); }; } // namespace armnn diff --git a/src/armnn/LoadedNetwork.cpp b/src/armnn/LoadedNetwork.cpp index f85191059c..4a307e2e04 100644 --- a/src/armnn/LoadedNetwork.cpp +++ b/src/armnn/LoadedNetwork.cpp @@ -125,7 +125,7 @@ LoadedNetwork::LoadedNetwork(std::unique_ptr net, m_ProfilingService(profilingService) { // Create a profiler and register it for the current thread. - m_Profiler = std::make_shared(); + m_Profiler = std::make_shared(); ProfilerManager::GetInstance().RegisterProfiler(m_Profiler.get()); Graph& order = m_OptimizedNetwork->GetGraph().TopologicalSort(); diff --git a/src/armnn/LoadedNetwork.hpp b/src/armnn/LoadedNetwork.hpp index 39b6089ac9..3a44206683 100644 --- a/src/armnn/LoadedNetwork.hpp +++ b/src/armnn/LoadedNetwork.hpp @@ -50,7 +50,7 @@ public: // NOTE we return by reference as the purpose of this method is only to provide // access to the private m_Profiler and in theory we should not need to increment // the shared_ptr's reference counter - const std::shared_ptr& GetProfiler() const { return m_Profiler; } + const std::shared_ptr& GetProfiler() const { return m_Profiler; } void FreeWorkingMemory(); @@ -91,7 +91,7 @@ private: WorkloadQueue m_InputQueue; WorkloadQueue m_WorkloadQueue; WorkloadQueue m_OutputQueue; - std::shared_ptr m_Profiler; + std::shared_ptr m_Profiler; mutable std::mutex m_WorkingMemMutex; diff --git a/src/armnn/Profiling.cpp b/src/armnn/Profiling.cpp index 1cdf30cbdf..c30b482888 100644 --- a/src/armnn/Profiling.cpp +++ b/src/armnn/Profiling.cpp @@ -80,7 +80,7 @@ std::vector FindKernelMeasurements(const Event* event) return measurements; } -std::map Profiler::CalculateProfilingEventStats() const +std::map ProfilerImpl::CalculateProfilingEventStats() const { std::map nameToStatsMap; @@ -111,7 +111,7 @@ const Event* GetEventPtr(const Event* ptr) { return ptr;} const Event* GetEventPtr(const std::unique_ptr& ptr) {return ptr.get(); } template -void Profiler::AnalyzeEventSequenceAndWriteResults(ItertType first, ItertType last, std::ostream& outStream) const +void ProfilerImpl::AnalyzeEventSequenceAndWriteResults(ItertType first, ItertType last, std::ostream& outStream) const { // Outputs event sequence, if needed. if (g_WriteProfilingEventSequence) @@ -162,7 +162,7 @@ void Profiler::AnalyzeEventSequenceAndWriteResults(ItertType first, ItertType la outStream << std::endl; } -Profiler::Profiler() +ProfilerImpl::ProfilerImpl() : m_ProfilingEnabled(false) { m_EventSequence.reserve(g_ProfilingEventCountHint); @@ -173,7 +173,7 @@ Profiler::Profiler() #endif } -Profiler::~Profiler() +ProfilerImpl::~ProfilerImpl() { if (m_ProfilingEnabled) { @@ -187,22 +187,23 @@ Profiler::~Profiler() ProfilerManager::GetInstance().RegisterProfiler(nullptr); } -bool Profiler::IsProfilingEnabled() +bool ProfilerImpl::IsProfilingEnabled() { return m_ProfilingEnabled; } -void Profiler::EnableProfiling(bool enableProfiling) +void ProfilerImpl::EnableProfiling(bool enableProfiling) { m_ProfilingEnabled = enableProfiling; } -Event* Profiler::BeginEvent(const BackendId& backendId, +Event* ProfilerImpl::BeginEvent(armnn::IProfiler* profiler, + const BackendId& backendId, const std::string& label, std::vector&& instruments) { Event* parent = m_Parents.empty() ? nullptr : m_Parents.top(); - m_EventSequence.push_back(std::make_unique(label, this, parent, backendId, std::move(instruments))); + m_EventSequence.push_back(std::make_unique(label, profiler, parent, backendId, std::move(instruments))); Event* event = m_EventSequence.back().get(); event->Start(); @@ -214,7 +215,7 @@ Event* Profiler::BeginEvent(const BackendId& backendId, return event; } -void Profiler::EndEvent(Event* event) +void ProfilerImpl::EndEvent(Event* event) { event->Stop(); @@ -242,7 +243,7 @@ int CalcLevel(const Event* eventPtr) return level; } -void Profiler::PopulateInferences(std::vector& outInferences, int& outBaseLevel) const +void ProfilerImpl::PopulateInferences(std::vector& outInferences, int& outBaseLevel) const { outInferences.reserve(m_EventSequence.size()); for (const auto& event : m_EventSequence) @@ -256,7 +257,7 @@ void Profiler::PopulateInferences(std::vector& outInferences, int& } } -void Profiler::PopulateDescendants(std::map>& outDescendantsMap) const +void ProfilerImpl::PopulateDescendants(std::map>& outDescendantsMap) const { for (const auto& event : m_EventSequence) { @@ -327,7 +328,7 @@ void ExtractJsonObjects(unsigned int inferenceIndex, } } -void Profiler::Print(std::ostream& outStream) const +void ProfilerImpl::Print(std::ostream& outStream) const { // Makes sure timestamps are output with 6 decimals, and save old settings. std::streamsize oldPrecision = outStream.precision(); @@ -377,7 +378,7 @@ void Profiler::Print(std::ostream& outStream) const outStream.precision(oldPrecision); } -void Profiler::AnalyzeEventsAndWriteResults(std::ostream& outStream) const +void ProfilerImpl::AnalyzeEventsAndWriteResults(std::ostream& outStream) const { // Stack should be empty now. const bool saneMarkerSequence = m_Parents.empty(); @@ -460,7 +461,7 @@ void Profiler::AnalyzeEventsAndWriteResults(std::ostream& outStream) const } } -std::uint32_t Profiler::GetEventColor(const BackendId& backendId) const +std::uint32_t ProfilerImpl::GetEventColor(const BackendId& backendId) const { static BackendId cpuRef("CpuRef"); static BackendId cpuAcc("CpuAcc"); @@ -481,7 +482,9 @@ std::uint32_t Profiler::GetEventColor(const BackendId& backendId) const } // The thread_local pointer to the profiler instance. -thread_local Profiler* tl_Profiler = nullptr; +thread_local IProfiler* tl_Profiler = nullptr; + + ProfilerManager& ProfilerManager::GetInstance() { @@ -490,14 +493,45 @@ ProfilerManager& ProfilerManager::GetInstance() return s_ProfilerManager; } -void ProfilerManager::RegisterProfiler(Profiler* profiler) +void ProfilerManager::RegisterProfiler(IProfiler* profiler) { tl_Profiler = profiler; } -Profiler* ProfilerManager::GetProfiler() +IProfiler* ProfilerManager::GetProfiler() { return tl_Profiler; } + +void IProfiler::EnableProfiling(bool enableProfiling) +{ + pProfilerImpl->EnableProfiling(enableProfiling); +} + +bool IProfiler::IsProfilingEnabled() +{ + return pProfilerImpl->IsProfilingEnabled(); +} + +void IProfiler::AnalyzeEventsAndWriteResults(std::ostream& outStream) const +{ + pProfilerImpl->AnalyzeEventsAndWriteResults(outStream); +} + +void IProfiler::Print(std::ostream& outStream) const +{ + pProfilerImpl->Print(outStream); +} + +Event* IProfiler::BeginEvent(const BackendId& backendId, + const std::string& label, + std::vector&& instruments) +{ + return pProfilerImpl->BeginEvent(this, backendId, label, std::move(instruments)); +} + +IProfiler::~IProfiler() = default; +IProfiler::IProfiler() : pProfilerImpl(new ProfilerImpl()) {}; + } // namespace armnn diff --git a/src/armnn/Profiling.hpp b/src/armnn/Profiling.hpp index c0d37dc13e..d134425b6c 100644 --- a/src/armnn/Profiling.hpp +++ b/src/armnn/Profiling.hpp @@ -24,40 +24,42 @@ namespace armnn // Simple single-threaded profiler. // Tracks events reported by BeginEvent()/EndEvent() and outputs detailed information and stats when // Profiler::AnalyzeEventsAndWriteResults() is called. -class Profiler final : public IProfiler +class ProfilerImpl { public: - Profiler(); - ~Profiler(); + ProfilerImpl(); + ~ProfilerImpl(); using InstrumentPtr = std::unique_ptr; // Marks the beginning of a user-defined event. // No attempt will be made to copy the name string: it must be known at compile time. - Event* BeginEvent(const BackendId& backendId, const std::string& name, std::vector&& instruments); + Event* BeginEvent(armnn::IProfiler* profiler, + const BackendId& backendId, + const std::string& name, + std::vector&& instruments); // Marks the end of a user-defined event. void EndEvent(Event* event); // Enables/disables profiling. - void EnableProfiling(bool enableProfiling) override; + void EnableProfiling(bool enableProfiling); // Checks if profiling is enabled. - bool IsProfilingEnabled() override; + bool IsProfilingEnabled(); // Increments the event tag, allowing grouping of events in a user-defined manner (e.g. per inference). void UpdateEventTag(); // Analyzes the tracked events and writes the results to the given output stream. // Please refer to the configuration variables in Profiling.cpp to customize the information written. - void AnalyzeEventsAndWriteResults(std::ostream& outStream) const override; + void AnalyzeEventsAndWriteResults(std::ostream& outStream) const; // Print stats for events in JSON Format to the given output stream. - void Print(std::ostream& outStream) const override; + void Print(std::ostream& outStream) const; // Gets the color to render an event with, based on which device it denotes. uint32_t GetEventColor(const BackendId& backendId) const; -private: using EventPtr = std::unique_ptr; struct Marker { @@ -82,10 +84,6 @@ private: std::stack m_Parents; std::vector m_EventSequence; bool m_ProfilingEnabled; - -private: - // Friend functions for unit testing, see ProfilerTests.cpp. - friend size_t GetProfilerEventSequenceSize(armnn::Profiler* profiler); }; // Singleton profiler manager. @@ -94,10 +92,10 @@ class ProfilerManager { public: // Register the given profiler as a thread local pointer. - void RegisterProfiler(Profiler* profiler); + void RegisterProfiler(IProfiler* profiler); // Gets the thread local pointer to the profiler. - Profiler* GetProfiler(); + IProfiler* GetProfiler(); // Accesses the singleton. static ProfilerManager& GetInstance(); @@ -132,7 +130,7 @@ public: { if (m_Profiler && m_Event) { - m_Profiler->EndEvent(m_Event); + m_Profiler->pProfilerImpl->EndEvent(m_Event); } } @@ -151,7 +149,7 @@ private: } Event* m_Event; ///< Event to track - Profiler* m_Profiler; ///< Profiler used + IProfiler* m_Profiler; ///< Profiler used }; } // namespace armnn diff --git a/src/armnn/ProfilingEvent.cpp b/src/armnn/ProfilingEvent.cpp index 60fb2f79c6..1ba9789034 100644 --- a/src/armnn/ProfilingEvent.cpp +++ b/src/armnn/ProfilingEvent.cpp @@ -9,7 +9,7 @@ namespace armnn { Event::Event(const std::string& eventName, - Profiler* profiler, + IProfiler* profiler, Event* parent, const BackendId backendId, std::vector&& instruments) @@ -69,7 +69,7 @@ const std::string& Event::GetName() const return m_EventName; } -const Profiler* Event::GetProfiler() const +const IProfiler* Event::GetProfiler() const { return m_Profiler; } diff --git a/src/armnn/ProfilingEvent.hpp b/src/armnn/ProfilingEvent.hpp index 9f57753585..7afd5c100c 100644 --- a/src/armnn/ProfilingEvent.hpp +++ b/src/armnn/ProfilingEvent.hpp @@ -16,7 +16,7 @@ namespace armnn { /// Forward declaration -class Profiler; +class IProfiler; /// Event class records measurements reported by BeginEvent()/EndEvent() and returns measurements when /// Event::GetMeasurements() is called. @@ -27,7 +27,7 @@ public: using Instruments = std::vector; Event(const std::string& eventName, - Profiler* profiler, + IProfiler* profiler, Event* parent, const BackendId backendId, std::vector&& instrument); @@ -56,7 +56,7 @@ public: /// Get the pointer of the profiler associated with this event /// \return Pointer of the profiler associated with this event - const Profiler* GetProfiler() const; + const IProfiler* GetProfiler() const; /// Get the pointer of the parent event /// \return Pointer of the parent event @@ -77,7 +77,7 @@ private: std::string m_EventName; /// Stored associated profiler - Profiler* m_Profiler; + IProfiler* m_Profiler; /// Stores optional parent event Event* m_Parent; diff --git a/src/armnn/test/ProfilerTests.cpp b/src/armnn/test/ProfilerTests.cpp index 7bd258e430..a0df3b6b62 100644 --- a/src/armnn/test/ProfilerTests.cpp +++ b/src/armnn/test/ProfilerTests.cpp @@ -19,14 +19,14 @@ namespace armnn { -size_t GetProfilerEventSequenceSize(armnn::Profiler* profiler) +size_t GetProfilerEventSequenceSize(armnn::IProfiler* profiler) { if (!profiler) { return static_cast(-1); } - return profiler->m_EventSequence.size(); + return profiler->pProfilerImpl->m_EventSequence.size(); } } // namespace armnn @@ -45,7 +45,7 @@ void RegisterUnregisterProfilerSingleThreadImpl(bool &res) res = !profilerManager.GetProfiler(); // Create and register a profiler for this thread. - std::unique_ptr profiler = std::make_unique(); + std::unique_ptr profiler = std::make_unique(); profilerManager.RegisterProfiler(profiler.get()); // Check that on a single thread we get the same profiler we registered. @@ -66,7 +66,7 @@ BOOST_AUTO_TEST_SUITE(Profiler) BOOST_AUTO_TEST_CASE(EnableDisableProfiling) { - std::unique_ptr profiler = std::make_unique(); + std::unique_ptr profiler = std::make_unique(); // Check that profiling is disabled by default. BOOST_TEST(!profiler->IsProfilingEnabled()); @@ -126,7 +126,7 @@ BOOST_AUTO_TEST_CASE(ProfilingMacros) } // Create and register a profiler for this thread. - std::unique_ptr profiler = std::make_unique(); + std::unique_ptr profiler = std::make_unique(); profilerManager.RegisterProfiler(profiler.get()); { // --- Profiler, but profiling disabled --- @@ -201,7 +201,7 @@ BOOST_AUTO_TEST_CASE(WriteEventResults) armnn::ProfilerManager& profileManager = armnn::ProfilerManager::GetInstance(); // Create and register a profiler for this thread. - std::unique_ptr profiler = std::make_unique(); + std::unique_ptr profiler = std::make_unique(); profileManager.RegisterProfiler(profiler.get()); // Enable profiling. @@ -282,7 +282,7 @@ BOOST_AUTO_TEST_CASE(ProfilerJsonPrinter) armnn::ProfilerManager& profilerManager = armnn::ProfilerManager::GetInstance(); // Create and register a profiler for this thread. - std::unique_ptr profiler = std::make_unique(); + std::unique_ptr profiler = std::make_unique(); profilerManager.RegisterProfiler(profiler.get()); profiler->EnableProfiling(true); diff --git a/src/armnn/test/UnitTests.hpp b/src/armnn/test/UnitTests.hpp index e0505c9a9f..c15477bf19 100644 --- a/src/armnn/test/UnitTests.hpp +++ b/src/armnn/test/UnitTests.hpp @@ -64,7 +64,7 @@ void CompareTestResultIfSupported(const std::string& testName, const std::vector template void RunTestFunction(const char* testName, TFuncPtr testFunction, Args... args) { - std::unique_ptr profiler = std::make_unique(); + std::unique_ptr profiler = std::make_unique(); armnn::ProfilerManager::GetInstance().RegisterProfiler(profiler.get()); auto memoryManager = WorkloadFactoryHelper::GetMemoryManager(); @@ -80,7 +80,7 @@ void RunTestFunction(const char* testName, TFuncPtr testFunction, Args... args) template void RunTestFunctionUsingTensorHandleFactory(const char* testName, TFuncPtr testFunction, Args... args) { - std::unique_ptr profiler = std::make_unique(); + std::unique_ptr profiler = std::make_unique(); armnn::ProfilerManager::GetInstance().RegisterProfiler(profiler.get()); auto memoryManager = WorkloadFactoryHelper::GetMemoryManager(); diff --git a/src/backends/backendsCommon/test/layerTests/DetectionPostProcessTestImpl.hpp b/src/backends/backendsCommon/test/layerTests/DetectionPostProcessTestImpl.hpp index 34ff31effc..3ee1fadd81 100644 --- a/src/backends/backendsCommon/test/layerTests/DetectionPostProcessTestImpl.hpp +++ b/src/backends/backendsCommon/test/layerTests/DetectionPostProcessTestImpl.hpp @@ -148,7 +148,7 @@ void DetectionPostProcessImpl(const armnn::TensorInfo& boxEncodingsInfo, const std::vector& expectedNumDetections, bool useRegularNms) { - std::unique_ptr profiler = std::make_unique(); + std::unique_ptr profiler = std::make_unique(); armnn::ProfilerManager::GetInstance().RegisterProfiler(profiler.get()); auto memoryManager = WorkloadFactoryHelper::GetMemoryManager(); diff --git a/tests/InferenceTest.cpp b/tests/InferenceTest.cpp index 3392f6ea51..e31e7dc6fb 100644 --- a/tests/InferenceTest.cpp +++ b/tests/InferenceTest.cpp @@ -142,7 +142,7 @@ bool InferenceTest(const InferenceTestOptions& params, } // Create a profiler and register it for the current thread. - std::unique_ptr profiler = std::make_unique(); + std::unique_ptr profiler = std::make_unique(); ProfilerManager::GetInstance().RegisterProfiler(profiler.get()); // Enable profiling if requested. -- cgit v1.2.1