From 0de4712098d4cb9ab66fce6f2f65e783b18bfa37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89anna=20=C3=93=20Cath=C3=A1in?= Date: Wed, 1 Apr 2020 15:40:12 +0100 Subject: MLECO-756 First cut of adding JSONTimelineDecoder and tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ibcd5fdefb5dda3ac3f2a5ff6d6eca618c27c538b Signed-off-by: Éanna Ó Catháin --- src/timelineDecoder/JSONTimelineDecoder.cpp | 406 ++++++++++++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 src/timelineDecoder/JSONTimelineDecoder.cpp (limited to 'src/timelineDecoder/JSONTimelineDecoder.cpp') diff --git a/src/timelineDecoder/JSONTimelineDecoder.cpp b/src/timelineDecoder/JSONTimelineDecoder.cpp new file mode 100644 index 0000000000..520995afe9 --- /dev/null +++ b/src/timelineDecoder/JSONTimelineDecoder.cpp @@ -0,0 +1,406 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "JSONTimelineDecoder.hpp" +#include "../profiling/ProfilingUtils.hpp" + +#include +#include + +namespace armnn +{ +namespace timelinedecoder +{ + +static const char *const CONNECTION = "connection"; +static const char *const BACKEND_ID = "backendId"; +static const char *const NAME = "name"; +static const char *const TYPE = "type"; +static const char *const WORKLOAD = "workload"; +static const char *const WORKLOAD_EXECUTION = "workload_execution"; +static const char *const INFERENCE = "inference"; +static const char *const LAYER = "layer"; +static const char *const ENTITY = "Entity"; +static const char *const EVENTCLASS = "EventClass"; +static const char *const EVENT = "Event"; + +JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateEntity(const Entity& entity) +{ + JSONEntity jsonEntity(entity.m_Guid); + jsonEntity.SetType(ENTITY); + this->m_Model.jsonEntities.insert({entity.m_Guid, jsonEntity}); + return TimelineStatus::TimelineStatus_Success; +} + +JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateEventClass(const EventClass& eventClass) +{ + JSONEntity jsonEntity(eventClass.m_Guid); + jsonEntity.SetType(EVENTCLASS); + this->m_Model.eventClasses.insert({eventClass.m_Guid, eventClass}); + this->m_Model.jsonEntities.insert({eventClass.m_Guid, jsonEntity}); + return TimelineStatus::TimelineStatus_Success; +} + +JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateEvent(const Event& event) +{ + JSONEntity jsonEntity(event.m_Guid); + jsonEntity.SetType(EVENT); + this->m_Model.events.insert({event.m_Guid, event}); + this->m_Model.jsonEntities.insert({jsonEntity.GetGuid(), jsonEntity}); + return TimelineStatus::TimelineStatus_Success; +} + +JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateLabel(const Label& label) +{ + this->m_Model.labels.insert({label.m_Guid, label}); + return TimelineStatus::TimelineStatus_Success; +} + +JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateRelationship(const Relationship& relationship) +{ + if (relationship.m_RelationshipType == ITimelineDecoder::RelationshipType::RetentionLink) + { + HandleRetentionLink(relationship); + } + else if (relationship.m_RelationshipType == ITimelineDecoder::RelationshipType::LabelLink) + { + HandleLabelLink(relationship); + } + else if (relationship.m_RelationshipType == ITimelineDecoder::RelationshipType::ExecutionLink) + { + HandleExecutionLink(relationship); + } + else + { + /* + * TODO Handle DataLink + */ + m_Model.relationships.insert({relationship.m_Guid, relationship}); + } + + return TimelineStatus::TimelineStatus_Success; +} + + +void JSONTimelineDecoder::HandleExecutionLink(const ITimelineDecoder::Relationship& relationship) +{ + uint64_t tailGuid = relationship.m_TailGuid; + uint64_t headGuid = relationship.m_HeadGuid; + + if (m_Model.jsonEntities.count(relationship.m_HeadGuid) != 0) + { + JSONEntity& tailJSONEntity = m_Model.jsonEntities.at(tailGuid); + JSONEntity& headJSONEntity = m_Model.jsonEntities.at(headGuid); + tailJSONEntity.SetParent(headJSONEntity); + m_Model.jsonEntities.insert({headGuid, headJSONEntity}); + m_Model.relationships.insert({relationship.m_Guid, relationship}); + } + else + { + /* + * TODO Add some protection against packet ordering issues + */ + m_Model.relationships.insert({relationship.m_Guid, relationship}); + } +} + +void JSONTimelineDecoder::HandleLabelLink(const ITimelineDecoder::Relationship& relationship) +{ + if (m_Model.labels.count(relationship.m_TailGuid) != 0) + { + if (m_Model.labels.at(relationship.m_TailGuid).m_Name == CONNECTION) + { + HandleConnectionLabel(relationship); + } + else if (m_Model.labels.at(relationship.m_TailGuid).m_Name == BACKEND_ID) + { + HandleBackendIdLabel(relationship); + } + else if (m_Model.labels.at(relationship.m_TailGuid).m_Name == NAME) + { + HandleNameLabel(relationship); + } + else if (m_Model.labels.at(relationship.m_TailGuid).m_Name == TYPE) + { + HandleTypeLabel(relationship); + } + else + { + /* + * TODO Add some protection against packet ordering issues + */ + m_Model.relationships.insert({relationship.m_Guid, relationship}); + } + } else + { + /* + * TODO Add some protection against packet ordering issues + */ + m_Model.relationships.insert({relationship.m_Guid, relationship}); + } +} + +void JSONTimelineDecoder::HandleTypeLabel(const ITimelineDecoder::Relationship& relationship) +{ + if (m_Model.relationships.count(relationship.m_HeadGuid) != 0) + { + Relationship labelRelation = m_Model.relationships.at(relationship.m_HeadGuid); + if (m_Model.jsonEntities.count(labelRelation.m_HeadGuid) != 0) + { + JSONEntity& headEntity = m_Model.jsonEntities.at(labelRelation.m_HeadGuid); + std::string type = m_Model.labels.at(labelRelation.m_TailGuid).m_Name; + headEntity.SetType(type); + } + } + else + { + /* + * TODO Add some protection against packet ordering issues + */ + m_Model.relationships.insert({relationship.m_Guid, relationship}); + } +} + +void JSONTimelineDecoder::HandleNameLabel(const ITimelineDecoder::Relationship& relationship) +{ + if (m_Model.relationships.count(relationship.m_HeadGuid) != 0) + { + Relationship labelRelation = m_Model.relationships.at(relationship.m_HeadGuid); + JSONEntity& headEntity = m_Model.jsonEntities.at(labelRelation.m_HeadGuid); + std::string name = m_Model.labels.at(labelRelation.m_TailGuid).m_Name; + headEntity.SetName(name); + } + else + { + /* + * TODO Add some protection against packet ordering issues + */ + m_Model.relationships.insert({relationship.m_Guid, relationship}); + } +} + +void JSONTimelineDecoder::HandleBackendIdLabel(const ITimelineDecoder::Relationship& relationship) +{ + if (m_Model.relationships.count(relationship.m_HeadGuid) != 0) + { + Relationship labelRelation = m_Model.relationships.at(relationship.m_HeadGuid); + JSONEntity& headEntity = m_Model.jsonEntities.at(labelRelation.m_HeadGuid); + std::string backendName = m_Model.labels.at(labelRelation.m_TailGuid).m_Name; + headEntity.extendedData.insert({BACKEND_ID, backendName}); + } + else + { + /* + * TODO Add some protection against packet ordering issues + */ + m_Model.relationships.insert({relationship.m_Guid, relationship}); + } +} + +void JSONTimelineDecoder::HandleConnectionLabel(const ITimelineDecoder::Relationship& relationship) +{ + if (m_Model.relationships.count(relationship.m_HeadGuid) != 0) + { + Relationship retentionRelation = m_Model.relationships.at(relationship.m_HeadGuid); + JSONEntity& headEntity = m_Model.jsonEntities.at(retentionRelation.m_HeadGuid); + JSONEntity& tailEntity = m_Model.jsonEntities.at(retentionRelation.m_TailGuid); + headEntity.AddConnection(headEntity, tailEntity); + } + else + { + /* + * TODO Add some protection against packet ordering issues + */ + m_Model.relationships.insert({relationship.m_Guid, relationship}); + } +} + +void JSONTimelineDecoder::HandleRetentionLink(const ITimelineDecoder::Relationship& relationship) +{ + if (m_Model.jsonEntities.count(relationship.m_TailGuid) != 0 && m_Model.jsonEntities + .count(relationship.m_HeadGuid) != 0) + { + JSONEntity& tailJSONEntity = m_Model.jsonEntities.at(relationship.m_TailGuid); + JSONEntity& headJSONEntity = m_Model.jsonEntities.at(relationship.m_HeadGuid); + tailJSONEntity.SetParent(headJSONEntity); + m_Model.jsonEntities.insert({relationship.m_HeadGuid, headJSONEntity}); + m_Model.relationships.insert({relationship.m_Guid, relationship}); + } + else + { + /* + * TODO Add some protection against packet ordering issues + */ + m_Model.relationships.insert({relationship.m_Guid, relationship}); + } +} + +void JSONTimelineDecoder::JSONEntity::SetParent(JSONEntity& parent) +{ + parent.childEntities.push_back(GetGuid()); +} + +void JSONTimelineDecoder::PrintJSON(JSONTimelineDecoder::JSONEntity& rootEntity) +{ + std::string jsonString = GetJSONString(rootEntity); + std::ofstream outfile; + outfile.open(this->outputJSONFile); + outfile << jsonString; +} + +std::string JSONTimelineDecoder::GetJSONString(JSONTimelineDecoder::JSONEntity& rootEntity) +{ + int counter = 0; + std::string json; + json.append("{\n"); + if(rootEntity.GetType() != "") + { + json.append("\tArmNN"); + json.append(": {\n"); + + for (uint64_t childEntityId : rootEntity.childEntities) + { + JSONEntity& childEntity = this->m_Model.jsonEntities.at(childEntityId); + json.append(GetJSONEntityString(childEntity, counter)); + } + } + json.append("}\n"); + return json; +} + +std::string JSONTimelineDecoder::GetJSONEntityString(JSONTimelineDecoder::JSONEntity& entity, int& counter) +{ + std::string jsonEntityString; + if(entity.GetType() == LAYER) + { + return GetLayerJSONString(entity, counter, jsonEntityString); + } + else if (entity.GetType() == WORKLOAD) + { + return GetWorkloadJSONString(entity, counter, jsonEntityString); + } + else if (entity.GetType() == WORKLOAD_EXECUTION) + { + return GetWorkloadExecutionJSONString(entity, jsonEntityString); + } + else if (entity.GetType() == INFERENCE) + { + return jsonEntityString; + } + else + { + for (uint64_t child_entity_id : entity.childEntities) + { + JSONEntity& childEntity = this->m_Model.jsonEntities.at(child_entity_id); + jsonEntityString.append(GetJSONEntityString(childEntity, ++counter)); + } + return jsonEntityString; + } +} + +std::string JSONTimelineDecoder::GetWorkloadExecutionJSONString(const JSONTimelineDecoder::JSONEntity& entity, + std::string& jsonEntityString) const +{ + if(entity.childEntities.size() < 2) + { + throw Exception("Workload Execution Entity Packet does not have the expected Event packets attached"); + } + JSONEntity jsonEventOne = entity.childEntities[0]; + JSONEntity jsonEventTwo = entity.childEntities[1]; + + Event event1 = m_Model.events.at(jsonEventOne.GetGuid()); + Event event2 = m_Model.events.at(jsonEventTwo.GetGuid()); + + uint64_t wall_clock_time = event2.m_TimeStamp - event1.m_TimeStamp; + jsonEntityString.append("\t\t\t"); + jsonEntityString.append("raw : ["); + jsonEntityString.append(std::to_string(wall_clock_time)); + jsonEntityString.append("], \n"); + jsonEntityString.append("\t\t\t"); + jsonEntityString.append("unit : us,\n"); + jsonEntityString.append("\t\t\t"); + jsonEntityString.append("}\n"); + + return jsonEntityString; +} + +std::string JSONTimelineDecoder::GetWorkloadJSONString(const JSONTimelineDecoder::JSONEntity& entity, int& counter, + std::string& jsonEntityString) +{ + jsonEntityString.append("\t\t\t"); + jsonEntityString.append("backendId :"); + jsonEntityString.append(entity.extendedData.at(BACKEND_ID)); + jsonEntityString.append(",\n"); + for (uint64_t child_entity_id : entity.childEntities) + { + JSONEntity &childEntity = m_Model.jsonEntities.at(child_entity_id); + jsonEntityString.append(GetJSONEntityString(childEntity, ++counter)); + } + return jsonEntityString; +} + +std::string JSONTimelineDecoder::GetLayerJSONString(JSONTimelineDecoder::JSONEntity& entity, int& counter, + std::string& jsonEntityString) +{ + jsonEntityString.append("\t\t"); + jsonEntityString.append(entity.GetName()); + jsonEntityString.append("_"); + jsonEntityString.append(std::to_string(counter)); + jsonEntityString.append(": {\n"); + jsonEntityString.append("\t\t\t"); + jsonEntityString.append("type: Measurement,\n"); + for (uint64_t child_entity_id : entity.childEntities) + { + JSONEntity& childEntity = m_Model.jsonEntities.at(child_entity_id); + jsonEntityString.append(GetJSONEntityString(childEntity, ++counter)); + } + return jsonEntityString; +} + +void JSONTimelineDecoder::JSONEntity::AddConnection(JSONEntity& headEntity, JSONEntity& connectedEntity) +{ + std::vector::iterator it = std::find(headEntity.childEntities.begin(), + headEntity.childEntities.end(), connectedEntity.GetGuid()); + headEntity.childEntities.erase(it); + headEntity.connected_entities.push_back(connectedEntity.m_Guid); +} + +uint64_t JSONTimelineDecoder::JSONEntity::GetGuid() +{ + return m_Guid; +} + +const JSONTimelineDecoder::Model &JSONTimelineDecoder::GetModel() +{ + return m_Model; +} + +void JSONTimelineDecoder::SetOutgoingCaptureFile(const std::string& outgoingCaptureFile) +{ + this->outputJSONFile = outgoingCaptureFile; +} + +void JSONTimelineDecoder::JSONEntity::SetName(std::string entityName) +{ + this->name = entityName; +} + +std::string JSONTimelineDecoder::JSONEntity::GetName() +{ + return this->name; +} + +void JSONTimelineDecoder::JSONEntity::SetType(std::string entityType) +{ + this->type = entityType; +} + +std::string JSONTimelineDecoder::JSONEntity::GetType() +{ + return this->type; +} + +} +} \ No newline at end of file -- cgit v1.2.1