• 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 "TimelineModel.hpp"
7 #include <LabelsAndEventClasses.hpp>
8 
9 #include <algorithm>
10 
11 namespace armnn
12 {
13 
14 namespace profiling
15 {
16 
AddLabel(const arm::pipe::ITimelineDecoder::Label & label)17 void TimelineModel::AddLabel(const arm::pipe::ITimelineDecoder::Label& label)
18 {
19     m_LabelMap.emplace(label.m_Guid, label);
20 }
21 
FindLabel(uint64_t guid)22 std::string* TimelineModel::FindLabel(uint64_t guid)
23 {
24     auto iter = m_LabelMap.find(guid);
25     if (iter != m_LabelMap.end())
26     {
27         return &iter->second.m_Name;
28     }
29     else
30     {
31         return nullptr;
32     }
33 }
34 
AddEntity(uint64_t guid)35 void TimelineModel::AddEntity(uint64_t guid)
36 {
37     m_Entities.emplace(guid, guid);
38 }
39 
FindEntity(uint64_t id)40 Entity* TimelineModel::FindEntity(uint64_t id)
41 {
42     auto iter = m_Entities.find(id);
43     if (iter != m_Entities.end())
44     {
45         return &(iter->second);
46     }
47     else
48     {
49         return nullptr;
50     }
51 }
52 
AddRelationship(const arm::pipe::ITimelineDecoder::Relationship & relationship)53 void TimelineModel::AddRelationship(const arm::pipe::ITimelineDecoder::Relationship& relationship)
54 {
55     m_Relationships.emplace(relationship.m_Guid, relationship);
56     if (relationship.m_RelationshipType == arm::pipe::ITimelineDecoder::RelationshipType::LabelLink)
57     {
58         HandleLabelLink(relationship);
59     }
60     else if (relationship.m_RelationshipType == arm::pipe::ITimelineDecoder::RelationshipType::RetentionLink)
61     {
62         // Take care of the special case of a connection between layers in ArmNN
63         // modelled by a retention link between two layer entities with an attribute GUID
64         // of connection
65         if (relationship.m_AttributeGuid == armnn::profiling::LabelsAndEventClasses::CONNECTION_GUID)
66         {
67             HandleConnection(relationship);
68         }
69         else if (relationship.m_AttributeGuid == armnn::profiling::LabelsAndEventClasses::CHILD_GUID)
70         {
71             HandleChild(relationship);
72         }
73         else if (relationship.m_AttributeGuid == armnn::profiling::LabelsAndEventClasses::EXECUTION_OF_GUID)
74         {
75             HandleExecutionOf(relationship);
76         }
77         else
78         {
79             // report unknown relationship type
80             std::stringstream ss;
81             ss << "Encountered a RetentionLink of unknown type [" << relationship.m_AttributeGuid << "]";
82             m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
83         }
84     }
85     else if (relationship.m_RelationshipType == arm::pipe::ITimelineDecoder::RelationshipType::ExecutionLink)
86     {
87         HandleExecutionLink(relationship);
88     }
89 }
90 
HandleLabelLink(const arm::pipe::ITimelineDecoder::Relationship & relationship)91 void TimelineModel::HandleLabelLink(const arm::pipe::ITimelineDecoder::Relationship& relationship)
92 {
93     Entity* entity = FindEntity(relationship.m_HeadGuid);
94     // we have a label attribute of an entity
95     std::string* value = nullptr;
96     std::string* attribute = nullptr;
97     value = FindLabel(relationship.m_TailGuid);
98     if (value == nullptr)
99     {
100         //report an error
101         std::stringstream ss;
102         ss << "could not find label link [" << relationship.m_Guid <<
103            "] value [" << relationship.m_TailGuid << "]";
104         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
105     }
106     if (relationship.m_AttributeGuid != 0)
107     {
108         attribute = FindLabel(relationship.m_AttributeGuid);
109         if (attribute == nullptr)
110         {
111             //report an error
112             std::stringstream ss;
113             ss << "could not find label link [" << relationship.m_Guid <<
114                "] attribute [" << relationship.m_AttributeGuid << "]";
115             m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
116         }
117     }
118     else
119     {
120         //report an error
121         std::stringstream ss;
122         ss << "label link [" << relationship.m_Guid << "] has a zero attribute guid";
123         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
124     }
125     if (entity != nullptr && attribute != nullptr && value != nullptr)
126     {
127         entity->AddAttribute(*attribute, *value);
128         // if the attribute is 'type' and the value is 'inference'
129         // we need to cache the entity guid as an inference
130         if (armnn::profiling::LabelsAndEventClasses::TYPE_LABEL.compare(*attribute) == 0 &&
131             armnn::profiling::LabelsAndEventClasses::INFERENCE.compare(*value) == 0)
132         {
133             m_InferenceGuids.push_back(relationship.m_HeadGuid);
134         }
135     }
136 
137     if (entity == nullptr)
138     {
139         //report an error
140         std::stringstream ss;
141         ss << "could not find label link [" << relationship.m_Guid <<
142            "] entity [" << relationship.m_HeadGuid << "] ";
143         if (value != nullptr)
144         {
145             ss << "value [" << *value << "] ";
146         }
147         if (attribute != nullptr)
148         {
149             ss << "attribute [" << *attribute << "] ";
150         }
151         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
152     }
153 }
154 
HandleConnection(const arm::pipe::ITimelineDecoder::Relationship & relationship)155 void TimelineModel::HandleConnection(const arm::pipe::ITimelineDecoder::Relationship& relationship)
156 {
157     Entity* outputLayer = FindEntity(relationship.m_HeadGuid);
158     if (outputLayer == nullptr)
159     {
160         std::stringstream ss;
161         ss << "could not find output entity [" << relationship.m_HeadGuid << "]";
162         ss << " of connection [" << relationship.m_Guid << "]";
163         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
164         return;
165     }
166     Entity* inputLayer = FindEntity(relationship.m_TailGuid);
167     if (inputLayer == nullptr)
168     {
169         std::stringstream ss;
170         ss << "could not find input entity [" << relationship.m_TailGuid << "]";
171         ss << " of connection [" << relationship.m_Guid << "]";
172         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
173         return;
174     }
175     Connection connection(relationship.m_Guid, outputLayer, inputLayer);
176     outputLayer->AddConnection(connection);
177 }
178 
HandleChild(const arm::pipe::ITimelineDecoder::Relationship & relationship)179 void TimelineModel::HandleChild(const arm::pipe::ITimelineDecoder::Relationship& relationship)
180 {
181     Entity* parentEntity = FindEntity(relationship.m_HeadGuid);
182     if (parentEntity == nullptr)
183     {
184         std::stringstream ss;
185         ss << "could not find parent entity [" << relationship.m_HeadGuid << "]";
186         ss << " of child relationship [" << relationship.m_Guid << "]";
187         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
188         return;
189     }
190     Entity* childEntity = FindEntity(relationship.m_TailGuid);
191     if (childEntity == nullptr)
192     {
193         std::stringstream ss;
194         ss << "could not find child entity [" << relationship.m_TailGuid << "]";
195         ss << " of child relationship [" << relationship.m_Guid << "]";
196         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
197         return;
198     }
199     parentEntity->AddChild(childEntity);
200 }
201 
HandleExecutionOf(const arm::pipe::ITimelineDecoder::Relationship & relationship)202 void TimelineModel::HandleExecutionOf(const arm::pipe::ITimelineDecoder::Relationship& relationship)
203 {
204     Entity* parentEntity = FindEntity(relationship.m_HeadGuid);
205     if (parentEntity == nullptr)
206     {
207         std::stringstream ss;
208         ss << "could not find parent entity [" << relationship.m_HeadGuid << "]";
209         ss << " of execution relationship [" << relationship.m_Guid << "]";
210         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
211         return;
212     }
213     Entity* executedEntity = FindEntity(relationship.m_TailGuid);
214     if (executedEntity == nullptr)
215     {
216         std::stringstream ss;
217         ss << "could not find executed entity [" << relationship.m_TailGuid << "]";
218         ss << " of execution relationship [" << relationship.m_Guid << "]";
219         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
220         return;
221     }
222     parentEntity->AddExecution(executedEntity);
223 }
224 
HandleExecutionLink(const arm::pipe::ITimelineDecoder::Relationship & relationship)225 void TimelineModel::HandleExecutionLink(const arm::pipe::ITimelineDecoder::Relationship& relationship)
226 {
227     // entityGuid,
228     Entity* parentEntity = FindEntity(relationship.m_HeadGuid);
229     if (parentEntity == nullptr)
230     {
231         std::stringstream ss;
232         ss << "could not find entity [" << relationship.m_HeadGuid << "]";
233         ss << " of ExecutionLink [" << relationship.m_Guid << "]";
234         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
235         return;
236     }
237     // eventGuid,
238     EventObj* eventObj = FindEvent(relationship.m_TailGuid);
239     if (eventObj == nullptr)
240     {
241         std::stringstream ss;
242         ss << "could not find event [" << relationship.m_TailGuid << "]";
243         ss << " of ExecutionLink [" << relationship.m_Guid << "]";
244         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
245         return;
246     }
247     // eventClassGuid
248     EventClassObj* eventClassObj = FindEventClass(relationship.m_AttributeGuid);
249     if (eventClassObj == nullptr)
250     {
251         std::stringstream ss;
252         ss << "could not find event class [" << relationship.m_TailGuid << "]";
253         ss << " of ExecutionLink [" << relationship.m_Guid << "]";
254         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
255         return;
256     }
257     eventObj->SetEventClass(eventClassObj);
258     parentEntity->AddEvent(eventObj);
259 }
260 
FindRelationship(uint64_t id)261 ModelRelationship* TimelineModel::FindRelationship(uint64_t id)
262 {
263     auto iter = m_Relationships.find(id);
264     if (iter != m_Relationships.end())
265     {
266         return &(iter->second);
267     }
268     else
269     {
270         return nullptr;
271     }
272 }
273 
IsInferenceGuid(uint64_t guid) const274 bool TimelineModel::IsInferenceGuid(uint64_t guid) const
275 {
276     auto it = std::find(m_InferenceGuids.begin(), m_InferenceGuids.end(), guid);
277     return it != m_InferenceGuids.end();
278 }
279 
AddEventClass(const arm::pipe::ITimelineDecoder::EventClass & eventClass)280 void TimelineModel::AddEventClass(const arm::pipe::ITimelineDecoder::EventClass& eventClass)
281 {
282     std::string* eventClassName = FindLabel(eventClass.m_NameGuid);
283     if (eventClassName != nullptr)
284     {
285         EventClassObj eventClassObj(eventClass.m_Guid, *eventClassName);
286         m_EventClasses.emplace(eventClassObj.GetGuid(), eventClassObj);
287     }
288     else
289     {
290         std::stringstream ss;
291         ss << "could not find name [" << eventClass.m_NameGuid << "]";
292         ss << " of of event class  [" << eventClass.m_Guid << "]";
293         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
294     }
295 }
296 
FindEventClass(uint64_t id)297 EventClassObj* TimelineModel::FindEventClass(uint64_t id)
298 {
299     auto iter = m_EventClasses.find(id);
300     if (iter != m_EventClasses.end())
301     {
302         return &(iter->second);
303     }
304     else
305     {
306         return nullptr;
307     }
308 }
309 
AddEvent(const arm::pipe::ITimelineDecoder::Event & event)310 void TimelineModel::AddEvent(const arm::pipe::ITimelineDecoder::Event& event)
311 {
312     EventObj evt(event.m_Guid, event.m_TimeStamp, event.m_ThreadId);
313     m_Events.emplace(event.m_Guid, evt);
314 }
315 
FindEvent(uint64_t id)316 EventObj* TimelineModel::FindEvent(uint64_t id)
317 {
318     auto iter = m_Events.find(id);
319     if (iter != m_Events.end())
320     {
321         return &(iter->second);
322     }
323     else
324     {
325         return nullptr;
326     }
327 }
328 
GetModelDescription(const TimelineModel & model)329 std::vector<std::string> GetModelDescription(const TimelineModel& model)
330 {
331     std::vector<std::string> desc;
332     for (auto& entry : model.GetEntities())
333     {
334         auto& entity = entry.second;
335         desc.push_back(GetEntityDescription(entity));
336         for (auto& connection : entity.GetConnections())
337         {
338             desc.push_back(GetConnectionDescription(connection));
339         }
340         for (auto child : entity.GetChildren())
341         {
342             desc.push_back(GetChildDescription(child));
343         }
344         for (auto execution : entity.GetExecutions())
345         {
346             desc.push_back(GetExecutionDescription(execution));
347         }
348         for (auto event : entity.GetEvents())
349         {
350             desc.push_back(GetEventDescription(event));
351         }
352     }
353     return desc;
354 }
355 
GetEntityDescription(const Entity & entity)356 std::string GetEntityDescription(const Entity& entity)
357 {
358     std::stringstream ss;
359     ss << "Entity [" << entity.GetGuid() << "]";
360     for (auto& attributeEntry : entity.GetAttributes())
361     {
362         if (profiling::LabelsAndEventClasses::PROCESS_ID_LABEL == attributeEntry.second.first)
363         {
364             ss << " " << attributeEntry.second.first << " = [processId]";
365         }
366         else {
367             ss << " " << attributeEntry.second.first << " = " << attributeEntry.second.second;
368         }
369     }
370     return ss.str();
371 }
372 
GetChildDescription(Entity * entity)373 std::string GetChildDescription(Entity* entity)
374 {
375     std::stringstream ss;
376     ss << "   child: " << GetEntityDescription(*entity);
377     return ss.str();
378 }
379 
GetConnectionDescription(const Connection & connection)380 std::string GetConnectionDescription(const Connection& connection)
381 {
382     std::stringstream ss;
383     ss << "   connection [" << connection.GetGuid() << "] from entity [";
384     ss << connection.GetHead()->GetGuid() << "] to entity [" << connection.GetTail()->GetGuid() << "]";
385     return ss.str();
386 }
387 
GetExecutionDescription(Entity * execution)388 std::string GetExecutionDescription(Entity* execution)
389 {
390     std::stringstream ss;
391     ss << "   execution: " << GetEntityDescription(*execution);
392     return ss.str();
393 }
394 
GetEventDescription(EventObj * event)395 std::string GetEventDescription(EventObj* event)
396 {
397     std::stringstream ss;
398     ss << "   event: [" << event->GetGuid() << "] class [" << event->GetEventClass() << "]";
399     return ss.str();
400 }
401 
402 } // namespace profiling
403 
404 } // namespace armnn