From 4fcda0101ec3d110c1d6d7bee5c83416b645528a Mon Sep 17 00:00:00 2001 From: telsoa01 Date: Fri, 9 Mar 2018 14:13:49 +0000 Subject: Release 18.02 Change-Id: Id3c11dc5ee94ef664374a988fcc6901e9a232fa6 --- src/armnn/Profiling.hpp | 159 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 src/armnn/Profiling.hpp (limited to 'src/armnn/Profiling.hpp') diff --git a/src/armnn/Profiling.hpp b/src/armnn/Profiling.hpp new file mode 100644 index 0000000000..88a7adff7c --- /dev/null +++ b/src/armnn/Profiling.hpp @@ -0,0 +1,159 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#pragma once + +#if ARMNN_PROFILING_ENABLED + +#include "armnn/ArmNN.hpp" + +#include +#include +#include +#include +#include +#include + +namespace armnn +{ + +// Clock class that uses the same timestamp function as the Mali DDK +class monotonic_clock { +public: + using duration = std::chrono::nanoseconds; + using time_point = std::chrono::time_point; + + static std::chrono::time_point now() noexcept + { + timespec ts; +#if defined(CLOCK_MONOTONIC_RAW) + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); +#else + clock_gettime(CLOCK_MONOTONIC, &ts); +#endif + return time_point(std::chrono::nanoseconds(ts.tv_sec*1000000000 + ts.tv_nsec)); + } +}; + +// Simple single-threaded profiler. +// Tracks events reported by BeginEvent()/EndEvent() and outputs detailed information and stats when +// Profiler::AnalyzeEventsAndWriteResults() is called. +class Profiler +{ +public: + // 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. + void BeginEvent(Compute compute, const std::string name); + + // Marks the end of a user-defined event. + void EndEvent(Compute compute); + + // Increments the event tag, allowing grouping of events in a user-defined manner (e.g. per inference). + void UpdateEventTag() { ++m_EventTag; m_EventTagUpdated = true; } + + // 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; + + // Accesses the singleton + static Profiler& Get() { return s_Instance; } + + // Gets a string name for a given Compute device enum + const char* GetEventComputeDevice(Compute compute) const; + + // Gets the color to render an event with, based on which device it denotes + std::uint32_t GetEventColor(Compute compute) const; + + typedef monotonic_clock Clock; + typedef std::chrono::time_point TimePoint; + +private: + + struct Marker + { + std::size_t m_Id; + const std::string m_EventName; + TimePoint m_TimeStamp; + Compute m_ComputeDevice; + std::uint32_t m_Tag; + }; + + struct ProfilingEvent + { + std::string m_Label; + TimePoint m_StartTime; + TimePoint m_StopTime; + Compute m_Device; + std::uint32_t m_Tag; + + double DurationMs() const + { + return std::chrono::duration(m_StopTime - m_StartTime).count()*1000.0; + } + }; + + struct ProfilingEventStats + { + double m_TotalMs; + double m_MinMs; + double m_MaxMs; + std::uint32_t m_Count; + }; + + Profiler(); + ~Profiler(); + + // Waits for a compute device to finish working to guarantee correct timings. + // Currently used exclusively when emitting profiling events denoting GPU work. + void WaitForDevice(Compute compute) const; + + void AnalyzeEventSequenceAndWriteResults(std::vector::const_iterator first, + std::vector::const_iterator last, + std::ostream& outStream) const; + + std::map CalculateProfilingEventStats() const; + + std::stack m_ObservedMarkers; + std::vector m_EventSequence; + std::uint32_t m_EventTag; + std::uint32_t m_NestingLevel; + bool m_EventTagUpdated; + + static Profiler s_Instance; +}; + +// Helper to easily add event markers to the codebase +class ScopedProfilingEvent +{ +public: + ScopedProfilingEvent(Compute compute, const std::string name) + : m_Compute(compute) + { + Profiler::Get().BeginEvent(compute, name); + } + + ~ScopedProfilingEvent() + { + Profiler::Get().EndEvent(m_Compute); + } + +private: + armnn::Compute m_Compute; +}; + +} // namespace armnn + +// Allows grouping events in an user-defined manner (e.g. per inference) +#define ARMNN_UPDATE_PROFILING_EVENT_TAG() armnn::Profiler::Get().UpdateEventTag(); + +// The event name must be known at compile time +#define ARMNN_SCOPED_PROFILING_EVENT(compute, name) armnn::ScopedProfilingEvent e_##__FILE__##__LINE__(compute, name); + +#else + +#define ARMNN_UPDATE_PROFILING_EVENT_TAG() +#define ARMNN_SCOPED_PROFILING_EVENT(compute, name) + +#endif // ARMNN_PROFILING_ENABLED + -- cgit v1.2.1