aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCathal Corbett <cathal.corbett@arm.com>2021-12-13 13:03:22 +0000
committerCathal Corbett <cathal.corbett@arm.com>2021-12-14 14:09:55 +0000
commit18655b8d326f6109c6fedacf42b46dc4bc942324 (patch)
tree79a4cff6e46ea41f404a693ac3a9de2787498f06
parenta097d2a0ed8e30d5aaf6d29ec18d0c39201b7b67 (diff)
downloadarmnn-18655b8d326f6109c6fedacf42b46dc4bc942324.tar.gz
IVGCVSW-6630 Add new method AddPrecompiledLayer() to INetwork
* Add new method AddPrecompiledLayer() to INetwork with Comments noting it is for backend users. * Added unit test to SubgraphViewTests.cpp. * Bug fix and code refactor in Graph.cpp specifically around Graph::SubstituteSubgraph(SubgraphView& subgraph, IConnectableLayer* substituteLayer) Change-Id: If2d816e5109e48ce920bf92d8823b39130c23a16 Signed-off-by: Cathal Corbett <cathal.corbett@arm.com>
-rw-r--r--include/armnn/INetwork.hpp13
-rw-r--r--src/armnn/Graph.cpp17
-rw-r--r--src/armnn/Graph.hpp1
-rw-r--r--src/armnn/Network.cpp31
-rw-r--r--src/armnn/Network.hpp4
-rw-r--r--src/armnn/test/SubgraphViewTests.cpp85
6 files changed, 138 insertions, 13 deletions
diff --git a/include/armnn/INetwork.hpp b/include/armnn/INetwork.hpp
index 1d98821160..4da01a62db 100644
--- a/include/armnn/INetwork.hpp
+++ b/include/armnn/INetwork.hpp
@@ -225,6 +225,9 @@ class NetworkImpl;
using INetworkPtr = std::unique_ptr<INetwork, void(*)(INetwork* network)>;
using IOptimizedNetworkPtr = std::unique_ptr<IOptimizedNetwork, void(*)(IOptimizedNetwork* network)>;
+using CompiledBlobDeleter = std::function<void(const void*)>;
+using CompiledBlobPtr = std::unique_ptr<void, CompiledBlobDeleter>;
+
/// Main network class which provides the interface for building up a neural network.
/// This object is subsequently required by the IRuntime::Load() method.
class INetwork
@@ -413,6 +416,16 @@ public:
IConnectableLayer* AddPooling3dLayer(const Pooling3dDescriptor& pooling3dDescriptor,
const char* name = nullptr);
+ /// Adds a Precompiled layer to the network.
+ /// Method use is for backend users.
+ /// @param preCompiledDescriptor - PreCompiledDescriptor contains parameters for the Precompiled layer.
+ /// @param compiledBlobPtr - CompiledBlobPtr pre-compiled object set for the Precompiled layer.
+ /// @param backend - optional BackendId set for the Precompiled layer.
+ /// @return - Interface for configuring the layer.
+ IConnectableLayer* AddPrecompiledLayer(const PreCompiledDescriptor& preCompiledDescriptor,
+ CompiledBlobPtr& compiledBlobPtr,
+ const Optional<BackendId>& backend);
+
/// Adds an activation layer to the network.
/// @param activationDescriptor - ActivationDescriptor to configure the activation.
/// @param name - Optional name for the layer.
diff --git a/src/armnn/Graph.cpp b/src/armnn/Graph.cpp
index 0591bea99a..6d24e50bdc 100644
--- a/src/armnn/Graph.cpp
+++ b/src/armnn/Graph.cpp
@@ -435,8 +435,11 @@ void Graph::SubstituteSubgraph(SubgraphView& subgraph, IConnectableLayer* substi
{
ARMNN_ASSERT(substituteLayer != nullptr);
- ReplaceSubgraphConnections(subgraph, substituteLayer);
- EraseSubgraphLayers(subgraph);
+ // Create a new sub-graph with only the given layer, using
+ // the given sub-graph as a reference of which parent graph to use
+ SubgraphView substituteSubgraph(substituteLayer);
+
+ SubstituteSubgraph(subgraph, substituteSubgraph);
}
void Graph::SubstituteSubgraph(SubgraphView& subgraph, const SubgraphView& substituteSubgraph)
@@ -456,16 +459,6 @@ void Graph::SubstituteSubgraph(SubgraphView& subgraph, const SubgraphView& subst
TopologicalSort();
}
-void Graph::ReplaceSubgraphConnections(const SubgraphView& subgraph, IConnectableLayer* substituteLayer)
-{
- ARMNN_ASSERT(substituteLayer != nullptr);
-
- // Create a new sub-graph with only the given layer, using
- // the given sub-graph as a reference of which parent graph to use
- SubgraphView substituteSubgraph(substituteLayer);
- ReplaceSubgraphConnections(subgraph, substituteSubgraph);
-}
-
void Graph::ReplaceSubgraphConnections(const SubgraphView& subgraph, const SubgraphView& substituteSubgraph)
{
ARMNN_ASSERT_MSG(!substituteSubgraph.GetLayers().empty(), "New sub-graph used for substitution must not be empty");
diff --git a/src/armnn/Graph.hpp b/src/armnn/Graph.hpp
index 74aefb23ee..d49b5e513f 100644
--- a/src/armnn/Graph.hpp
+++ b/src/armnn/Graph.hpp
@@ -263,7 +263,6 @@ private:
std::unordered_set<LayerBindingId> m_OutputIds;
std::unordered_map<const Layer*, Iterator> m_PosInGraphMap;
- void ReplaceSubgraphConnections(const SubgraphView& subgraph, IConnectableLayer* substituteLayer);
void ReplaceSubgraphConnections(const SubgraphView& subgraph, const SubgraphView& substituteSubgraph);
void EraseSubgraphLayers(SubgraphView &subgraph);
diff --git a/src/armnn/Network.cpp b/src/armnn/Network.cpp
index 54d9ae2028..c6f3f914b5 100644
--- a/src/armnn/Network.cpp
+++ b/src/armnn/Network.cpp
@@ -214,6 +214,13 @@ IConnectableLayer* INetwork::AddPooling3dLayer(const Pooling3dDescriptor& poolin
return pNetworkImpl->AddPooling3dLayer(pooling3dDescriptor, name);
}
+IConnectableLayer* INetwork::AddPrecompiledLayer(const PreCompiledDescriptor& preCompiledDescriptor,
+ CompiledBlobPtr& compiledBlobPtr,
+ const Optional<BackendId>& backend)
+{
+ return pNetworkImpl->AddPrecompiledLayer(preCompiledDescriptor, compiledBlobPtr, backend);
+}
+
IConnectableLayer* INetwork::AddActivationLayer(const ActivationDescriptor& activationDescriptor,
const char* name)
{
@@ -2763,6 +2770,30 @@ IConnectableLayer* NetworkImpl::AddUnidirectionalSequenceLstmLayer(
return layer;
}
+IConnectableLayer* NetworkImpl::AddPrecompiledLayer(const PreCompiledDescriptor& preCompiledDescriptor,
+ CompiledBlobPtr& compiledBlobPtr,
+ const Optional<BackendId>& backend)
+{
+ // Method use is for backend users.
+ const auto layer = m_Graph->AddLayer<PreCompiledLayer>(preCompiledDescriptor, "pre-compiled");
+
+ // Assign the pre-compiled object to layer
+ // Pass only one compiled network, Arm NN does not handle multiple
+ // pre-compiled objects in a single pre-compiled layer currently
+ layer->SetPreCompiledObject(std::move(compiledBlobPtr));
+
+ if (backend.has_value())
+ {
+ layer->SetBackendId(backend.value());
+ }
+ else
+ {
+ layer->SetBackendId(layer->GetBackendHint().value());
+ }
+
+ return layer;
+}
+
ARMNN_NO_DEPRECATE_WARN_BEGIN
void NetworkImpl::Accept(ILayerVisitor& visitor) const
{
diff --git a/src/armnn/Network.hpp b/src/armnn/Network.hpp
index 959d88dbed..3fdc140099 100644
--- a/src/armnn/Network.hpp
+++ b/src/armnn/Network.hpp
@@ -170,6 +170,10 @@ public:
IConnectableLayer* AddPooling3dLayer(const Pooling3dDescriptor& pooling3dDescriptor,
const char* name = nullptr);
+ IConnectableLayer* AddPrecompiledLayer(const PreCompiledDescriptor& preCompiledDescriptor,
+ CompiledBlobPtr& compiledBlobPtr,
+ const Optional<BackendId>& backend);
+
IConnectableLayer* AddPreluLayer(const char* name = nullptr);
IConnectableLayer* AddQuantizeLayer(const char* name = nullptr);
diff --git a/src/armnn/test/SubgraphViewTests.cpp b/src/armnn/test/SubgraphViewTests.cpp
index d270787968..4e509be78b 100644
--- a/src/armnn/test/SubgraphViewTests.cpp
+++ b/src/armnn/test/SubgraphViewTests.cpp
@@ -168,6 +168,91 @@ TEST_CASE("SingleInputSingleOutput")
CHECK_EQ(preCompiledLayer->GetOutputSlot(0).GetConnection(0), subgraphOutputConn);
}
+TEST_CASE("SingleInputSingleOutputAddPrecompiledLayerSubstituteSubgraph1")
+{
+ // Construct graph.
+ Graph graph;
+
+ Layer* const inputLayer = graph.AddLayer<InputLayer>(0, "input");
+
+ Convolution2dDescriptor convDescriptor;
+ Layer* const convLayer1 = graph.AddLayer<Convolution2dLayer>(convDescriptor, "conv1");
+ Layer* const convLayer2 = graph.AddLayer<Convolution2dLayer>(convDescriptor, "conv2");
+
+ Layer* const outputLayer = graph.AddLayer<OutputLayer>(0, "output");
+
+ inputLayer->GetOutputSlot(0).Connect(convLayer1->GetInputSlot(0));
+ convLayer1->GetOutputSlot(0).Connect(convLayer2->GetInputSlot(0));
+ convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+
+ // Construct sub-graph
+ SubgraphViewSelector::SubgraphViewPtr subgraph = CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
+ CreateOutputsFrom({convLayer2}),
+ {});
+
+ // Save sub-graph connections for comparison after substitution
+ IOutputSlot* subgraphInputConn = subgraph->GetInputSlot(0)->GetConnection();
+ IInputSlot* subgraphOutputConn = subgraph->GetOutputSlot(0)->GetConnection(0);
+
+ PreCompiledDescriptor preCompiledDescriptor(1, 1);
+ CompiledBlobPtr compiledBlobPtr;
+ BackendId backend = Compute::CpuRef;
+
+ // Construct dummy pre-compiled layer
+ INetworkPtr network = INetwork::Create();
+ IConnectableLayer* preCompiledLayer = network->AddPrecompiledLayer(preCompiledDescriptor, compiledBlobPtr, backend);
+
+ // Substitute sub-graph with pre-compiled layer
+ graph.SubstituteSubgraph(*subgraph, preCompiledLayer);
+
+ // Check that connections are correct after substitution
+ CHECK_EQ(preCompiledLayer->GetInputSlot(0).GetConnection(), subgraphInputConn);
+ CHECK_EQ(preCompiledLayer->GetOutputSlot(0).GetConnection(0), subgraphOutputConn);
+}
+
+TEST_CASE("SingleInputSingleOutputAddPrecompiledLayerSubstituteSubgraph2")
+{
+ // Construct graph.
+ Graph graph;
+
+ Layer* const inputLayer = graph.AddLayer<InputLayer>(0, "input");
+
+ Convolution2dDescriptor convDescriptor;
+ Layer* const convLayer1 = graph.AddLayer<Convolution2dLayer>(convDescriptor, "conv1");
+ Layer* const convLayer2 = graph.AddLayer<Convolution2dLayer>(convDescriptor, "conv2");
+
+ Layer* const outputLayer = graph.AddLayer<OutputLayer>(0, "output");
+
+ inputLayer->GetOutputSlot(0).Connect(convLayer1->GetInputSlot(0));
+ convLayer1->GetOutputSlot(0).Connect(convLayer2->GetInputSlot(0));
+ convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+
+ // Construct sub-graph
+ SubgraphViewSelector::SubgraphViewPtr subgraph = CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
+ CreateOutputsFrom({convLayer2}),
+ {});
+
+ // Save sub-graph connections for comparison after substitution
+ IOutputSlot* subgraphInputConn = subgraph->GetInputSlot(0)->GetConnection();
+ IInputSlot* subgraphOutputConn = subgraph->GetOutputSlot(0)->GetConnection(0);
+
+ PreCompiledDescriptor preCompiledDescriptor(1, 1);
+ CompiledBlobPtr compiledBlobPtr;
+ BackendId backend = Compute::CpuRef;
+
+ // Construct dummy pre-compiled layer
+ INetworkPtr network = INetwork::Create();
+ IConnectableLayer* preCompiledLayer = network->AddPrecompiledLayer(preCompiledDescriptor, compiledBlobPtr, backend);
+ SubgraphView substituteSubgraph(preCompiledLayer);
+
+ // Substitute sub-graph with pre-compiled layer
+ graph.SubstituteSubgraph(*subgraph, substituteSubgraph);
+
+ // Check that connections are correct after substitution
+ CHECK_EQ(preCompiledLayer->GetInputSlot(0).GetConnection(), subgraphInputConn);
+ CHECK_EQ(preCompiledLayer->GetOutputSlot(0).GetConnection(0), subgraphOutputConn);
+}
+
TEST_CASE("SingleInputSingleOutputSubstituteGraph")
{
// Construct graph