aboutsummaryrefslogtreecommitdiff
path: root/src/profiling/test
diff options
context:
space:
mode:
authorJim Flynn <jim.flynn@arm.com>2020-03-29 17:48:26 +0100
committerfinn.williams <finn.williams@arm.com>2020-04-27 16:38:55 +0000
commit4e755a50e35a1f5ac1b011dc4baf89e6d97f116e (patch)
tree9660dba96819145e4f1bfe34e4482dca211ffc26 /src/profiling/test
parent303980c502c721f13d65e7087be6c0758df65044 (diff)
downloadarmnn-4e755a50e35a1f5ac1b011dc4baf89e6d97f116e.tar.gz
IVGCVSW-4595 Add IFileOnlyPacketHandlers to file only profiling connection
Change-Id: Ib49a8cbbf323da4109cdab9750e6c4d276e484b7 Signed-off-by: Jim Flynn <jim.flynn@arm.com>
Diffstat (limited to 'src/profiling/test')
-rw-r--r--src/profiling/test/FileOnlyProfilingDecoratorTests.cpp68
-rw-r--r--src/profiling/test/PrintPacketHeaderHandler.cpp31
-rw-r--r--src/profiling/test/PrintPacketHeaderHandler.hpp26
-rw-r--r--src/profiling/test/TestTimelinePacketHandler.cpp132
-rw-r--r--src/profiling/test/TestTimelinePacketHandler.hpp90
-rw-r--r--src/profiling/test/TimelineModel.cpp57
-rw-r--r--src/profiling/test/TimelineModel.hpp67
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