aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSadik Armagan <sadik.armagan@arm.com>2021-01-13 15:56:51 +0000
committerSadik Armagan <sadik.armagan@arm.com>2021-01-13 15:56:51 +0000
commitb3021435ad91e494af01ca0778915877dc0780c0 (patch)
tree176bff8eafd8f6a2679d3569cbd640400b10a9ef
parentf36e10b8947fe5f0984e7428c2d5d5d7fe18007e (diff)
downloadandroid-nn-driver-b3021435ad91e494af01ca0778915877dc0780c0.tar.gz
IVGCVSW-4417 'Serialise ArmNN Model on android-nn-driver'
* Implemented serialization of the network on android-nn-driver !armnn:4850 Signed-off-by: Sadik Armagan <sadik.armagan@arm.com> Change-Id: I3caf07bd4d1d2a3068c58f0b344303c4cf977ca6
-rw-r--r--1.2/ArmnnDriverImpl.cpp16
-rw-r--r--1.3/ArmnnDriverImpl.cpp16
-rw-r--r--ArmnnDriverImpl.cpp16
-rw-r--r--ModelToINetworkConverter.cpp8
-rw-r--r--Utils.cpp64
-rw-r--r--Utils.hpp12
6 files changed, 104 insertions, 28 deletions
diff --git a/1.2/ArmnnDriverImpl.cpp b/1.2/ArmnnDriverImpl.cpp
index d5539bc..2ef51db 100644
--- a/1.2/ArmnnDriverImpl.cpp
+++ b/1.2/ArmnnDriverImpl.cpp
@@ -125,6 +125,11 @@ Return<V1_0::ErrorStatus> ArmnnDriverImpl::prepareArmnnModel_1_2(
return V1_0::ErrorStatus::NONE;
}
+ // Serialize the network graph to a .armnn file if an output directory
+ // has been specified in the drivers' arguments.
+ auto serializedNetworkFileName =
+ SerializeNetwork(*modelConverter.GetINetwork(), options.GetRequestInputsAndOutputsDumpDir());
+
// Optimize the network
armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
armnn::OptimizerOptions OptOptions;
@@ -195,11 +200,12 @@ Return<V1_0::ErrorStatus> ArmnnDriverImpl::prepareArmnnModel_1_2(
return V1_0::ErrorStatus::NONE;
}
- // Now that we have a networkId for the graph rename the dump file to use it
- // so that we can associate the graph file and the input/output tensor dump files
- RenameGraphDotFile(dotGraphFileName,
- options.GetRequestInputsAndOutputsDumpDir(),
- netId);
+ // Now that we have a networkId for the graph rename the exported files to use it
+ // so that we can associate the graph file and the input/output tensor exported files
+ RenameExportedFiles(serializedNetworkFileName,
+ dotGraphFileName,
+ options.GetRequestInputsAndOutputsDumpDir(),
+ netId);
std::unique_ptr<ArmnnPreparedModel_1_2<hal_1_2::HalPolicy>> preparedModel(
new ArmnnPreparedModel_1_2<hal_1_2::HalPolicy>(
diff --git a/1.3/ArmnnDriverImpl.cpp b/1.3/ArmnnDriverImpl.cpp
index 595df0a..c9f0340 100644
--- a/1.3/ArmnnDriverImpl.cpp
+++ b/1.3/ArmnnDriverImpl.cpp
@@ -136,6 +136,11 @@ Return<V1_3::ErrorStatus> ArmnnDriverImpl::prepareArmnnModel_1_3(
return V1_3::ErrorStatus::NONE;
}
+ // Serialize the network graph to a .armnn file if an output directory
+ // has been specified in the drivers' arguments.
+ auto serializedNetworkFileName =
+ SerializeNetwork(*modelConverter.GetINetwork(), options.GetRequestInputsAndOutputsDumpDir());
+
// Optimize the network
armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
armnn::OptimizerOptions OptOptions;
@@ -206,11 +211,12 @@ Return<V1_3::ErrorStatus> ArmnnDriverImpl::prepareArmnnModel_1_3(
return V1_3::ErrorStatus::NONE;
}
- // Now that we have a networkId for the graph rename the dump file to use it
- // so that we can associate the graph file and the input/output tensor dump files
- RenameGraphDotFile(dotGraphFileName,
- options.GetRequestInputsAndOutputsDumpDir(),
- netId);
+ // Now that we have a networkId for the graph rename the exported files to use it
+ // so that we can associate the graph file and the input/output tensor exported files
+ RenameExportedFiles(serializedNetworkFileName,
+ dotGraphFileName,
+ options.GetRequestInputsAndOutputsDumpDir(),
+ netId);
std::unique_ptr<ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>> preparedModel(
new ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>(
diff --git a/ArmnnDriverImpl.cpp b/ArmnnDriverImpl.cpp
index ef37cae..917370c 100644
--- a/ArmnnDriverImpl.cpp
+++ b/ArmnnDriverImpl.cpp
@@ -100,6 +100,11 @@ Return<V1_0::ErrorStatus> ArmnnDriverImpl<HalPolicy>::prepareModel(
return V1_0::ErrorStatus::NONE;
}
+ // Serialize the network graph to a .armnn file if an output directory
+ // has been specified in the drivers' arguments.
+ auto serializedNetworkFileName =
+ SerializeNetwork(*modelConverter.GetINetwork(), options.GetRequestInputsAndOutputsDumpDir());
+
// Optimize the network
armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
armnn::OptimizerOptions OptOptions;
@@ -169,11 +174,12 @@ Return<V1_0::ErrorStatus> ArmnnDriverImpl<HalPolicy>::prepareModel(
return V1_0::ErrorStatus::NONE;
}
- // Now that we have a networkId for the graph rename the dump file to use it
- // so that we can associate the graph file and the input/output tensor dump files
- RenameGraphDotFile(dotGraphFileName,
- options.GetRequestInputsAndOutputsDumpDir(),
- netId);
+ // Now that we have a networkId for the graph rename the exported files to use it
+ // so that we can associate the graph file and the input/output tensor exported files
+ RenameExportedFiles(serializedNetworkFileName,
+ dotGraphFileName,
+ options.GetRequestInputsAndOutputsDumpDir(),
+ netId);
sp<ArmnnPreparedModel<HalPolicy>> preparedModel(
new ArmnnPreparedModel<HalPolicy>(
diff --git a/ModelToINetworkConverter.cpp b/ModelToINetworkConverter.cpp
index e8cf8a8..c205a57 100644
--- a/ModelToINetworkConverter.cpp
+++ b/ModelToINetworkConverter.cpp
@@ -87,8 +87,9 @@ void ModelToINetworkConverter<HalPolicy>::Convert()
const HalOperand& operand = getMainModel(m_Model).operands[inputIndex];
ALOGV("ModelToINetworkConverter::Convert(): GetTensorInfoForOperand(operand)");
const armnn::TensorInfo& tensor = GetTensorInfoForOperand(operand);
- ALOGV("ModelToINetworkConverter::Convert(): m_Data.m_Network->AddInputLayer(i)");
- armnn::IConnectableLayer* layer = m_Data.m_Network->AddInputLayer(i);
+ const std::string layerName = "Input_" + std::to_string(i);
+ ALOGV("ModelToINetworkConverter::Convert(): m_Data.m_Network->AddInputLayer(i, layerName.c_str())");
+ armnn::IConnectableLayer* layer = m_Data.m_Network->AddInputLayer(i, layerName.c_str());
ALOGV("ModelToINetworkConverter::Convert(): layer->GetOutputSlot(0)");
armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
@@ -184,7 +185,8 @@ void ModelToINetworkConverter<HalPolicy>::Convert()
uint32_t outputIndex = getMainModel(m_Model).outputIndexes[i];
const HalOperand& operand = getMainModel(m_Model).operands[outputIndex];
const armnn::TensorInfo& tensor = GetTensorInfoForOperand(operand);
- armnn::IConnectableLayer* layer = m_Data.m_Network->AddOutputLayer(i);
+ const std::string layerName = "Output_" + std::to_string(i);
+ armnn::IConnectableLayer* layer = m_Data.m_Network->AddOutputLayer(i, layerName.c_str());
assert(m_Data.m_OutputSlotForOperand[outputIndex]);
m_Data.m_OutputSlotForOperand[outputIndex]->Connect(layer->GetInputSlot(0));
diff --git a/Utils.cpp b/Utils.cpp
index 895278a..53877ba 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -8,6 +8,7 @@
#include "Utils.hpp"
#include "Half.hpp"
+#include <armnnSerializer/ISerializer.hpp>
#include <armnnUtils/Permute.hpp>
#include <armnn/Utils.hpp>
@@ -22,8 +23,6 @@
#include <cstdio>
#include <time.h>
-
-
using namespace android;
using namespace android::hardware;
using namespace android::hidl::memory::V1_0;
@@ -572,6 +571,41 @@ std::string ExportNetworkGraphToDotFile(const armnn::IOptimizedNetwork& optimize
return fileName;
}
+std::string SerializeNetwork(const armnn::INetwork& network, const std::string& dumpDir)
+{
+ std::string fileName;
+ // The dump directory must exist in advance.
+ if (dumpDir.empty())
+ {
+ return fileName;
+ }
+
+ std::string timestamp = GetFileTimestamp();
+ if (timestamp.empty())
+ {
+ return fileName;
+ }
+
+ auto serializer(armnnSerializer::ISerializer::Create());
+
+ // Serialize the Network
+ serializer->Serialize(network);
+
+ // Set the name of the output .armnn file.
+ fs::path dumpPath = dumpDir;
+ fs::path tempFilePath = dumpPath / (timestamp + "_network.armnn");
+ fileName = tempFilePath.string();
+
+ // Save serialized network to a file
+ std::ofstream serializedFile(fileName, std::ios::out | std::ios::binary);
+ bool serialized = serializer->SaveSerializedToStream(serializedFile);
+ if (!serialized)
+ {
+ ALOGW("An error occurred when serializing to file %s", fileName.c_str());
+ }
+ return fileName;
+}
+
bool IsDynamicTensor(const armnn::TensorInfo& tensorInfo)
{
if (tensorInfo.GetShape().GetDimensionality() == armnn::Dimensionality::NotSpecified)
@@ -613,25 +647,37 @@ std::string GetFileTimestamp()
return ss.str();
}
-void RenameGraphDotFile(const std::string& oldName, const std::string& dumpDir, const armnn::NetworkId networkId)
+void RenameExportedFiles(const std::string& existingSerializedFileName,
+ const std::string& existingDotFileName,
+ const std::string& dumpDir,
+ const armnn::NetworkId networkId)
{
if (dumpDir.empty())
{
return;
}
- if (oldName.empty())
+ RenameFile(existingSerializedFileName, std::string("_network.armnn"), dumpDir, networkId);
+ RenameFile(existingDotFileName, std::string("_networkgraph.dot"), dumpDir, networkId);
+}
+
+void RenameFile(const std::string& existingName,
+ const std::string& extension,
+ const std::string& dumpDir,
+ const armnn::NetworkId networkId)
+{
+ if (existingName.empty() || dumpDir.empty())
{
return;
}
- fs::path dumpPath = dumpDir;
- const fs::path newFileName = dumpPath / (std::to_string(networkId) + "_networkgraph.dot");
- int iRet = rename(oldName.c_str(), newFileName.c_str());
+ fs::path dumpPath = dumpDir;
+ const fs::path newFileName = dumpPath / (std::to_string(networkId) + extension);
+ int iRet = rename(existingName.c_str(), newFileName.c_str());
if (iRet != 0)
{
std::stringstream ss;
- ss << "rename of [" << oldName << "] to [" << newFileName << "] failed with errno " << std::to_string(errno)
- << " : " << std::strerror(errno);
+ ss << "rename of [" << existingName << "] to [" << newFileName << "] failed with errno "
+ << std::to_string(errno) << " : " << std::strerror(errno);
ALOGW(ss.str().c_str());
}
}
diff --git a/Utils.hpp b/Utils.hpp
index e3b7d82..c4d89f7 100644
--- a/Utils.hpp
+++ b/Utils.hpp
@@ -135,7 +135,17 @@ void DumpJsonProfilingIfRequired(bool gpuProfilingEnabled,
std::string ExportNetworkGraphToDotFile(const armnn::IOptimizedNetwork& optimizedNetwork,
const std::string& dumpDir);
-void RenameGraphDotFile(const std::string& oldName, const std::string& dumpDir, const armnn::NetworkId networkId);
+std::string SerializeNetwork(const armnn::INetwork& network, const std::string& dumpDir);
+
+void RenameExportedFiles(const std::string& existingSerializedFileName,
+ const std::string& existingDotFileName,
+ const std::string& dumpDir,
+ const armnn::NetworkId networkId);
+
+void RenameFile(const std::string& existingName,
+ const std::string& extension,
+ const std::string& dumpDir,
+ const armnn::NetworkId networkId);
/// Checks if a tensor info represents a dynamic tensor
bool IsDynamicTensor(const armnn::TensorInfo& outputInfo);