1 // 2 // Copyright © 2020 Arm Ltd and Contributors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 // 5 6 #include "TestTimelinePacketHandler.hpp" 7 #include "IProfilingConnection.hpp" 8 #include <LabelsAndEventClasses.hpp> 9 10 #include <chrono> 11 #include <iostream> 12 13 namespace armnn 14 { 15 16 namespace profiling 17 { 18 GetHeadersAccepted()19std::vector<uint32_t> TestTimelinePacketHandler::GetHeadersAccepted() 20 { 21 std::vector<uint32_t> headers; 22 headers.push_back(m_DirectoryHeader); // message directory 23 headers.push_back(m_MessageHeader); // message 24 return headers; 25 } 26 HandlePacket(const arm::pipe::Packet & packet)27void TestTimelinePacketHandler::HandlePacket(const arm::pipe::Packet& packet) 28 { 29 if (packet.GetHeader() == m_DirectoryHeader) 30 { 31 ProcessDirectoryPacket(packet); 32 } 33 else if (packet.GetHeader() == m_MessageHeader) 34 { 35 ProcessMessagePacket(packet); 36 } 37 else 38 { 39 std::stringstream ss; 40 ss << "Received a packet with unknown header [" << packet.GetHeader() << "]"; 41 throw armnn::Exception(ss.str()); 42 } 43 } 44 Stop()45void TestTimelinePacketHandler::Stop() 46 { 47 m_Connection->Close(); 48 } 49 WaitOnInferenceCompletion(unsigned int timeout)50void TestTimelinePacketHandler::WaitOnInferenceCompletion(unsigned int timeout) 51 { 52 std::unique_lock<std::mutex> lck(m_InferenceCompletedMutex); 53 54 auto start = std::chrono::high_resolution_clock::now(); 55 // Here we we will go back to sleep after a spurious wake up if 56 // m_InferenceCompleted is not yet true. 57 if (!m_InferenceCompletedConditionVariable.wait_for(lck, 58 std::chrono::milliseconds(timeout), 59 [&]{return m_InferenceCompleted == true;})) 60 { 61 auto finish = std::chrono::high_resolution_clock::now(); 62 std::chrono::duration<double, std::milli> elapsed = finish - start; 63 std::stringstream ss; 64 ss << "Timed out waiting on inference completion for " << elapsed.count() << " ms"; 65 throw armnn::TimeoutException(ss.str()); 66 } 67 return; 68 } 69 SetInferenceComplete()70void TestTimelinePacketHandler::SetInferenceComplete() 71 { 72 { // only lock when we are updating the inference completed variable 73 std::unique_lock<std::mutex> lck(m_InferenceCompletedMutex); 74 m_InferenceCompleted = true; 75 } 76 m_InferenceCompletedConditionVariable.notify_one(); 77 } 78 ProcessDirectoryPacket(const arm::pipe::Packet & packet)79void TestTimelinePacketHandler::ProcessDirectoryPacket(const arm::pipe::Packet& packet) 80 { 81 m_DirectoryDecoder(packet); 82 } 83 ProcessMessagePacket(const arm::pipe::Packet & packet)84void TestTimelinePacketHandler::ProcessMessagePacket(const arm::pipe::Packet& packet) 85 { 86 m_Decoder(packet); 87 } 88 89 // TimelineMessageDecoder functions CreateEntity(const Entity & entity)90arm::pipe::ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateEntity(const Entity& entity) 91 { 92 m_TimelineModel.AddEntity(entity.m_Guid); 93 return arm::pipe::ITimelineDecoder::TimelineStatus::TimelineStatus_Success; 94 } 95 CreateEventClass(const arm::pipe::ITimelineDecoder::EventClass & eventClass)96arm::pipe::ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateEventClass( 97 const arm::pipe::ITimelineDecoder::EventClass& eventClass) 98 { 99 m_TimelineModel.AddEventClass(eventClass); 100 return arm::pipe::ITimelineDecoder::TimelineStatus::TimelineStatus_Success; 101 } 102 CreateEvent(const arm::pipe::ITimelineDecoder::Event & event)103arm::pipe::ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateEvent( 104 const arm::pipe::ITimelineDecoder::Event& event) 105 { 106 m_TimelineModel.AddEvent(event); 107 return arm::pipe::ITimelineDecoder::TimelineStatus::TimelineStatus_Success; 108 } 109 CreateLabel(const arm::pipe::ITimelineDecoder::Label & label)110arm::pipe::ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateLabel( 111 const arm::pipe::ITimelineDecoder::Label& label) 112 { 113 m_TimelineModel.AddLabel(label); 114 return arm::pipe::ITimelineDecoder::TimelineStatus::TimelineStatus_Success; 115 } 116 CreateRelationship(const arm::pipe::ITimelineDecoder::Relationship & relationship)117arm::pipe::ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateRelationship( 118 const arm::pipe::ITimelineDecoder::Relationship& relationship) 119 { 120 m_TimelineModel.AddRelationship(relationship); 121 // check to see if this is an execution link to an inference of event class end of life 122 // if so the inference has completed so send out a notification... 123 if (relationship.m_RelationshipType == RelationshipType::ExecutionLink && 124 m_TimelineModel.IsInferenceGuid(relationship.m_HeadGuid)) 125 { 126 ProfilingStaticGuid attributeGuid(relationship.m_AttributeGuid); 127 if (attributeGuid == armnn::profiling::LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS) 128 { 129 if (m_PacketHandler != nullptr) 130 { 131 m_PacketHandler->SetInferenceComplete(); 132 } 133 } 134 } 135 return arm::pipe::ITimelineDecoder::TimelineStatus::TimelineStatus_Success; 136 } 137 138 } // namespace profiling 139 140 } // namespace armnn