blob: d16a300d91357324f2bfb45a671d05fd74a6a7c0 [file] [log] [blame]
Jim Flynn4e755a52020-03-29 17:48:26 +01001//
Jim Flynn6398a982020-05-27 17:05:21 +01002// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
Jim Flynn4e755a52020-03-29 17:48:26 +01003// SPDX-License-Identifier: MIT
4//
5
6#include "TimelineModel.hpp"
Jim Flynn6398a982020-05-27 17:05:21 +01007#include <LabelsAndEventClasses.hpp>
8
9#include <algorithm>
Jim Flynn4e755a52020-03-29 17:48:26 +010010
11namespace armnn
12{
13
14namespace profiling
15{
16
17void TimelineModel::AddLabel(const ITimelineDecoder::Label& label)
18{
19 m_LabelMap.emplace(label.m_Guid, label);
20}
21
Jim Flynn6398a982020-05-27 17:05:21 +010022std::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
Jim Flynn4e755a52020-03-29 17:48:26 +010035void TimelineModel::AddEntity(uint64_t guid)
36{
37 m_Entities.emplace(guid, guid);
38}
39
Jim Flynn6398a982020-05-27 17:05:21 +010040Entity* TimelineModel::FindEntity(uint64_t id)
Jim Flynn4e755a52020-03-29 17:48:26 +010041{
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
53void TimelineModel::AddRelationship(const ITimelineDecoder::Relationship& relationship)
54{
55 m_Relationships.emplace(relationship.m_Guid, relationship);
Jim Flynn6398a982020-05-27 17:05:21 +010056 if (relationship.m_RelationshipType == ITimelineDecoder::RelationshipType::LabelLink)
57 {
58 HandleLabelLink(relationship);
59 }
60 else if (relationship.m_RelationshipType == 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(armnnProfiling::ProfilingException(ss.str()));
83 }
84 }
85 else if (relationship.m_RelationshipType == ITimelineDecoder::RelationshipType::ExecutionLink)
86 {
87 HandleExecutionLink(relationship);
88 }
Jim Flynn4e755a52020-03-29 17:48:26 +010089}
90
Jim Flynn6398a982020-05-27 17:05:21 +010091void TimelineModel::HandleLabelLink(const 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(armnnProfiling::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(armnnProfiling::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(armnnProfiling::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(armnnProfiling::ProfilingException(ss.str()));
152 }
153}
154
155void TimelineModel::HandleConnection(const 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(armnnProfiling::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(armnnProfiling::ProfilingException(ss.str()));
173 return;
174 }
175 Connection connection(relationship.m_Guid, outputLayer, inputLayer);
176 outputLayer->AddConnection(connection);
177}
178
179void TimelineModel::HandleChild(const 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(armnnProfiling::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(armnnProfiling::ProfilingException(ss.str()));
197 return;
198 }
199 parentEntity->AddChild(childEntity);
200}
201
202void TimelineModel::HandleExecutionOf(const 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(armnnProfiling::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(armnnProfiling::ProfilingException(ss.str()));
220 return;
221 }
222 parentEntity->AddExecution(executedEntity);
223}
224
225void TimelineModel::HandleExecutionLink(const 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(armnnProfiling::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(armnnProfiling::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(armnnProfiling::ProfilingException(ss.str()));
255 return;
256 }
257 eventObj->SetEventClass(eventClassObj);
258 parentEntity->AddEvent(eventObj);
259}
260
261ModelRelationship* TimelineModel::FindRelationship(uint64_t id)
Jim Flynn4e755a52020-03-29 17:48:26 +0100262{
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
Jim Flynn6398a982020-05-27 17:05:21 +0100274bool 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
280void TimelineModel::AddEventClass(const 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(armnnProfiling::ProfilingException(ss.str()));
294 }
295}
296
297EventClassObj* 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
310void TimelineModel::AddEvent(const 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
316EventObj* 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
329std::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
356std::string GetEntityDescription(const Entity& entity)
357{
358 std::stringstream ss;
359 ss << "Entity [" << entity.GetGuid() << "]";
360 for (auto& attributeEntry : entity.GetAttributes())
361 {
362 ss << " " << attributeEntry.second.first << " = " << attributeEntry.second.second;
363 }
364 return ss.str();
365}
366
367std::string GetChildDescription(Entity* entity)
368{
369 std::stringstream ss;
370 ss << " child: " << GetEntityDescription(*entity);
371 return ss.str();
372}
373
374std::string GetConnectionDescription(const Connection& connection)
375{
376 std::stringstream ss;
377 ss << " connection [" << connection.GetGuid() << "] from entity [";
378 ss << connection.GetHead()->GetGuid() << "] to entity [" << connection.GetTail()->GetGuid() << "]";
379 return ss.str();
380}
381
382std::string GetExecutionDescription(Entity* execution)
383{
384 std::stringstream ss;
385 ss << " execution: " << GetEntityDescription(*execution);
386 return ss.str();
387}
388
389std::string GetEventDescription(EventObj* event)
390{
391 std::stringstream ss;
392 ss << " event: [" << event->GetGuid() << "] class [" << event->GetEventClass() << "]";
393 return ss.str();
394}
395
Jim Flynn4e755a52020-03-29 17:48:26 +0100396} // namespace profiling
397
398} // namespace armnn