aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatteo Martincigh <matteo.martincigh@arm.com>2019-05-17 12:15:30 +0100
committerMatteo Martincigh <matteo.martincigh@arm.com>2019-05-17 12:55:14 +0100
commit88054f855792514f033d9c3bfe0d5e4e93cac528 (patch)
treea657f92350703d10538d0898d341eabe1325592f
parentaf000a907d16a330ca336044fadf13e3f73c35b8 (diff)
downloadarmnn-88054f855792514f033d9c3bfe0d5e4e93cac528.tar.gz
IVGCVSW-3030 Add a mock backend for unit testing
* Added a mock implementation of an ArmNN backend for unit testing * Implemented a mock version of OptimizeSubgraphView * Fixed a typo in the Optimization API Change-Id: Ic7acf7cc5c2a76a918e94cdc356baae7c7597a6d Signed-off-by: Matteo Martincigh <matteo.martincigh@arm.com>
-rw-r--r--src/backends/backendsCommon/IBackendInternal.hpp2
-rw-r--r--src/backends/backendsCommon/OptimizationViews.hpp2
-rw-r--r--src/backends/backendsCommon/test/CMakeLists.txt3
-rw-r--r--src/backends/backendsCommon/test/MockBackend.cpp249
-rw-r--r--src/backends/backendsCommon/test/MockBackend.hpp36
-rw-r--r--src/backends/backendsCommon/test/MockBackendId.hpp13
6 files changed, 303 insertions, 2 deletions
diff --git a/src/backends/backendsCommon/IBackendInternal.hpp b/src/backends/backendsCommon/IBackendInternal.hpp
index 826730a800..634e2aba94 100644
--- a/src/backends/backendsCommon/IBackendInternal.hpp
+++ b/src/backends/backendsCommon/IBackendInternal.hpp
@@ -83,7 +83,7 @@ public:
{
if (optSubgraph)
{
- result.AddSubstituion({subgraph, SubgraphView(*optSubgraph.get())});
+ result.AddSubstitution({subgraph, SubgraphView(*optSubgraph.get())});
}
else
{
diff --git a/src/backends/backendsCommon/OptimizationViews.hpp b/src/backends/backendsCommon/OptimizationViews.hpp
index e96c11aaba..a63fdf1ffb 100644
--- a/src/backends/backendsCommon/OptimizationViews.hpp
+++ b/src/backends/backendsCommon/OptimizationViews.hpp
@@ -30,7 +30,7 @@ public:
using Subgraphs = std::vector<SubgraphView>;
using Substitutions = std::vector<SubstitutionPair>;
- void AddSubstituion(SubstitutionPair&& substitution)
+ void AddSubstitution(SubstitutionPair&& substitution)
{
m_SuccesfulOptimizations.emplace_back(substitution);
}
diff --git a/src/backends/backendsCommon/test/CMakeLists.txt b/src/backends/backendsCommon/test/CMakeLists.txt
index bc190dd818..ab63679268 100644
--- a/src/backends/backendsCommon/test/CMakeLists.txt
+++ b/src/backends/backendsCommon/test/CMakeLists.txt
@@ -30,6 +30,9 @@ list(APPEND armnnBackendsCommonUnitTests_sources
LstmTestImpl.hpp
NormTestImpl.hpp
MergerTestImpl.hpp
+ MockBackend.cpp
+ MockBackend.hpp
+ MockBackendId.hpp
OptimizedNetworkTests.cpp
PermuteTestImpl.hpp
Pooling2dTestImpl.hpp
diff --git a/src/backends/backendsCommon/test/MockBackend.cpp b/src/backends/backendsCommon/test/MockBackend.cpp
new file mode 100644
index 0000000000..eca38cdddf
--- /dev/null
+++ b/src/backends/backendsCommon/test/MockBackend.cpp
@@ -0,0 +1,249 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "MockBackend.hpp"
+#include "MockBackendId.hpp"
+
+#include <backendsCommon/IBackendContext.hpp>
+#include <backendsCommon/IMemoryManager.hpp>
+#include <backendsCommon/BackendRegistry.hpp>
+
+#include <Optimizer.hpp>
+#include <SubgraphViewSelector.hpp>
+
+#include <boost/cast.hpp>
+
+#include <algorithm>
+
+namespace
+{
+
+bool IsLayerSupported(const armnn::Layer* layer)
+{
+ BOOST_ASSERT(layer != nullptr);
+
+ armnn::LayerType layerType = layer->GetType();
+ switch (layerType)
+ {
+ case armnn::LayerType::Input:
+ case armnn::LayerType::Output:
+ case armnn::LayerType::Convolution2d:
+ // Layer supported
+ return true;
+ default:
+ // Layer unsupported
+ return false;
+ }
+}
+
+bool IsLayerSupported(const armnn::Layer& layer)
+{
+ return IsLayerSupported(&layer);
+}
+
+bool IsLayerOptimizable(const armnn::Layer* layer)
+{
+ BOOST_ASSERT(layer != nullptr);
+
+ // A Layer is not optimizable if its name contains "unoptimizable"
+ const std::string layerName(layer->GetName());
+ bool optimizable = layerName.find("unoptimizable") == std::string::npos;
+
+ return optimizable;
+}
+
+bool IsLayerOptimizable(const armnn::Layer& layer)
+{
+ return IsLayerOptimizable(&layer);
+}
+
+} // Anonymous namespace
+
+namespace armnn
+{
+
+namespace
+{
+
+static BackendRegistry::StaticRegistryInitializer g_RegisterHelper
+{
+ BackendRegistryInstance(),
+ MockBackend::GetIdStatic(),
+ []()
+ {
+ return IBackendInternalUniquePtr(new MockBackend);
+ }
+};
+
+}
+
+const BackendId& MockBackend::GetIdStatic()
+{
+ static const BackendId s_Id{MockBackendId()};
+ return s_Id;
+}
+
+IBackendInternal::IWorkloadFactoryPtr MockBackend::CreateWorkloadFactory(
+ const IBackendInternal::IMemoryManagerSharedPtr& memoryManager) const
+{
+ return IWorkloadFactoryPtr{};
+}
+
+IBackendInternal::IBackendContextPtr MockBackend::CreateBackendContext(const IRuntime::CreationOptions&) const
+{
+ return IBackendContextPtr{};
+}
+
+IBackendInternal::IMemoryManagerUniquePtr MockBackend::CreateMemoryManager() const
+{
+ return IMemoryManagerUniquePtr{};
+}
+
+IBackendInternal::Optimizations MockBackend::GetOptimizations() const
+{
+ return Optimizations{};
+}
+
+IBackendInternal::ILayerSupportSharedPtr MockBackend::GetLayerSupport() const
+{
+ return ILayerSupportSharedPtr{};
+}
+
+OptimizationViews MockBackend::OptimizeSubgraphView(const SubgraphView& subgraph) const
+{
+ // Prepare the optimization views
+ OptimizationViews optimizationViews;
+
+ // Get the layers of the input sub-graph
+ const SubgraphView::Layers& subgraphLayers = subgraph.GetLayers();
+
+ // Parse the layers
+ SubgraphView::Layers supportedLayers;
+ SubgraphView::Layers unsupportedLayers;
+ SubgraphView::Layers untouchedLayers;
+ std::for_each(subgraphLayers.begin(),
+ subgraphLayers.end(),
+ [&](Layer* layer)
+ {
+ bool supported = IsLayerSupported(layer);
+ if (supported)
+ {
+ // Layer supported, check if it's optimizable
+ bool optimizable = IsLayerOptimizable(layer);
+ if (optimizable)
+ {
+ // Layer fully supported
+ supportedLayers.push_back(layer);
+ }
+ else
+ {
+ // Layer supported but not optimizable
+ untouchedLayers.push_back(layer);
+ }
+ }
+ else
+ {
+ // Layer unsupported
+ unsupportedLayers.push_back(layer);
+ }
+ });
+
+ // Check if there are supported layers
+ if (!supportedLayers.empty())
+ {
+ // Select the layers that are neither inputs or outputs, but that are optimizable
+ auto supportedSubgraphSelector = [](const Layer& layer)
+ {
+ return layer.GetType() != LayerType::Input &&
+ layer.GetType() != LayerType::Output &&
+ IsLayerSupported(layer) &&
+ IsLayerOptimizable(layer);
+ };
+
+ // Apply the subgraph selector to the supported layers to group them into sub-graphs were appropriate
+ SubgraphView mutableSubgraph(subgraph);
+ SubgraphViewSelector::Subgraphs supportedSubgraphs =
+ SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, supportedSubgraphSelector);
+
+ // Create a substitution pair for each supported sub-graph
+ std::for_each(supportedSubgraphs.begin(),
+ supportedSubgraphs.end(),
+ [&optimizationViews](const SubgraphView::SubgraphViewPtr& supportedSubgraph)
+ {
+ BOOST_ASSERT(supportedSubgraph != nullptr);
+
+ PreCompiledLayer* preCompiledLayer =
+ optimizationViews.GetGraph().AddLayer<PreCompiledLayer>(
+ PreCompiledDescriptor(supportedSubgraph->GetNumInputSlots(),
+ supportedSubgraph->GetNumOutputSlots()),
+ "pre-compiled");
+ preCompiledLayer->SetBackendId(MockBackendId());
+
+ SubgraphView substitutionSubgraph(*supportedSubgraph);
+ SubgraphView replacementSubgraph(preCompiledLayer);
+
+ optimizationViews.AddSubstitution({ substitutionSubgraph, replacementSubgraph });
+ });
+ }
+
+ // Check if there are unsupported layers
+ if (!unsupportedLayers.empty())
+ {
+ // Select the layers that are neither inputs or outputs, and are not optimizable
+ auto unsupportedSubgraphSelector = [](const Layer& layer)
+ {
+ return layer.GetType() != LayerType::Input &&
+ layer.GetType() != LayerType::Output &&
+ !IsLayerSupported(layer);
+ };
+
+ // Apply the subgraph selector to the unsupported layers to group them into sub-graphs were appropriate
+ SubgraphView mutableSubgraph(subgraph);
+ SubgraphViewSelector::Subgraphs unsupportedSubgraphs =
+ SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, unsupportedSubgraphSelector);
+
+ // Add each unsupported sub-graph to the list of failed sub-graphs in the optimizization views
+ std::for_each(unsupportedSubgraphs.begin(),
+ unsupportedSubgraphs.end(),
+ [&optimizationViews](const SubgraphView::SubgraphViewPtr& unsupportedSubgraph)
+ {
+ BOOST_ASSERT(unsupportedSubgraph != nullptr);
+
+ optimizationViews.AddFailedSubgraph(SubgraphView(*unsupportedSubgraph));
+ });
+ }
+
+ // Check if there are untouched layers
+ if (!untouchedLayers.empty())
+ {
+ // Select the layers that are neither inputs or outputs, that are supported but that and are not optimizable
+ auto untouchedSubgraphSelector = [](const Layer& layer)
+ {
+ return layer.GetType() != LayerType::Input &&
+ layer.GetType() != LayerType::Output &&
+ IsLayerSupported(layer) &&
+ !IsLayerOptimizable(layer);
+ };
+
+ // Apply the subgraph selector to the untouched layers to group them into sub-graphs were appropriate
+ SubgraphView mutableSubgraph(subgraph);
+ SubgraphViewSelector::Subgraphs untouchedSubgraphs =
+ SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, untouchedSubgraphSelector);
+
+ // Add each untouched sub-graph to the list of untouched sub-graphs in the optimizization views
+ std::for_each(untouchedSubgraphs.begin(),
+ untouchedSubgraphs.end(),
+ [&optimizationViews](const SubgraphView::SubgraphViewPtr& untouchedSubgraph)
+ {
+ BOOST_ASSERT(untouchedSubgraph != nullptr);
+
+ optimizationViews.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
+ });
+ }
+
+ return optimizationViews;
+}
+
+} // namespace armnn
diff --git a/src/backends/backendsCommon/test/MockBackend.hpp b/src/backends/backendsCommon/test/MockBackend.hpp
new file mode 100644
index 0000000000..d0a3de8682
--- /dev/null
+++ b/src/backends/backendsCommon/test/MockBackend.hpp
@@ -0,0 +1,36 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <backendsCommon/IBackendInternal.hpp>
+#include <backendsCommon/OptimizationViews.hpp>
+
+namespace armnn
+{
+
+class MockBackend : public IBackendInternal
+{
+public:
+ MockBackend() = default;
+ ~MockBackend() = default;
+
+ static const BackendId& GetIdStatic();
+ const BackendId& GetId() const override { return GetIdStatic(); }
+
+ IBackendInternal::IMemoryManagerUniquePtr CreateMemoryManager() const override;
+
+ IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(
+ const IBackendInternal::IMemoryManagerSharedPtr& memoryManager = nullptr) const override;
+
+ IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const override;
+
+ IBackendInternal::Optimizations GetOptimizations() const override;
+ IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override;
+
+ OptimizationViews OptimizeSubgraphView(const SubgraphView& subgraph) const override;
+};
+
+} // namespace armnn
diff --git a/src/backends/backendsCommon/test/MockBackendId.hpp b/src/backends/backendsCommon/test/MockBackendId.hpp
new file mode 100644
index 0000000000..724ce60c1b
--- /dev/null
+++ b/src/backends/backendsCommon/test/MockBackendId.hpp
@@ -0,0 +1,13 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+namespace armnn
+{
+
+constexpr const char* MockBackendId() { return "MockAcc"; }
+
+} // namespace armnn