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