ArmNN
 21.02
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"
8 
9 #include <algorithm>
10 
11 namespace armnn
12 {
13 
14 namespace profiling
15 {
16 
17 void TimelineModel::AddLabel(const arm::pipe::ITimelineDecoder::Label& label)
18 {
19  m_LabelMap.emplace(label.m_Guid, label);
20 }
21 
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 
35 void TimelineModel::AddEntity(uint64_t guid)
36 {
37  m_Entities.emplace(guid, guid);
38 }
39 
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 
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 
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 &&
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 
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 
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 
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 
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 
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 
274 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 
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 
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 
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 
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 
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 
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 
373 std::string GetChildDescription(Entity* entity)
374 {
375  std::stringstream ss;
376  ss << " child: " << GetEntityDescription(*entity);
377  return ss.str();
378 }
379 
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 
388 std::string GetExecutionDescription(Entity* execution)
389 {
390  std::stringstream ss;
391  ss << " execution: " << GetEntityDescription(*execution);
392  return ss.str();
393 }
394 
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
uint64_t GetGuid() const
void AddEvent(EventObj *event)
static ARMNN_DLLEXPORT std::string TYPE_LABEL
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)
static ARMNN_DLLEXPORT ProfilingStaticGuid CONNECTION_GUID
const Entities & GetEntities() const
void AddChild(Entity *child)
void AddEventClass(const arm::pipe::ITimelineDecoder::EventClass &eventClass)
void AddEvent(const arm::pipe::ITimelineDecoder::Event &event)
static ARMNN_DLLEXPORT ProfilingStaticGuid EXECUTION_OF_GUID
void AddConnection(const Connection &connection)
void AddAttribute(const std::string &type, const std::string &value)
const Entity * GetTail() const
static ARMNN_DLLEXPORT std::string PROCESS_ID_LABEL
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)
static ARMNN_DLLEXPORT std::string INFERENCE
std::string GetChildDescription(Entity *entity)
static ARMNN_DLLEXPORT ProfilingStaticGuid CHILD_GUID