aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLes Bell <les.bell@arm.com>2018-09-03 16:24:52 +0100
committerMatthew Bentham <matthew.bentham@arm.com>2018-09-17 17:21:25 +0100
commit033626d1ee9256032309bbc6685c3a69a919cd64 (patch)
tree42a1ab9c3b83c4da019b69e2189846663e0d19be
parent9e53a35b66b1ec7ceee7c712380a13596175b83b (diff)
downloadarmnn-033626d1ee9256032309bbc6685c3a69a919cd64.tar.gz
IVGCVSW-1783 refactor add/mul/div layers
Change-Id: Ic043030455b3cf8ad7f92fd0a75175c1827a95f4
-rw-r--r--Android.mk1
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/armnn/layers/AdditionLayer.cpp53
-rw-r--r--src/armnn/layers/AdditionLayer.hpp10
-rw-r--r--src/armnn/layers/ArithmeticBaseLayer.cpp68
-rw-r--r--src/armnn/layers/ArithmeticBaseLayer.hpp26
-rw-r--r--src/armnn/layers/DivisionLayer.cpp50
-rw-r--r--src/armnn/layers/DivisionLayer.hpp7
-rw-r--r--src/armnn/layers/MultiplicationLayer.cpp52
-rw-r--r--src/armnn/layers/MultiplicationLayer.hpp9
10 files changed, 112 insertions, 166 deletions
diff --git a/Android.mk b/Android.mk
index c712ced385..eae457375c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -172,6 +172,7 @@ LOCAL_SRC_FILES := \
src/armnn/backends/WorkloadFactory.cpp \
src/armnn/layers/ActivationLayer.cpp \
src/armnn/layers/AdditionLayer.cpp \
+ src/armnn/layers/ArithmeticBaseLayer.cpp \
src/armnn/layers/BatchNormalizationLayer.cpp \
src/armnn/layers/ConstantLayer.cpp \
src/armnn/layers/Convolution2dLayer.cpp \
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 09761af4b1..802ca50cfd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -291,6 +291,8 @@ list(APPEND armnn_sources
src/armnn/layers/ActivationLayer.cpp
src/armnn/layers/AdditionLayer.hpp
src/armnn/layers/AdditionLayer.cpp
+ src/armnn/layers/ArithmeticBaseLayer.hpp
+ src/armnn/layers/ArithmeticBaseLayer.cpp
src/armnn/layers/BatchNormalizationLayer.hpp
src/armnn/layers/BatchNormalizationLayer.cpp
src/armnn/layers/ConstantLayer.hpp
diff --git a/src/armnn/layers/AdditionLayer.cpp b/src/armnn/layers/AdditionLayer.cpp
index ab73a918db..c1413102b8 100644
--- a/src/armnn/layers/AdditionLayer.cpp
+++ b/src/armnn/layers/AdditionLayer.cpp
@@ -3,6 +3,7 @@
// See LICENSE file in the project root for full license information.
//
#include "AdditionLayer.hpp"
+
#include "LayerCloneBase.hpp"
#include <armnn/TypesUtils.hpp>
@@ -13,11 +14,12 @@ namespace armnn
{
AdditionLayer::AdditionLayer(const char* name)
- : Layer(2, 1, LayerType::Addition, name)
+ : ArithmeticBaseLayer(2, 1, LayerType::Addition, name)
{
}
-std::unique_ptr<IWorkload> AdditionLayer::CreateWorkload(const Graph& graph, const IWorkloadFactory& factory) const
+std::unique_ptr<IWorkload> AdditionLayer::CreateWorkload(const Graph& graph,
+ const IWorkloadFactory& factory) const
{
AdditionQueueDescriptor descriptor;
return factory.CreateAddition(descriptor, PrepInfoAndDesc(descriptor, graph));
@@ -28,51 +30,4 @@ AdditionLayer* AdditionLayer::Clone(Graph& graph) const
return CloneBase<AdditionLayer>(graph, GetName());
}
-std::vector<TensorShape> AdditionLayer::InferOutputShapes(const std::vector<TensorShape>& inputShapes) const
-{
- BOOST_ASSERT(inputShapes.size() == 2);
- auto& input0 = inputShapes[0];
- auto& input1 = inputShapes[1];
-
- // Get the max of the inputs.
- BOOST_ASSERT(input0.GetNumDimensions() == input1.GetNumDimensions());
- unsigned int numDims = input0.GetNumDimensions();
- std::vector<unsigned int> dims(numDims);
-
- for (unsigned int i = 0; i < numDims; i++)
- {
- unsigned int dim0 = input0[i];
- unsigned int dim1 = input1[i];
-
- // Validates inputs are broadcast compatible.
-#if !NDEBUG
- if (dim0 != dim1)
- {
- BOOST_ASSERT_MSG(dim0 == 1 || dim1 == 1, "Dimensions should either match or one should be of size 1.");
- }
-#endif
-
- dims[i] = std::max(dim0, dim1);
- }
-
- return std::vector<TensorShape>({ TensorShape(numDims, dims.data()) });
-}
-
-void AdditionLayer::ValidateTensorShapesFromInputs()
-{
- VerifyLayerConnections(2, CHECK_LOCATION());
-
- auto inferredShapes = InferOutputShapes({
- GetInputSlot(0).GetConnection()->GetTensorInfo().GetShape(),
- GetInputSlot(1).GetConnection()->GetTensorInfo().GetShape()
- });
-
- BOOST_ASSERT(inferredShapes.size() == 1);
-
- ConditionalThrowIfNotEqual<LayerValidationException>(
- "AdditionLayer: TensorShape set on OutputSlot[0] does not match the inferred shape.",
- GetOutputSlot(0).GetTensorInfo().GetShape(),
- inferredShapes[0]);
-}
-
} // namespace armnn
diff --git a/src/armnn/layers/AdditionLayer.hpp b/src/armnn/layers/AdditionLayer.hpp
index 37f0b5c259..d34536d114 100644
--- a/src/armnn/layers/AdditionLayer.hpp
+++ b/src/armnn/layers/AdditionLayer.hpp
@@ -4,23 +4,19 @@
//
#pragma once
-#include <Layer.hpp>
+#include "ArithmeticBaseLayer.hpp"
namespace armnn
{
-class AdditionLayer : public Layer
+class AdditionLayer : public ArithmeticBaseLayer
{
public:
- virtual std::unique_ptr<IWorkload> CreateWorkload(const Graph& graph,
+ virtual std::unique_ptr<IWorkload> CreateWorkload(const Graph& graph,
const IWorkloadFactory& factory) const override;
AdditionLayer* Clone(Graph& graph) const override;
- void ValidateTensorShapesFromInputs() override;
-
- std::vector<TensorShape> InferOutputShapes(const std::vector<TensorShape>& inputShapes) const override;
-
protected:
AdditionLayer(const char* name);
~AdditionLayer() = default;
diff --git a/src/armnn/layers/ArithmeticBaseLayer.cpp b/src/armnn/layers/ArithmeticBaseLayer.cpp
new file mode 100644
index 0000000000..63937fba6c
--- /dev/null
+++ b/src/armnn/layers/ArithmeticBaseLayer.cpp
@@ -0,0 +1,68 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// See LICENSE file in the project root for full license information.
+//
+#include "ArithmeticBaseLayer.hpp"
+
+#include "InternalTypes.hpp"
+#include "armnn/Exceptions.hpp"
+#include <armnn/TypesUtils.hpp>
+
+#include <boost/assert.hpp>
+
+namespace armnn
+{
+
+ArithmeticBaseLayer::ArithmeticBaseLayer(unsigned int numInputSlots, unsigned int numOutputSlots,
+ LayerType type, const char* name)
+ : Layer(numInputSlots, numOutputSlots, type, name)
+{
+}
+
+std::vector<TensorShape> ArithmeticBaseLayer::InferOutputShapes(const std::vector<TensorShape>& inputShapes) const
+{
+ BOOST_ASSERT(inputShapes.size() == 2);
+ auto& input0 = inputShapes[0];
+ auto& input1 = inputShapes[1];
+
+ // Get the max of the inputs.
+ BOOST_ASSERT(input0.GetNumDimensions() == input1.GetNumDimensions());
+ unsigned int numDims = input0.GetNumDimensions();
+ std::vector<unsigned int> dims(numDims);
+
+ for (unsigned int i = 0; i < numDims; i++)
+ {
+ unsigned int dim0 = input0[i];
+ unsigned int dim1 = input1[i];
+
+#if !NDEBUG
+ // Validate inputs are broadcast compatible.
+ BOOST_ASSERT_MSG(dim0 == dim1 || dim0 == 1 || dim1 == 1,
+ "Dimensions should either match or one should be of size 1.");
+#endif
+
+ dims[i] = std::max(dim0, dim1);
+ }
+
+ return std::vector<TensorShape>({ TensorShape(numDims, dims.data()) });
+}
+
+void ArithmeticBaseLayer::ValidateTensorShapesFromInputs()
+{
+ VerifyLayerConnections(2, CHECK_LOCATION());
+
+ auto inferredShapes = InferOutputShapes({
+ GetInputSlot(0).GetConnection()->GetTensorInfo().GetShape(),
+ GetInputSlot(1).GetConnection()->GetTensorInfo().GetShape()
+ });
+
+ BOOST_ASSERT(inferredShapes.size() == 1);
+
+ std::string msg = GetLayerTypeAsCString(GetType());
+ msg += "Layer: TensorShape set on OutputSlot[0] does not match the inferred shape.";
+ ConditionalThrowIfNotEqual<LayerValidationException>(msg,
+ GetOutputSlot(0).GetTensorInfo().GetShape(),
+ inferredShapes[0]);
+}
+
+} // namespace armnn
diff --git a/src/armnn/layers/ArithmeticBaseLayer.hpp b/src/armnn/layers/ArithmeticBaseLayer.hpp
new file mode 100644
index 0000000000..eee612add4
--- /dev/null
+++ b/src/armnn/layers/ArithmeticBaseLayer.hpp
@@ -0,0 +1,26 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// See LICENSE file in the project root for full license information.
+//
+#pragma once
+
+#include <Layer.hpp>
+
+namespace armnn
+{
+
+/// NOTE: this is an abstract class, it does not implement:
+/// std::unique_ptr<IWorkload> Layer::CreateWorkload(const Graph& graph, const IWorkloadFactory& factory) const = 0;
+/// Layer* Clone(Graph& graph) const = 0;
+class ArithmeticBaseLayer : public Layer
+{
+public:
+ void ValidateTensorShapesFromInputs() override;
+ std::vector<TensorShape> InferOutputShapes(const std::vector<TensorShape>& inputShapes) const override;
+
+protected:
+ ArithmeticBaseLayer(unsigned int numInputSlots, unsigned int numOutputSlots, LayerType type, const char* name);
+ ~ArithmeticBaseLayer() = default;
+};
+
+} // namespace
diff --git a/src/armnn/layers/DivisionLayer.cpp b/src/armnn/layers/DivisionLayer.cpp
index bf09e14229..c0f958929e 100644
--- a/src/armnn/layers/DivisionLayer.cpp
+++ b/src/armnn/layers/DivisionLayer.cpp
@@ -14,7 +14,7 @@ namespace armnn
{
DivisionLayer::DivisionLayer(const char* name)
- : Layer(2, 1, LayerType::Division, name)
+ : ArithmeticBaseLayer(2, 1, LayerType::Division, name)
{
}
@@ -22,7 +22,6 @@ std::unique_ptr<IWorkload> DivisionLayer::CreateWorkload(const Graph& graph,
const IWorkloadFactory& factory) const
{
DivisionQueueDescriptor descriptor;
-
return factory.CreateDivision(descriptor, PrepInfoAndDesc(descriptor, graph));
}
@@ -31,51 +30,4 @@ DivisionLayer* DivisionLayer::Clone(Graph& graph) const
return CloneBase<DivisionLayer>(graph, GetName());
}
-std::vector<TensorShape> DivisionLayer::InferOutputShapes(const std::vector<TensorShape>& inputShapes) const
-{
- BOOST_ASSERT(inputShapes.size() == 2);
- auto& input0 = inputShapes[0];
- auto& input1 = inputShapes[1];
-
- // Get the max of the inputs.
- BOOST_ASSERT(input0.GetNumDimensions() == input1.GetNumDimensions());
- unsigned int numDims = input0.GetNumDimensions();
- std::vector<unsigned int> dims(numDims);
-
- for (unsigned int i = 0; i < numDims; i++)
- {
- unsigned int dim0 = input0[i];
- unsigned int dim1 = input1[i];
-
- // Validates inputs are broadcast compatible.
-#if !NDEBUG
- if (dim0 != dim1)
- {
- BOOST_ASSERT_MSG(dim0 == 1 || dim1 == 1, "Dimensions should either match or one should be of size 1.");
- }
-#endif
-
- dims[i] = std::max(dim0, dim1);
- }
-
- return std::vector<TensorShape>({ TensorShape(numDims, dims.data()) });
-}
-
-void DivisionLayer::ValidateTensorShapesFromInputs()
-{
- VerifyLayerConnections(2, CHECK_LOCATION());
-
- auto inferredShapes = InferOutputShapes({
- GetInputSlot(0).GetConnection()->GetTensorInfo().GetShape(),
- GetInputSlot(1).GetConnection()->GetTensorInfo().GetShape()
- });
-
- BOOST_ASSERT(inferredShapes.size() == 1);
-
- ConditionalThrowIfNotEqual<LayerValidationException>(
- "DivisionLayer: TensorShape set on OutputSlot[0] does not match the inferred shape.",
- GetOutputSlot(0).GetTensorInfo().GetShape(),
- inferredShapes[0]);
-}
-
} // namespace armnn
diff --git a/src/armnn/layers/DivisionLayer.hpp b/src/armnn/layers/DivisionLayer.hpp
index 1bd69c4446..c6a642e318 100644
--- a/src/armnn/layers/DivisionLayer.hpp
+++ b/src/armnn/layers/DivisionLayer.hpp
@@ -4,12 +4,12 @@
//
#pragma once
-#include <Layer.hpp>
+#include "ArithmeticBaseLayer.hpp"
namespace armnn
{
-class DivisionLayer : public Layer
+class DivisionLayer : public ArithmeticBaseLayer
{
public:
virtual std::unique_ptr<IWorkload> CreateWorkload(const Graph& graph,
@@ -17,9 +17,6 @@ public:
DivisionLayer* Clone(Graph& graph) const override;
- void ValidateTensorShapesFromInputs() override;
- std::vector<TensorShape> InferOutputShapes(const std::vector<TensorShape>& inputShapes) const override;
-
protected:
DivisionLayer(const char* name);
~DivisionLayer() = default;
diff --git a/src/armnn/layers/MultiplicationLayer.cpp b/src/armnn/layers/MultiplicationLayer.cpp
index ed7683da5f..6970b3f7f4 100644
--- a/src/armnn/layers/MultiplicationLayer.cpp
+++ b/src/armnn/layers/MultiplicationLayer.cpp
@@ -14,15 +14,14 @@ namespace armnn
{
MultiplicationLayer::MultiplicationLayer(const char* name)
- : Layer(2, 1, LayerType::Multiplication, name)
+ : ArithmeticBaseLayer(2, 1, LayerType::Multiplication, name)
{
}
-std::unique_ptr<IWorkload> MultiplicationLayer::CreateWorkload(const Graph& graph,
+std::unique_ptr<IWorkload> MultiplicationLayer::CreateWorkload(const Graph& graph,
const IWorkloadFactory& factory) const
{
MultiplicationQueueDescriptor descriptor;
-
return factory.CreateMultiplication(descriptor, PrepInfoAndDesc(descriptor, graph));
}
@@ -31,51 +30,4 @@ MultiplicationLayer* MultiplicationLayer::Clone(Graph& graph) const
return CloneBase<MultiplicationLayer>(graph, GetName());
}
-std::vector<TensorShape> MultiplicationLayer::InferOutputShapes(const std::vector<TensorShape>& inputShapes) const
-{
- BOOST_ASSERT(inputShapes.size() == 2);
- auto& input0 = inputShapes[0];
- auto& input1 = inputShapes[1];
-
- // Get the max of the inputs.
- BOOST_ASSERT(input0.GetNumDimensions() == input1.GetNumDimensions());
- unsigned int numDims = input0.GetNumDimensions();
- std::vector<unsigned int> dims(numDims);
-
- for (unsigned int i = 0; i < numDims; i++)
- {
- unsigned int dim0 = input0[i];
- unsigned int dim1 = input1[i];
-
- // Validates inputs are broadcast compatible.
-#if !NDEBUG
- if (dim0 != dim1)
- {
- BOOST_ASSERT_MSG(dim0 == 1 || dim1 == 1, "Dimensions should either match or one should be of size 1.");
- }
-#endif
-
- dims[i] = std::max(dim0, dim1);
- }
-
- return std::vector<TensorShape>({ TensorShape(numDims, dims.data()) });
-}
-
-void MultiplicationLayer::ValidateTensorShapesFromInputs()
-{
- VerifyLayerConnections(2, CHECK_LOCATION());
-
- auto inferredShapes = InferOutputShapes({
- GetInputSlot(0).GetConnection()->GetTensorInfo().GetShape(),
- GetInputSlot(1).GetConnection()->GetTensorInfo().GetShape()
- });
-
- BOOST_ASSERT(inferredShapes.size() == 1);
-
- ConditionalThrowIfNotEqual<LayerValidationException>(
- "MultiplicationLayer: TensorShape set on OutputSlot[0] does not match the inferred shape.",
- GetOutputSlot(0).GetTensorInfo().GetShape(),
- inferredShapes[0]);
-}
-
} // namespace armnn
diff --git a/src/armnn/layers/MultiplicationLayer.hpp b/src/armnn/layers/MultiplicationLayer.hpp
index bbfd1ee694..264d12feeb 100644
--- a/src/armnn/layers/MultiplicationLayer.hpp
+++ b/src/armnn/layers/MultiplicationLayer.hpp
@@ -4,22 +4,19 @@
//
#pragma once
-#include <Layer.hpp>
+#include "ArithmeticBaseLayer.hpp"
namespace armnn
{
-class MultiplicationLayer : public Layer
+class MultiplicationLayer : public ArithmeticBaseLayer
{
public:
- virtual std::unique_ptr<IWorkload> CreateWorkload(const Graph& graph,
+ virtual std::unique_ptr<IWorkload> CreateWorkload(const Graph& graph,
const IWorkloadFactory& factory) const override;
MultiplicationLayer* Clone(Graph& graph) const override;
- void ValidateTensorShapesFromInputs() override;
- std::vector<TensorShape> InferOutputShapes(const std::vector<TensorShape>& inputShapes) const override;
-
protected:
MultiplicationLayer(const char* name);
~MultiplicationLayer() = default;