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