ArmNN
 21.08
TimelineModel.cpp
Go to the documentation of this file.
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 armnn
13 {
14 
15 namespace profiling
16 {
17 
18 void TimelineModel::AddLabel(const arm::pipe::ITimelineDecoder::Label& label)
19 {
20  m_LabelMap.emplace(label.m_Guid, label);
21 }
22 
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 
36 void TimelineModel::AddEntity(uint64_t guid)
37 {
38  m_Entities.emplace(guid, guid);
39 }
40 
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 
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 == arm::pipe::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 == armnn::profiling::LabelsAndEventClasses::CONNECTION_GUID)
67  {
68  HandleConnection(relationship);
69  }
70  else if (relationship.m_AttributeGuid == armnn::profiling::LabelsAndEventClasses::CHILD_GUID)
71  {
72  HandleChild(relationship);
73  }
74  else if (relationship.m_AttributeGuid == armnn::profiling::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 
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 (armnn::profiling::LabelsAndEventClasses::TYPE_LABEL.compare(*attribute) == 0 &&
132  armnn::profiling::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 
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 
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 
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 
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 
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 
275 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 
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 
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 
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 
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 
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 
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 (profiling::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 
374 std::string GetChildDescription(Entity* entity)
375 {
376  std::stringstream ss;
377  ss << " child: " << GetEntityDescription(*entity);
378  return ss.str();
379 }
380 
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 
389 std::string GetExecutionDescription(Entity* execution)
390 {
391  std::stringstream ss;
392  ss << " execution: " << GetEntityDescription(*execution);
393  return ss.str();
394 }
395 
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 profiling
404 
405 } // namespace armnn
uint64_t GetGuid() const
void AddEvent(EventObj *event)
std::string GetConnectionDescription(const Connection &connection)
EventObj * FindEvent(uint64_t id)
void AddLabel(const arm::pipe::ITimelineDecoder::Label &label)
const Attributes & GetAttributes() const
ModelRelationship * FindRelationship(uint64_t id)
Entity * FindEntity(uint64_t id)
std::string * FindLabel(uint64_t guid)
bool IsInferenceGuid(uint64_t guid) const
Copyright (c) 2021 ARM Limited and Contributors.
EventClassObj * FindEventClass(uint64_t id)
const Entities & GetEntities() const
void AddChild(Entity *child)
void AddEventClass(const arm::pipe::ITimelineDecoder::EventClass &eventClass)
void AddEvent(const arm::pipe::ITimelineDecoder::Event &event)
void AddConnection(const Connection &connection)
void AddAttribute(const std::string &type, const std::string &value)
const Entity * GetTail() const
std::string GetExecutionDescription(Entity *execution)
std::vector< std::string > GetModelDescription(const TimelineModel &model)
void SetEventClass(EventClassObj *evtClass)
std::string GetEntityDescription(const Entity &entity)
std::string GetEventDescription(EventObj *event)
void AddExecution(Entity *execution)
const Entity * GetHead() const
void AddRelationship(const arm::pipe::ITimelineDecoder::Relationship &relationship)
std::string GetChildDescription(Entity *entity)