diff options
Diffstat (limited to 'src/profiling/test')
-rw-r--r-- | src/profiling/test/FileOnlyProfilingDecoratorTests.cpp | 68 | ||||
-rw-r--r-- | src/profiling/test/PrintPacketHeaderHandler.cpp | 31 | ||||
-rw-r--r-- | src/profiling/test/PrintPacketHeaderHandler.hpp | 26 | ||||
-rw-r--r-- | src/profiling/test/TestTimelinePacketHandler.cpp | 132 | ||||
-rw-r--r-- | src/profiling/test/TestTimelinePacketHandler.hpp | 90 | ||||
-rw-r--r-- | src/profiling/test/TimelineModel.cpp | 57 | ||||
-rw-r--r-- | src/profiling/test/TimelineModel.hpp | 67 |
7 files changed, 466 insertions, 5 deletions
diff --git a/src/profiling/test/FileOnlyProfilingDecoratorTests.cpp b/src/profiling/test/FileOnlyProfilingDecoratorTests.cpp index baadb8555d..964489478e 100644 --- a/src/profiling/test/FileOnlyProfilingDecoratorTests.cpp +++ b/src/profiling/test/FileOnlyProfilingDecoratorTests.cpp @@ -3,12 +3,14 @@ // SPDX-License-Identifier: MIT // -#include "../FileOnlyProfilingConnection.hpp" - +#include <armnn/utility/IgnoreUnused.hpp> +#include <FileOnlyProfilingConnection.hpp> +#include <Filesystem.hpp> +#include <NullProfilingConnection.hpp> #include <ProfilingService.hpp> #include <Runtime.hpp> -#include <Filesystem.hpp> -#include <armnn/utility/IgnoreUnused.hpp> +#include "PrintPacketHeaderHandler.hpp" +#include "TestTimelinePacketHandler.hpp" #include <boost/filesystem.hpp> #include <boost/numeric/conversion/cast.hpp> @@ -37,11 +39,67 @@ class FileOnlyHelperService : public ProfilingService BOOST_AUTO_TEST_SUITE(FileOnlyProfilingDecoratorTests) +std::string UniqueFileName() +{ + std::time_t t = std::time(nullptr); + char mbstr[100]; + std::strftime(mbstr, sizeof(mbstr), "%Y_%m_%d_%H_%M_%S_", std::localtime(&t)); + std::stringstream ss; + ss << mbstr; + ss << t; + ss << ".bin"; + return ss.str(); +} + +BOOST_AUTO_TEST_CASE(TestFileOnlyProfiling) +{ + // Create a temporary file name. + boost::filesystem::path tempPath = boost::filesystem::temp_directory_path(); + boost::filesystem::path tempFile = UniqueFileName(); + tempPath = tempPath / tempFile; + armnn::Runtime::CreationOptions creationOptions; + creationOptions.m_ProfilingOptions.m_EnableProfiling = true; + creationOptions.m_ProfilingOptions.m_FileOnly = true; + creationOptions.m_ProfilingOptions.m_CapturePeriod = 100; + creationOptions.m_ProfilingOptions.m_TimelineEnabled = true; + ILocalPacketHandlerSharedPtr localPacketHandlerPtr = std::make_shared<TestTimelinePacketHandler>(); + creationOptions.m_ProfilingOptions.m_LocalPacketHandlers.push_back(localPacketHandlerPtr); + + armnn::Runtime runtime(creationOptions); + + // Load a simple network + // build up the structure of the network + INetworkPtr net(INetwork::Create()); + + IConnectableLayer* input = net->AddInputLayer(0, "input"); + + NormalizationDescriptor descriptor; + IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor, "normalization"); + + IConnectableLayer* output = net->AddOutputLayer(0, "output"); + + input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0)); + normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0)); + + input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32)); + normalize->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32)); + + // optimize the network + std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef }; + IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime.GetDeviceSpec()); + + // Load it into the runtime. It should succeed. + armnn::NetworkId netId; + BOOST_TEST(runtime.LoadNetwork(netId, std::move(optNet)) == Status::Success); + + static_cast<TestTimelinePacketHandler*>(localPacketHandlerPtr.get())->WaitOnInferenceCompletion(3000); +} + BOOST_AUTO_TEST_CASE(DumpOutgoingValidFileEndToEnd, * boost::unit_test::disabled()) { // Create a temporary file name. boost::filesystem::path tempPath = boost::filesystem::temp_directory_path(); - boost::filesystem::path tempFile = boost::filesystem::unique_path(); + boost::filesystem::path tempFile = UniqueFileName(); tempPath = tempPath / tempFile; armnn::Runtime::CreationOptions::ExternalProfilingOptions options; options.m_EnableProfiling = true; diff --git a/src/profiling/test/PrintPacketHeaderHandler.cpp b/src/profiling/test/PrintPacketHeaderHandler.cpp new file mode 100644 index 0000000000..24095d8250 --- /dev/null +++ b/src/profiling/test/PrintPacketHeaderHandler.cpp @@ -0,0 +1,31 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "PrintPacketHeaderHandler.hpp" + +#include <iostream> + +namespace armnn +{ + +namespace profiling +{ + +std::vector<uint32_t> PrintPacketHeaderHandler::GetHeadersAccepted() +{ + return std::vector<uint32_t>(); +} + +void PrintPacketHeaderHandler::HandlePacket(const Packet& packet) +{ + std::stringstream ss; + ss << "Handler Received Outgoing Packet [" << packet.GetPacketFamily() << ":" << packet.GetPacketId() << "]"; + ss << " Length [" << packet.GetLength() << "]" << std::endl; + std::cout << ss.str() << std::endl; +}; + +} // namespace profiling + +} // namespace armnn
\ No newline at end of file diff --git a/src/profiling/test/PrintPacketHeaderHandler.hpp b/src/profiling/test/PrintPacketHeaderHandler.hpp new file mode 100644 index 0000000000..3cd5921e51 --- /dev/null +++ b/src/profiling/test/PrintPacketHeaderHandler.hpp @@ -0,0 +1,26 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include <armnn/profiling/ILocalPacketHandler.hpp> +#include "Packet.hpp" + +namespace armnn +{ + +namespace profiling +{ + +class PrintPacketHeaderHandler : public ILocalPacketHandler +{ + virtual std::vector<uint32_t> GetHeadersAccepted(); + + virtual void HandlePacket(const Packet& packet); +}; + +} // namespace profiling + +} // namespace armnn diff --git a/src/profiling/test/TestTimelinePacketHandler.cpp b/src/profiling/test/TestTimelinePacketHandler.cpp new file mode 100644 index 0000000000..93fb4b433c --- /dev/null +++ b/src/profiling/test/TestTimelinePacketHandler.cpp @@ -0,0 +1,132 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "TestTimelinePacketHandler.hpp" +#include "IProfilingConnection.hpp" + +#include <armnn/utility/IgnoreUnused.hpp> + +#include <chrono> +#include <iostream> +#include <sstream> + +namespace armnn +{ + +namespace profiling +{ + +std::vector<uint32_t> TestTimelinePacketHandler::GetHeadersAccepted() +{ + std::vector<uint32_t> headers; + headers.push_back(m_DirectoryHeader); // message directory + headers.push_back(m_MessageHeader); // message + return headers; +} + +void TestTimelinePacketHandler::HandlePacket(const Packet& packet) +{ + if (packet.GetHeader() == m_DirectoryHeader) + { + ProcessDirectoryPacket(packet); + } + else if (packet.GetHeader() == m_MessageHeader) + { + ProcessMessagePacket(packet); + } + else + { + std::stringstream ss; + ss << "Received a packet with unknown header [" << packet.GetHeader() << "]"; + throw armnn::Exception(ss.str()); + } +} + +void TestTimelinePacketHandler::Stop() +{ + m_Connection->Close(); +} + +void TestTimelinePacketHandler::WaitOnInferenceCompletion(unsigned int timeout) +{ + std::unique_lock<std::mutex> lck(m_InferenceCompletedMutex); + + auto start = std::chrono::high_resolution_clock::now(); + // Here we we will go back to sleep after a spurious wake up if + // m_InferenceCompleted is not yet true. + if (!m_InferenceCompletedConditionVariable.wait_for(lck, + std::chrono::milliseconds(timeout), + [&]{return m_InferenceCompleted == true;})) + { + auto finish = std::chrono::high_resolution_clock::now(); + std::chrono::duration<double, std::milli> elapsed = finish - start; + std::stringstream ss; + ss << "Timed out waiting on inference completion for " << elapsed.count() << " ms"; + throw armnn::TimeoutException(ss.str()); + } + return; +} + +void TestTimelinePacketHandler::SetInferenceComplete() +{ + { // only lock when we are updating the inference completed variable + std::unique_lock<std::mutex> lck(m_InferenceCompletedMutex); + m_InferenceCompleted = true; + } + m_InferenceCompletedConditionVariable.notify_one(); +} + +void TestTimelinePacketHandler::ProcessDirectoryPacket(const Packet& packet) +{ + m_DirectoryDecoder(packet); +} + +void TestTimelinePacketHandler::ProcessMessagePacket(const Packet& packet) +{ + m_Decoder(packet); +} + +// TimelineMessageDecoder functions +ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateEntity(const Entity& entity) +{ + m_TimelineModel.AddEntity(entity.m_Guid); + return ITimelineDecoder::TimelineStatus::TimelineStatus_Success; +} + +ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateEventClass( + const ITimelineDecoder::EventClass& eventClass) +{ + // for the moment terminate the run here so we can get this code + // onto master prior to a major re-organisation + if (m_PacketHandler != nullptr) + { + m_PacketHandler->SetInferenceComplete(); + } + IgnoreUnused(eventClass); + return ITimelineDecoder::TimelineStatus::TimelineStatus_Success; +} + +ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateEvent(const ITimelineDecoder::Event& event) +{ + IgnoreUnused(event); + return ITimelineDecoder::TimelineStatus::TimelineStatus_Success; +} + +ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateLabel(const ITimelineDecoder::Label& label) +{ + m_TimelineModel.AddLabel(label); + return ITimelineDecoder::TimelineStatus::TimelineStatus_Success; +} + +ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateRelationship( + const ITimelineDecoder::Relationship& relationship) +{ + m_TimelineModel.AddRelationship(relationship); + return ITimelineDecoder::TimelineStatus::TimelineStatus_Success; +} + +} // namespace profiling + +} // namespace armnn
\ No newline at end of file diff --git a/src/profiling/test/TestTimelinePacketHandler.hpp b/src/profiling/test/TestTimelinePacketHandler.hpp new file mode 100644 index 0000000000..2902e5f89c --- /dev/null +++ b/src/profiling/test/TestTimelinePacketHandler.hpp @@ -0,0 +1,90 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include <armnn/profiling/ILocalPacketHandler.hpp> +#include <armnn/profiling/ITimelineDecoder.hpp> +#include "Packet.hpp" +#include "ProfilingUtils.hpp" +#include "TimelineCaptureCommandHandler.hpp" +#include "TimelineDirectoryCaptureCommandHandler.hpp" +#include "TimelineModel.hpp" + +#include <condition_variable> +#include <map> +#include <mutex> +#include <vector> + +namespace armnn +{ + +namespace profiling +{ + +// forward declaration of class +class TestTimelinePacketHandler; +class TimelineMessageDecoder : public ITimelineDecoder +{ +public: + TimelineMessageDecoder(TimelineModel& model) : m_PacketHandler(nullptr), m_TimelineModel(model) {} + virtual TimelineStatus CreateEntity(const Entity&) override; + virtual TimelineStatus CreateEventClass(const EventClass&) override; + virtual TimelineStatus CreateEvent(const Event&) override; + virtual TimelineStatus CreateLabel(const Label&) override; + virtual TimelineStatus CreateRelationship(const Relationship&) override; + void SetPacketHandler(TestTimelinePacketHandler* packetHandler) {m_PacketHandler = packetHandler;}; +private: + TestTimelinePacketHandler* m_PacketHandler; + TimelineModel& m_TimelineModel; +}; + +class TestTimelinePacketHandler : public ILocalPacketHandler +{ +public: + TestTimelinePacketHandler() : + m_Connection(nullptr), + m_InferenceCompleted(false), + m_DirectoryHeader(CreateTimelinePacketHeader(1, 0, 0, 0, 0, 0).first), + m_MessageHeader(CreateTimelinePacketHeader(1, 0, 1, 0, 0, 0).first), + m_MessageDecoder(m_TimelineModel), + m_Decoder(1, 1, 0, m_MessageDecoder), + m_DirectoryDecoder(1, 0, 0, m_Decoder, true) + { m_MessageDecoder.SetPacketHandler(this); } + + virtual std::vector<uint32_t> GetHeadersAccepted() override; // ILocalPacketHandler + + virtual void HandlePacket(const Packet& packet) override; // ILocalPacketHandler + + void Stop(); + + void WaitOnInferenceCompletion(unsigned int timeout); + void SetInferenceComplete(); + + const TimelineModel& GetTimelineModel() const {return m_TimelineModel;} + + virtual void SetConnection(IProfilingConnection* profilingConnection) override // ILocalPacketHandler + { + m_Connection = profilingConnection; + } + +private: + void ProcessDirectoryPacket(const Packet& packet); + void ProcessMessagePacket(const Packet& packet); + IProfilingConnection* m_Connection; + std::mutex m_InferenceCompletedMutex; + std::condition_variable m_InferenceCompletedConditionVariable; + bool m_InferenceCompleted; + TimelineModel m_TimelineModel; + uint32_t m_DirectoryHeader; + uint32_t m_MessageHeader; + TimelineMessageDecoder m_MessageDecoder; + timelinedecoder::TimelineCaptureCommandHandler m_Decoder; + timelinedecoder::TimelineDirectoryCaptureCommandHandler m_DirectoryDecoder; +}; + +} // namespace profiling + +} // namespace armnn
\ No newline at end of file diff --git a/src/profiling/test/TimelineModel.cpp b/src/profiling/test/TimelineModel.cpp new file mode 100644 index 0000000000..73aa0c5580 --- /dev/null +++ b/src/profiling/test/TimelineModel.cpp @@ -0,0 +1,57 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "TimelineModel.hpp" + +namespace armnn +{ + +namespace profiling +{ + +void TimelineModel::AddLabel(const ITimelineDecoder::Label& label) +{ + m_LabelMap.emplace(label.m_Guid, label); +} + +void TimelineModel::AddEntity(uint64_t guid) +{ + m_Entities.emplace(guid, guid); +} + +Entity* TimelineModel::findEntity(uint64_t id) +{ + auto iter = m_Entities.find(id); + if (iter != m_Entities.end()) + { + return &(iter->second); + } + else + { + return nullptr; + } +} + +void TimelineModel::AddRelationship(const ITimelineDecoder::Relationship& relationship) +{ + m_Relationships.emplace(relationship.m_Guid, relationship); +} + +ModelRelationship* TimelineModel::findRelationship(uint64_t id) +{ + auto iter = m_Relationships.find(id); + if (iter != m_Relationships.end()) + { + return &(iter->second); + } + else + { + return nullptr; + } +} + +} // namespace profiling + +} // namespace armnn
\ No newline at end of file diff --git a/src/profiling/test/TimelineModel.hpp b/src/profiling/test/TimelineModel.hpp new file mode 100644 index 0000000000..7b88d5fa2c --- /dev/null +++ b/src/profiling/test/TimelineModel.hpp @@ -0,0 +1,67 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include <armnn/profiling/ITimelineDecoder.hpp> + +#include <map> +#include <vector> + +namespace armnn +{ + +namespace profiling +{ +using LabelMap = std::map<uint64_t, ITimelineDecoder::Label>; +using Attribute = std::pair<std::string, std::string>; +using Attributes = std::map<std::string, Attribute>; +class Entity +{ +public: + Entity(uint64_t guid) : m_Guid(guid) {} + uint64_t GetGuid() {return m_Guid;} + void AddChild(Entity* child) + { + if (child != nullptr) + { + m_Children.push_back(child); + } + } + void AddAttribute(const std::string& type, const std::string& value) + { + Attribute attr(type, value); + m_Attributes.emplace(type, attr); + } +private: + uint64_t m_Guid; + Attributes m_Attributes; + std::vector<Entity*> m_Children; +}; +using Entities = std::map<uint64_t, Entity>; +struct ModelRelationship +{ + ModelRelationship(const ITimelineDecoder::Relationship& relationship) : m_Relationship(relationship) {} + ITimelineDecoder::Relationship m_Relationship; + std::vector<Entity*> m_RelatedEntities; +}; +using Relationships = std::map<uint64_t, ModelRelationship>; +class TimelineModel +{ +public: + void AddLabel(const ITimelineDecoder::Label& label); + void AddEntity(uint64_t guid); + Entity* findEntity(uint64_t id); + void AddRelationship(const ITimelineDecoder::Relationship& relationship); + ModelRelationship* findRelationship(uint64_t id); +private: + LabelMap m_LabelMap; + Entities m_Entities; + Relationships m_Relationships; +}; + +} // namespace profiling + +} // namespace armnn
\ No newline at end of file |