• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()19 std::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)27 void 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()45 void TestTimelinePacketHandler::Stop()
46 {
47     m_Connection->Close();
48 }
49 
WaitOnInferenceCompletion(unsigned int timeout)50 void 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()70 void 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)79 void TestTimelinePacketHandler::ProcessDirectoryPacket(const arm::pipe::Packet& packet)
80 {
81     m_DirectoryDecoder(packet);
82 }
83 
ProcessMessagePacket(const arm::pipe::Packet & packet)84 void TestTimelinePacketHandler::ProcessMessagePacket(const arm::pipe::Packet& packet)
85 {
86     m_Decoder(packet);
87 }
88 
89 // TimelineMessageDecoder functions
CreateEntity(const Entity & entity)90 arm::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)96 arm::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)103 arm::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)110 arm::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)117 arm::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