From f7713212f080771e0c6d53d939da59a9ea2e7da0 Mon Sep 17 00:00:00 2001 From: Jim Flynn Date: Tue, 14 Jul 2020 09:50:59 +0100 Subject: IVGCVSW-5101 Add a SOL/EOL and a process ID label to Network Change-Id: I6261f46404a3aab5c069bca40586994d31d26fe8 Signed-off-by: Jim Flynn --- src/armnn/LoadedNetwork.cpp | 13 +++++ src/armnn/LoadedNetwork.hpp | 2 + src/armnn/Runtime.cpp | 14 ++++++ src/armnn/test/RuntimeTests.cpp | 40 ++++++++++++++- src/profiling/LabelsAndEventClasses.cpp | 3 ++ src/profiling/LabelsAndEventClasses.hpp | 2 + src/profiling/TimelineUtilityMethods.cpp | 4 ++ src/profiling/TimelineUtilityMethods.hpp | 2 +- .../test/FileOnlyProfilingDecoratorTests.cpp | 57 +++++++++++----------- src/profiling/test/ProfilingTestUtils.cpp | 45 +++++++++++++++-- src/profiling/test/TimelineModel.cpp | 8 ++- src/profiling/test/TimelineUtilityMethodsTests.cpp | 10 +++- 12 files changed, 161 insertions(+), 39 deletions(-) diff --git a/src/armnn/LoadedNetwork.cpp b/src/armnn/LoadedNetwork.cpp index 0dd75aa649..593539d3ee 100644 --- a/src/armnn/LoadedNetwork.cpp +++ b/src/armnn/LoadedNetwork.cpp @@ -7,6 +7,7 @@ #include "Layer.hpp" #include "Graph.hpp" #include "Network.hpp" +#include #include "Runtime.hpp" #include "Profiling.hpp" #include "HeapProfiling.hpp" @@ -196,6 +197,13 @@ LoadedNetwork::LoadedNetwork(std::unique_ptr net, if (timelineUtils) { timelineUtils->CreateTypedEntity(networkGuid, LabelsAndEventClasses::NETWORK_GUID); + // Mark the network with a start of life event + timelineUtils->RecordEvent(networkGuid, LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS); + // and with the process ID + int processID = armnnUtils::Processes::GetCurrentId(); + std::stringstream ss; + ss << processID; + timelineUtils->MarkEntityWithLabel(networkGuid, ss.str(), LabelsAndEventClasses::PROCESS_ID_GUID); } //Then create workloads. @@ -298,6 +306,11 @@ void LoadedNetwork::SendNetworkStructure() timelineUtils->Commit(); } +profiling::ProfilingGuid LoadedNetwork::GetNetworkGuid() +{ + return m_OptimizedNetwork->GetGuid(); +} + TensorInfo LoadedNetwork::GetInputTensorInfo(LayerBindingId layerId) const { for (auto&& inputLayer : m_OptimizedNetwork->GetGraph().GetInputLayers()) diff --git a/src/armnn/LoadedNetwork.hpp b/src/armnn/LoadedNetwork.hpp index 8c2103019e..39b6089ac9 100644 --- a/src/armnn/LoadedNetwork.hpp +++ b/src/armnn/LoadedNetwork.hpp @@ -58,6 +58,8 @@ public: void SendNetworkStructure(); + profiling::ProfilingGuid GetNetworkGuid(); + private: void AllocateWorkingMemory(std::lock_guard& lock); diff --git a/src/armnn/Runtime.cpp b/src/armnn/Runtime.cpp index 28e2df22ab..63f39c6529 100644 --- a/src/armnn/Runtime.cpp +++ b/src/armnn/Runtime.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -117,9 +118,22 @@ Status Runtime::UnloadNetwork(NetworkId networkId) return Status::Failure; } + std::unique_ptr timelineUtils = + profiling::TimelineUtilityMethods::GetTimelineUtils(m_ProfilingService); { std::lock_guard lockGuard(m_Mutex); + // If timeline recording is on mark the Network end of life + if (timelineUtils) + { + auto search = m_LoadedNetworks.find(networkId); + if (search != m_LoadedNetworks.end()) + { + profiling::ProfilingGuid networkGuid = search->second->GetNetworkGuid(); + timelineUtils->RecordEvent(networkGuid, + profiling::LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS); + } + } if (m_LoadedNetworks.erase(networkId) == 0) { ARMNN_LOG(warning) << "WARNING: Runtime::UnloadNetwork(): " << networkId << " not found!"; diff --git a/src/armnn/test/RuntimeTests.cpp b/src/armnn/test/RuntimeTests.cpp index 7e9acb7d79..12ec8b1ece 100644 --- a/src/armnn/test/RuntimeTests.cpp +++ b/src/armnn/test/RuntimeTests.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -414,7 +415,6 @@ BOOST_AUTO_TEST_CASE(ProfilingEnableCpuRef) BOOST_CHECK(readableBuffer != nullptr); unsigned int size = readableBuffer->GetSize(); - BOOST_CHECK(size == 772); const unsigned char* readableData = readableBuffer->GetReadableData(); BOOST_CHECK(readableData != nullptr); @@ -422,7 +422,7 @@ BOOST_AUTO_TEST_CASE(ProfilingEnableCpuRef) unsigned int offset = 0; // Verify Header - VerifyTimelineHeaderBinary(readableData, offset, 764); + VerifyTimelineHeaderBinary(readableData, offset, size - 8); BOOST_TEST_MESSAGE("HEADER OK"); // Post-optimisation network @@ -440,6 +440,42 @@ BOOST_AUTO_TEST_CASE(ProfilingEnableCpuRef) offset); BOOST_TEST_MESSAGE("NETWORK TYPE RELATIONSHIP OK"); + // Network - START OF LIFE + ProfilingGuid networkSolEventGuid = VerifyTimelineEventBinaryPacket(EmptyOptional(), + EmptyOptional(), + EmptyOptional(), + readableData, + offset); + BOOST_TEST_MESSAGE("NETWORK START OF LIFE EVENT OK"); + + // Network - START OF LIFE event relationship + VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink, + EmptyOptional(), + optNetGuid, + networkSolEventGuid, + LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS, + readableData, + offset); + BOOST_TEST_MESSAGE("NETWORK START OF LIFE RELATIONSHIP OK"); + + // Process ID Label + int processID = armnnUtils::Processes::GetCurrentId(); + std::stringstream ss; + ss << processID; + std::string processIdLabel = ss.str(); + VerifyTimelineLabelBinaryPacketData(EmptyOptional(), processIdLabel, readableData, offset); + BOOST_TEST_MESSAGE("PROCESS ID LABEL OK"); + + // Entity - Process ID relationship + VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink, + EmptyOptional(), + optNetGuid, + EmptyOptional(), + LabelsAndEventClasses::PROCESS_ID_GUID, + readableData, + offset); + BOOST_TEST_MESSAGE("NETWORK PROCESS ID RELATIONSHIP OK"); + // Input layer // Input layer entity VerifyTimelineEntityBinaryPacketData(input->GetGuid(), readableData, offset); diff --git a/src/profiling/LabelsAndEventClasses.cpp b/src/profiling/LabelsAndEventClasses.cpp index 6b6a190507..fe6d119c2f 100644 --- a/src/profiling/LabelsAndEventClasses.cpp +++ b/src/profiling/LabelsAndEventClasses.cpp @@ -21,6 +21,7 @@ std::string LabelsAndEventClasses::INDEX_LABEL("index"); std::string LabelsAndEventClasses::BACKENDID_LABEL("backendId"); std::string LabelsAndEventClasses::CHILD_LABEL("child"); std::string LabelsAndEventClasses::EXECUTION_OF_LABEL("execution_of"); +std::string LabelsAndEventClasses::PROCESS_ID_LABEL("processId"); ProfilingStaticGuid LabelsAndEventClasses::EMPTY_GUID(0); ProfilingStaticGuid LabelsAndEventClasses::NAME_GUID( @@ -35,6 +36,8 @@ ProfilingStaticGuid LabelsAndEventClasses::CHILD_GUID( m_GuidGenerator.GenerateStaticId(LabelsAndEventClasses::CHILD_LABEL)); ProfilingStaticGuid LabelsAndEventClasses::EXECUTION_OF_GUID( m_GuidGenerator.GenerateStaticId(LabelsAndEventClasses::EXECUTION_OF_LABEL)); +ProfilingStaticGuid LabelsAndEventClasses::PROCESS_ID_GUID( + m_GuidGenerator.GenerateStaticId(LabelsAndEventClasses::PROCESS_ID_LABEL)); // Common types std::string LabelsAndEventClasses::LAYER("layer"); diff --git a/src/profiling/LabelsAndEventClasses.hpp b/src/profiling/LabelsAndEventClasses.hpp index 835fc7923e..b06b9a1488 100644 --- a/src/profiling/LabelsAndEventClasses.hpp +++ b/src/profiling/LabelsAndEventClasses.hpp @@ -27,6 +27,7 @@ public: ARMNN_DLLEXPORT static std::string BACKENDID_LABEL; ARMNN_DLLEXPORT static std::string CHILD_LABEL; ARMNN_DLLEXPORT static std::string EXECUTION_OF_LABEL; + ARMNN_DLLEXPORT static std::string PROCESS_ID_LABEL; ARMNN_DLLEXPORT static ProfilingStaticGuid EMPTY_GUID; ARMNN_DLLEXPORT static ProfilingStaticGuid NAME_GUID; ARMNN_DLLEXPORT static ProfilingStaticGuid TYPE_GUID; @@ -34,6 +35,7 @@ public: ARMNN_DLLEXPORT static ProfilingStaticGuid BACKENDID_GUID; ARMNN_DLLEXPORT static ProfilingStaticGuid CHILD_GUID; ARMNN_DLLEXPORT static ProfilingStaticGuid EXECUTION_OF_GUID; + ARMNN_DLLEXPORT static ProfilingStaticGuid PROCESS_ID_GUID; // Common types ARMNN_DLLEXPORT static std::string LAYER; diff --git a/src/profiling/TimelineUtilityMethods.cpp b/src/profiling/TimelineUtilityMethods.cpp index fe5c6b1340..e72894a6ab 100644 --- a/src/profiling/TimelineUtilityMethods.cpp +++ b/src/profiling/TimelineUtilityMethods.cpp @@ -53,6 +53,10 @@ void TimelineUtilityMethods::SendWellKnownLabelsAndEventClasses(ISendTimelinePac timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::EXECUTION_OF_GUID, LabelsAndEventClasses::EXECUTION_OF_LABEL); + // Send the "process_id" label, this call throws in case of error + timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::PROCESS_ID_GUID, + LabelsAndEventClasses::PROCESS_ID_LABEL); + // Send the "layer" label, this call throws in case of error timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::LAYER_GUID, LabelsAndEventClasses::LAYER); diff --git a/src/profiling/TimelineUtilityMethods.hpp b/src/profiling/TimelineUtilityMethods.hpp index 857d82f267..80d5e8dffe 100644 --- a/src/profiling/TimelineUtilityMethods.hpp +++ b/src/profiling/TimelineUtilityMethods.hpp @@ -47,7 +47,7 @@ public: void CreateNamedTypedEntity(ProfilingGuid entityGuid, const std::string& name, ProfilingStaticGuid typeGuid); - void MarkEntityWithLabel(ProfilingGuid entityGuid, const std::string &labelName, ProfilingStaticGuid labelLinkGuid); + void MarkEntityWithLabel(ProfilingGuid entityGuid, const std::string& labelName, ProfilingStaticGuid labelLinkGuid); ProfilingStaticGuid DeclareLabel(const std::string& labelName); diff --git a/src/profiling/test/FileOnlyProfilingDecoratorTests.cpp b/src/profiling/test/FileOnlyProfilingDecoratorTests.cpp index 69ebe33188..f9df633a1c 100644 --- a/src/profiling/test/FileOnlyProfilingDecoratorTests.cpp +++ b/src/profiling/test/FileOnlyProfilingDecoratorTests.cpp @@ -114,39 +114,40 @@ BOOST_AUTO_TEST_CASE(TestFileOnlyProfiling) std::vector desc = GetModelDescription(model); std::vector expectedOutput; expectedOutput.push_back("Entity [0] name = input type = layer"); - expectedOutput.push_back(" connection [14] from entity [0] to entity [1]"); - expectedOutput.push_back(" child: Entity [23] backendId = " + backend.Get() + " type = workload"); + expectedOutput.push_back(" connection [17] from entity [0] to entity [1]"); + expectedOutput.push_back(" child: Entity [26] backendId = " + backend.Get() + " type = workload"); expectedOutput.push_back("Entity [1] name = Rsqrt type = layer"); - expectedOutput.push_back(" connection [22] from entity [1] to entity [2]"); - expectedOutput.push_back(" child: Entity [15] backendId = " + backend.Get() + " type = workload"); + expectedOutput.push_back(" connection [25] from entity [1] to entity [2]"); + expectedOutput.push_back(" child: Entity [18] backendId = " + backend.Get() + " type = workload"); expectedOutput.push_back("Entity [2] name = output type = layer"); - expectedOutput.push_back(" child: Entity [27] backendId = " + backend.Get() + " type = workload"); - expectedOutput.push_back("Entity [6] type = network"); + expectedOutput.push_back(" child: Entity [30] backendId = " + backend.Get() + " type = workload"); + expectedOutput.push_back("Entity [6] processId = [processId] type = network"); expectedOutput.push_back(" child: Entity [0] name = input type = layer"); expectedOutput.push_back(" child: Entity [1] name = Rsqrt type = layer"); expectedOutput.push_back(" child: Entity [2] name = output type = layer"); - expectedOutput.push_back(" execution: Entity [31] type = inference"); - expectedOutput.push_back("Entity [15] backendId = " + backend.Get() + " type = workload"); - expectedOutput.push_back(" execution: Entity [44] type = workload_execution"); - expectedOutput.push_back("Entity [23] backendId = " + backend.Get() + " type = workload"); - expectedOutput.push_back(" execution: Entity [36] type = workload_execution"); - expectedOutput.push_back("Entity [27] backendId = " + backend.Get() + " type = workload"); - expectedOutput.push_back(" execution: Entity [52] type = workload_execution"); - expectedOutput.push_back("Entity [31] type = inference"); - expectedOutput.push_back(" child: Entity [36] type = workload_execution"); - expectedOutput.push_back(" child: Entity [44] type = workload_execution"); - expectedOutput.push_back(" child: Entity [52] type = workload_execution"); - expectedOutput.push_back(" event: [34] class [start_of_life]"); - expectedOutput.push_back(" event: [60] class [end_of_life]"); - expectedOutput.push_back("Entity [36] type = workload_execution"); - expectedOutput.push_back(" event: [40] class [start_of_life]"); - expectedOutput.push_back(" event: [42] class [end_of_life]"); - expectedOutput.push_back("Entity [44] type = workload_execution"); - expectedOutput.push_back(" event: [48] class [start_of_life]"); - expectedOutput.push_back(" event: [50] class [end_of_life]"); - expectedOutput.push_back("Entity [52] type = workload_execution"); - expectedOutput.push_back(" event: [56] class [start_of_life]"); - expectedOutput.push_back(" event: [58] class [end_of_life]"); + expectedOutput.push_back(" execution: Entity [34] type = inference"); + expectedOutput.push_back(" event: [8] class [start_of_life]"); + expectedOutput.push_back("Entity [18] backendId = " + backend.Get() + " type = workload"); + expectedOutput.push_back(" execution: Entity [47] type = workload_execution"); + expectedOutput.push_back("Entity [26] backendId = " + backend.Get() + " type = workload"); + expectedOutput.push_back(" execution: Entity [39] type = workload_execution"); + expectedOutput.push_back("Entity [30] backendId = " + backend.Get() + " type = workload"); + expectedOutput.push_back(" execution: Entity [55] type = workload_execution"); + expectedOutput.push_back("Entity [34] type = inference"); + expectedOutput.push_back(" child: Entity [39] type = workload_execution"); + expectedOutput.push_back(" child: Entity [47] type = workload_execution"); + expectedOutput.push_back(" child: Entity [55] type = workload_execution"); + expectedOutput.push_back(" event: [37] class [start_of_life]"); + expectedOutput.push_back(" event: [63] class [end_of_life]"); + expectedOutput.push_back("Entity [39] type = workload_execution"); + expectedOutput.push_back(" event: [43] class [start_of_life]"); + expectedOutput.push_back(" event: [45] class [end_of_life]"); + expectedOutput.push_back("Entity [47] type = workload_execution"); + expectedOutput.push_back(" event: [51] class [start_of_life]"); + expectedOutput.push_back(" event: [53] class [end_of_life]"); + expectedOutput.push_back("Entity [55] type = workload_execution"); + expectedOutput.push_back(" event: [59] class [start_of_life]"); + expectedOutput.push_back(" event: [61] class [end_of_life]"); BOOST_TEST(CompareOutput(desc, expectedOutput)); } } diff --git a/src/profiling/test/ProfilingTestUtils.cpp b/src/profiling/test/ProfilingTestUtils.cpp index 2dae5cf52e..8050eaa508 100644 --- a/src/profiling/test/ProfilingTestUtils.cpp +++ b/src/profiling/test/ProfilingTestUtils.cpp @@ -8,8 +8,9 @@ #include #include -#include +#include #include +#include #include @@ -438,11 +439,9 @@ void VerifyPostOptimisationStructureTestImpl(armnn::BackendId backendId) profiling::BufferManager& bufferManager = profilingServiceHelper.GetProfilingBufferManager(); auto readableBuffer = bufferManager.GetReadableBuffer(); - // Profiling is enable, the post-optimisation structure should be created + // Profiling is enabled, the post-optimisation structure should be created BOOST_CHECK(readableBuffer != nullptr); - unsigned int size = readableBuffer->GetSize(); - BOOST_CHECK(size == 1124); const unsigned char* readableData = readableBuffer->GetReadableData(); BOOST_CHECK(readableData != nullptr); @@ -450,7 +449,7 @@ void VerifyPostOptimisationStructureTestImpl(armnn::BackendId backendId) unsigned int offset = 0; // Verify Header - VerifyTimelineHeaderBinary(readableData, offset, 1116); + VerifyTimelineHeaderBinary(readableData, offset, size - 8); BOOST_TEST_MESSAGE("HEADER OK"); // Post-optimisation network @@ -468,6 +467,42 @@ void VerifyPostOptimisationStructureTestImpl(armnn::BackendId backendId) offset); BOOST_TEST_MESSAGE("NETWORK TYPE RELATIONSHIP OK"); + // Network - START OF LIFE + ProfilingGuid networkSolEventGuid = VerifyTimelineEventBinaryPacket(EmptyOptional(), + EmptyOptional(), + EmptyOptional(), + readableData, + offset); + BOOST_TEST_MESSAGE("NETWORK START OF LIFE EVENT OK"); + + // Network - START OF LIFE event relationship + VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink, + EmptyOptional(), + optNetGuid, + networkSolEventGuid, + LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS, + readableData, + offset); + BOOST_TEST_MESSAGE("NETWORK START OF LIFE RELATIONSHIP OK"); + + // Process ID Label + int processID = armnnUtils::Processes::GetCurrentId(); + std::stringstream ss; + ss << processID; + std::string processIdLabel = ss.str(); + VerifyTimelineLabelBinaryPacketData(EmptyOptional(), processIdLabel, readableData, offset); + BOOST_TEST_MESSAGE("PROCESS ID LABEL OK"); + + // Entity - Process ID relationship + VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink, + EmptyOptional(), + optNetGuid, + EmptyOptional(), + LabelsAndEventClasses::PROCESS_ID_GUID, + readableData, + offset); + BOOST_TEST_MESSAGE("NETWORK PROCESS ID RELATIONSHIP OK"); + // Input layer // Input layer entity VerifyTimelineEntityBinaryPacketData(input->GetGuid(), readableData, offset); diff --git a/src/profiling/test/TimelineModel.cpp b/src/profiling/test/TimelineModel.cpp index d16a300d91..2e4fd06013 100644 --- a/src/profiling/test/TimelineModel.cpp +++ b/src/profiling/test/TimelineModel.cpp @@ -359,7 +359,13 @@ std::string GetEntityDescription(const Entity& entity) ss << "Entity [" << entity.GetGuid() << "]"; for (auto& attributeEntry : entity.GetAttributes()) { - ss << " " << attributeEntry.second.first << " = " << attributeEntry.second.second; + if (profiling::LabelsAndEventClasses::PROCESS_ID_LABEL == attributeEntry.second.first) + { + ss << " " << attributeEntry.second.first << " = [processId]"; + } + else { + ss << " " << attributeEntry.second.first << " = " << attributeEntry.second.second; + } } return ss.str(); } diff --git a/src/profiling/test/TimelineUtilityMethodsTests.cpp b/src/profiling/test/TimelineUtilityMethodsTests.cpp index 720b8b4f02..cbe3b797a3 100644 --- a/src/profiling/test/TimelineUtilityMethodsTests.cpp +++ b/src/profiling/test/TimelineUtilityMethodsTests.cpp @@ -82,7 +82,7 @@ BOOST_AUTO_TEST_CASE(SendWellKnownLabelsAndEventClassesTest) auto readableBuffer = mockBufferManager.GetReadableBuffer(); BOOST_CHECK(readableBuffer != nullptr); unsigned int size = readableBuffer->GetSize(); - BOOST_TEST(size == 432); + BOOST_TEST(size == 460); const unsigned char* readableData = readableBuffer->GetReadableData(); BOOST_CHECK(readableData != nullptr); @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(SendWellKnownLabelsAndEventClassesTest) unsigned int offset = 0; // Verify Header - VerifyTimelineHeaderBinary(readableData, offset, 424); + VerifyTimelineHeaderBinary(readableData, offset, 452); // First "well-known" label: NAME VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::NAME_GUID, @@ -128,6 +128,12 @@ BOOST_AUTO_TEST_CASE(SendWellKnownLabelsAndEventClassesTest) readableData, offset); + // Seventh "well-known" label: PROCESS_ID_LABEL + VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::PROCESS_ID_GUID, + LabelsAndEventClasses::PROCESS_ID_LABEL, + readableData, + offset); + // Well-known types // Layer VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::LAYER_GUID, -- cgit v1.2.1