aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk5
-rw-r--r--CMakeLists.txt2
-rw-r--r--include/armnn/ILayerSupport.hpp4
-rw-r--r--include/armnn/INetwork.hpp5
-rw-r--r--include/armnn/LayerSupport.hpp7
-rw-r--r--src/armnn/InternalTypes.cpp1
-rw-r--r--src/armnn/InternalTypes.hpp1
-rw-r--r--src/armnn/LayerSupport.cpp9
-rw-r--r--src/armnn/LayersFwd.hpp2
-rw-r--r--src/armnn/Network.cpp5
-rw-r--r--src/armnn/Network.hpp2
-rw-r--r--src/armnn/layers/RsqrtLayer.cpp48
-rw-r--r--src/armnn/layers/RsqrtLayer.hpp40
-rw-r--r--src/backends/backendsCommon/ILayerSupport.cpp7
-rw-r--r--src/backends/backendsCommon/WorkloadData.cpp11
-rw-r--r--src/backends/backendsCommon/WorkloadData.hpp5
-rw-r--r--src/backends/backendsCommon/WorkloadFactory.cpp9
-rw-r--r--src/backends/backendsCommon/WorkloadFactory.hpp3
-rw-r--r--src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp2
-rwxr-xr-xsrc/backends/backendsCommon/test/LayerTests.cpp164
-rw-r--r--src/backends/backendsCommon/test/LayerTests.hpp24
-rw-r--r--src/backends/cl/ClWorkloadFactory.cpp6
-rw-r--r--src/backends/cl/ClWorkloadFactory.hpp3
-rw-r--r--src/backends/neon/NeonWorkloadFactory.cpp6
-rw-r--r--src/backends/neon/NeonWorkloadFactory.hpp3
-rw-r--r--src/backends/reference/RefLayerSupport.cpp11
-rw-r--r--src/backends/reference/RefLayerSupport.hpp4
-rw-r--r--src/backends/reference/RefWorkloadFactory.cpp8
-rw-r--r--src/backends/reference/RefWorkloadFactory.hpp3
-rw-r--r--src/backends/reference/backend.mk2
-rw-r--r--src/backends/reference/test/RefLayerTests.cpp6
-rw-r--r--src/backends/reference/workloads/CMakeLists.txt4
-rw-r--r--src/backends/reference/workloads/RefRsqrtFloat32Workload.cpp25
-rw-r--r--src/backends/reference/workloads/RefRsqrtFloat32Workload.hpp21
-rw-r--r--src/backends/reference/workloads/RefWorkloads.hpp1
-rw-r--r--src/backends/reference/workloads/Rsqrt.cpp23
-rw-r--r--src/backends/reference/workloads/Rsqrt.hpp18
37 files changed, 497 insertions, 3 deletions
diff --git a/Android.mk b/Android.mk
index 4c8c492766..c02dc39db6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -113,13 +113,14 @@ LOCAL_SRC_FILES := \
src/armnn/layers/PermuteLayer.cpp \
src/armnn/layers/Pooling2dLayer.cpp \
src/armnn/layers/DivisionLayer.cpp \
- src/armnn/layers/SubtractionLayer.cpp \
src/armnn/layers/ReshapeLayer.cpp \
- src/armnn/layers/SpaceToBatchNdLayer.cpp \
src/armnn/layers/ResizeBilinearLayer.cpp \
+ src/armnn/layers/RsqrtLayer.cpp \
+ src/armnn/layers/SpaceToBatchNdLayer.cpp \
src/armnn/layers/SoftmaxLayer.cpp \
src/armnn/layers/SplitterLayer.cpp \
src/armnn/layers/StridedSliceLayer.cpp \
+ src/armnn/layers/SubtractionLayer.cpp \
src/armnn/Descriptors.cpp \
src/armnn/Exceptions.cpp \
src/armnn/Graph.cpp \
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a00a44a6ce..9fedc25cdf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -240,6 +240,8 @@ list(APPEND armnn_sources
src/armnn/layers/SpaceToBatchNdLayer.cpp
src/armnn/layers/ResizeBilinearLayer.hpp
src/armnn/layers/ResizeBilinearLayer.cpp
+ src/armnn/layers/RsqrtLayer.cpp
+ src/armnn/layers/RsqrtLayer.hpp
src/armnn/layers/SoftmaxLayer.hpp
src/armnn/layers/SoftmaxLayer.cpp
src/armnn/layers/SplitterLayer.hpp
diff --git a/include/armnn/ILayerSupport.hpp b/include/armnn/ILayerSupport.hpp
index e8840cb29e..af38b07f39 100644
--- a/include/armnn/ILayerSupport.hpp
+++ b/include/armnn/ILayerSupport.hpp
@@ -195,6 +195,10 @@ public:
virtual bool IsResizeBilinearSupported(const TensorInfo& input,
Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const;
+ virtual bool IsRsqrtSupported(const TensorInfo& input,
+ const TensorInfo& output,
+ Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const;
+
virtual bool IsSoftmaxSupported(const TensorInfo& input,
const TensorInfo& output,
const SoftmaxDescriptor& descriptor,
diff --git a/include/armnn/INetwork.hpp b/include/armnn/INetwork.hpp
index 63fd78bb69..5f341ad6fa 100644
--- a/include/armnn/INetwork.hpp
+++ b/include/armnn/INetwork.hpp
@@ -338,6 +338,11 @@ public:
/// @ return - Interface for configuring the layer.
virtual IConnectableLayer* AddEqualLayer(const char* name = nullptr) = 0;
+ /// Add Reciprocal of square root layer to the network.
+ /// @param name - Optional name for the layer.
+ /// @ return - Interface for configuring the layer.
+ virtual IConnectableLayer* AddRsqrtLayer(const char* name = nullptr) = 0;
+
protected:
~INetwork() {}
};
diff --git a/include/armnn/LayerSupport.hpp b/include/armnn/LayerSupport.hpp
index 5a5ba98f72..446dd705b0 100644
--- a/include/armnn/LayerSupport.hpp
+++ b/include/armnn/LayerSupport.hpp
@@ -249,6 +249,13 @@ bool IsReshapeSupported(const BackendId& backend,
size_t reasonIfUnsupportedMaxLength = 1024);
/// Deprecated in favor of IBackend and ILayerSupport interfaces
+bool IsRsqrtSupported(const BackendId& backend,
+ const TensorInfo& input,
+ const TensorInfo& output,
+ char* reasonIfUnsupported = nullptr,
+ size_t reasonIfUnsupportedMaxLength = 1024);
+
+/// Deprecated in favor of IBackend and ILayerSupport interfaces
bool IsFloorSupported(const BackendId& backend,
const TensorInfo& input,
const TensorInfo& output,
diff --git a/src/armnn/InternalTypes.cpp b/src/armnn/InternalTypes.cpp
index fe806f1ccb..9ffd73ac08 100644
--- a/src/armnn/InternalTypes.cpp
+++ b/src/armnn/InternalTypes.cpp
@@ -45,6 +45,7 @@ char const* GetLayerTypeAsCString(LayerType type)
case LayerType::Permute: return "Permute";
case LayerType::Pooling2d: return "Pooling2d";
case LayerType::Reshape: return "Reshape";
+ case LayerType::Rsqrt: return "Rsqrt";
case LayerType::ResizeBilinear: return "ResizeBilinear";
case LayerType::Softmax: return "Softmax";
case LayerType::SpaceToBatchNd: return "SpaceToBatchNd";
diff --git a/src/armnn/InternalTypes.hpp b/src/armnn/InternalTypes.hpp
index c6b5c04665..f4996db73e 100644
--- a/src/armnn/InternalTypes.hpp
+++ b/src/armnn/InternalTypes.hpp
@@ -46,6 +46,7 @@ enum class LayerType
Pooling2d,
Reshape,
ResizeBilinear,
+ Rsqrt,
Softmax,
SpaceToBatchNd,
Splitter,
diff --git a/src/armnn/LayerSupport.cpp b/src/armnn/LayerSupport.cpp
index 3c864c5ae7..cf6ce27dda 100644
--- a/src/armnn/LayerSupport.cpp
+++ b/src/armnn/LayerSupport.cpp
@@ -389,6 +389,15 @@ bool IsReshapeSupported(const BackendId& backend,
FORWARD_LAYER_SUPPORT_FUNC(backend, IsReshapeSupported, input);
}
+bool IsRsqrtSupported(const BackendId& backend,
+ const TensorInfo& input,
+ const TensorInfo& output,
+ char* reasonIfUnsupported,
+ size_t reasonIfUnsupportedMaxLength)
+{
+ FORWARD_LAYER_SUPPORT_FUNC(backend, IsRsqrtSupported, input, output);
+}
+
bool IsFloorSupported(const BackendId& backend,
const TensorInfo& input,
const TensorInfo& output,
diff --git a/src/armnn/LayersFwd.hpp b/src/armnn/LayersFwd.hpp
index c9a12a6643..9f55233e8e 100644
--- a/src/armnn/LayersFwd.hpp
+++ b/src/armnn/LayersFwd.hpp
@@ -38,6 +38,7 @@
#include "layers/Pooling2dLayer.hpp"
#include "layers/ReshapeLayer.hpp"
#include "layers/ResizeBilinearLayer.hpp"
+#include "layers/RsqrtLayer.hpp"
#include "layers/SoftmaxLayer.hpp"
#include "layers/SpaceToBatchNdLayer.hpp"
#include "layers/SplitterLayer.hpp"
@@ -103,6 +104,7 @@ DECLARE_LAYER(Permute)
DECLARE_LAYER(Pooling2d)
DECLARE_LAYER(Reshape)
DECLARE_LAYER(ResizeBilinear)
+DECLARE_LAYER(Rsqrt)
DECLARE_LAYER(Softmax)
DECLARE_LAYER(SpaceToBatchNd)
DECLARE_LAYER(Splitter)
diff --git a/src/armnn/Network.cpp b/src/armnn/Network.cpp
index 0d959547e4..187d04eb2b 100644
--- a/src/armnn/Network.cpp
+++ b/src/armnn/Network.cpp
@@ -727,6 +727,11 @@ IConnectableLayer* Network::AddEqualLayer(const char* name)
return m_Graph->AddLayer<EqualLayer>(name);
}
+IConnectableLayer* Network::AddRsqrtLayer(const char * name)
+{
+ return m_Graph->AddLayer<RsqrtLayer>(name);
+}
+
OptimizedNetwork::OptimizedNetwork(std::unique_ptr<Graph> graph)
: m_Graph(std::move(graph))
{
diff --git a/src/armnn/Network.hpp b/src/armnn/Network.hpp
index f36ca4fa74..ba741e9af6 100644
--- a/src/armnn/Network.hpp
+++ b/src/armnn/Network.hpp
@@ -139,6 +139,8 @@ public:
IConnectableLayer* AddEqualLayer(const char* name = nullptr) override;
+ IConnectableLayer* AddRsqrtLayer(const char* name = nullptr) override;
+
private:
IConnectableLayer* AddFullyConnectedLayerImpl(const FullyConnectedDescriptor& fullyConnectedDescriptor,
const ConstTensor& weights,
diff --git a/src/armnn/layers/RsqrtLayer.cpp b/src/armnn/layers/RsqrtLayer.cpp
new file mode 100644
index 0000000000..d516810c68
--- /dev/null
+++ b/src/armnn/layers/RsqrtLayer.cpp
@@ -0,0 +1,48 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "RsqrtLayer.hpp"
+
+#include "LayerCloneBase.hpp"
+
+#include <armnn/TypesUtils.hpp>
+#include <backendsCommon/WorkloadData.hpp>
+#include <backendsCommon/WorkloadFactory.hpp>
+
+namespace armnn
+{
+
+RsqrtLayer::RsqrtLayer(const char* name)
+ : Layer(1, 1, LayerType::Rsqrt, name)
+{
+}
+
+std::unique_ptr<IWorkload> RsqrtLayer::CreateWorkload(const Graph& graph,
+ const IWorkloadFactory& factory) const
+{
+ RsqrtQueueDescriptor descriptor;
+ return factory.CreateRsqrt(descriptor, PrepInfoAndDesc(descriptor, graph));
+}
+
+RsqrtLayer* RsqrtLayer::Clone(Graph& graph) const
+{
+ return CloneBase<RsqrtLayer>(graph, GetName());
+}
+
+void RsqrtLayer::ValidateTensorShapesFromInputs()
+{
+ VerifyLayerConnections(1, CHECK_LOCATION());
+
+ auto inferredShapes = InferOutputShapes({ GetInputSlot(0).GetConnection()->GetTensorInfo().GetShape() });
+
+ BOOST_ASSERT(inferredShapes.size() == 1);
+
+ ConditionalThrowIfNotEqual<LayerValidationException>(
+ "RsqrtLayer: TensorShape set on OutputSlot[0] does not match the inferred shape.",
+ GetOutputSlot(0).GetTensorInfo().GetShape(),
+ inferredShapes[0]);
+}
+
+} // namespace armnn \ No newline at end of file
diff --git a/src/armnn/layers/RsqrtLayer.hpp b/src/armnn/layers/RsqrtLayer.hpp
new file mode 100644
index 0000000000..47a4ccedd6
--- /dev/null
+++ b/src/armnn/layers/RsqrtLayer.hpp
@@ -0,0 +1,40 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <Layer.hpp>
+
+namespace armnn
+{
+
+class RsqrtLayer : public Layer
+{
+public:
+ /// Makes a workload for the Rsqrt type.
+ /// @param [in] graph The graph where this layer can be found.
+ /// @param [in] factory The workload factory which will create the workload.
+ /// @return A pointer to the created workload, or nullptr if not created.
+ virtual std::unique_ptr<IWorkload> CreateWorkload(const Graph& graph,
+ const IWorkloadFactory& factory) const override;
+
+ /// Creates a dynamically-allocated copy of this layer.
+ /// @param [in] graph The graph into which this layer is being cloned.
+ RsqrtLayer* Clone(Graph& graph) const override;
+
+ /// Check if the input tensor shape(s)
+ /// will lead to a valid configuration of @ref RsqrtLayer.
+ void ValidateTensorShapesFromInputs() override;
+
+protected:
+ /// Constructor to create an RsqrtLayer.
+ /// @param [in] name Optional name for the layer.
+ RsqrtLayer(const char* name);
+
+ /// Default destructor
+ ~RsqrtLayer() = default;
+};
+
+} // namespace \ No newline at end of file
diff --git a/src/backends/backendsCommon/ILayerSupport.cpp b/src/backends/backendsCommon/ILayerSupport.cpp
index 0b78913b99..aa1bb5042d 100644
--- a/src/backends/backendsCommon/ILayerSupport.cpp
+++ b/src/backends/backendsCommon/ILayerSupport.cpp
@@ -336,4 +336,11 @@ bool ILayerSupport::IsGreaterSupported(const TensorInfo& input0,
return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported);
}
+bool ILayerSupport::IsRsqrtSupported(const TensorInfo &input,
+ const TensorInfo &output,
+ Optional<std::string &> reasonIfUnsupported) const
+{
+ return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported);
+}
+
} // namespace armnn
diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp
index 1dac498c11..a5db088be7 100644
--- a/src/backends/backendsCommon/WorkloadData.cpp
+++ b/src/backends/backendsCommon/WorkloadData.cpp
@@ -1040,4 +1040,15 @@ void GreaterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
"second input");
}
+void RsqrtQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
+{
+ ValidateSingleInput(workloadInfo, "RsqrtQueueDescriptor");
+ ValidateSingleOutput(workloadInfo, "RsqrtQueueDescriptor");
+ ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
+ workloadInfo.m_OutputTensorInfos[0],
+ "RsqrtQueueDescriptor",
+ "input",
+ "output");
+}
+
} //namespace armnn
diff --git a/src/backends/backendsCommon/WorkloadData.hpp b/src/backends/backendsCommon/WorkloadData.hpp
index 9142d87bfd..59e3dfbf5c 100644
--- a/src/backends/backendsCommon/WorkloadData.hpp
+++ b/src/backends/backendsCommon/WorkloadData.hpp
@@ -373,4 +373,9 @@ struct DebugQueueDescriptor : QueueDescriptorWithParameters<DebugDescriptor>
void Validate(const WorkloadInfo& workloadInfo) const;
};
+struct RsqrtQueueDescriptor : QueueDescriptor
+{
+ void Validate(const WorkloadInfo& workloadInfo) const;
+};
+
} //namespace armnn
diff --git a/src/backends/backendsCommon/WorkloadFactory.cpp b/src/backends/backendsCommon/WorkloadFactory.cpp
index 3b8a7d8f7f..1dc96a5ec3 100644
--- a/src/backends/backendsCommon/WorkloadFactory.cpp
+++ b/src/backends/backendsCommon/WorkloadFactory.cpp
@@ -600,6 +600,15 @@ bool IWorkloadFactory::IsLayerSupported(const BackendId& backendId,
result = layerSupportObject->IsResizeBilinearSupported(OverrideDataType(input, dataType), reason);
break;
}
+ case LayerType::Rsqrt:
+ {
+ const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
+ const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
+ result = layerSupportObject->IsRsqrtSupported(OverrideDataType(input, dataType),
+ OverrideDataType(output, dataType),
+ reason);
+ break;
+ }
case LayerType::Softmax:
{
auto cLayer = boost::polymorphic_downcast<const SoftmaxLayer*>(&layer);
diff --git a/src/backends/backendsCommon/WorkloadFactory.hpp b/src/backends/backendsCommon/WorkloadFactory.hpp
index e72987fdcb..aee9f91b56 100644
--- a/src/backends/backendsCommon/WorkloadFactory.hpp
+++ b/src/backends/backendsCommon/WorkloadFactory.hpp
@@ -156,6 +156,9 @@ public:
virtual std::unique_ptr<IWorkload> CreateDebug(const DebugQueueDescriptor& descriptor,
const WorkloadInfo& info) const = 0;
+
+ virtual std::unique_ptr<IWorkload> CreateRsqrt(const RsqrtQueueDescriptor& descriptor,
+ const WorkloadInfo& info) const = 0;
};
} //namespace armnn
diff --git a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp
index d4c5fe43c6..d6528bb0ae 100644
--- a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp
+++ b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp
@@ -378,6 +378,8 @@ DECLARE_LAYER_POLICY_2_PARAM(ResizeBilinear)
DECLARE_LAYER_POLICY_2_PARAM(Reshape)
+DECLARE_LAYER_POLICY_1_PARAM(Rsqrt)
+
DECLARE_LAYER_POLICY_2_PARAM(Softmax)
DECLARE_LAYER_POLICY_2_PARAM(SpaceToBatchNd)
diff --git a/src/backends/backendsCommon/test/LayerTests.cpp b/src/backends/backendsCommon/test/LayerTests.cpp
index 52150075ce..8e4596b703 100755
--- a/src/backends/backendsCommon/test/LayerTests.cpp
+++ b/src/backends/backendsCommon/test/LayerTests.cpp
@@ -6734,6 +6734,170 @@ LayerTestResult<uint8_t, 4> ResizeBilinearMagUint8Test(
return result;
}
+LayerTestResult<float, 2> Rsqrt2dTestCommon(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::TensorInfo inputTensorInfo,
+ const armnn::TensorInfo outputTensorInfo,
+ std::vector<float> inputValues,
+ std::vector<float> expectedOutputValues)
+{
+ auto inputTensor = MakeTensor<float, 2>(inputTensorInfo, std::vector<float>(inputValues));
+
+ LayerTestResult<float, 2> result(outputTensorInfo);
+ result.outputExpected = MakeTensor<float, 2>(outputTensorInfo, std::vector<float>(expectedOutputValues));
+
+ std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
+ std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
+
+ armnn::RsqrtQueueDescriptor descriptor;
+
+ armnn::WorkloadInfo info;
+
+ AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
+ AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
+
+ std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateRsqrt(descriptor, info);
+
+ inputHandle->Allocate();
+ outputHandle->Allocate();
+
+ CopyDataToITensorHandle(inputHandle.get(), &inputTensor[0][0]);
+
+ workload->Execute();
+
+ CopyDataFromITensorHandle(&result.output[0][0], outputHandle.get());
+
+ return result;
+}
+LayerTestResult<float, 2> Rsqrt2dTest(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+{
+ const armnn::TensorShape inputShape{ 2, 2 };
+ const armnn::TensorShape outputShape{ 2, 2 };
+
+ const armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32);
+ const armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32);
+
+ std::vector<float> inputValues
+ {
+ 1.f, 4.f,
+ 16.f, 25.f
+ };
+
+ std::vector<float> expectedOutputValues
+ {
+ 1.f, 0.5f,
+ 0.25f, 0.2f
+ };
+
+ return Rsqrt2dTestCommon(workloadFactory, memoryManager,
+ inputTensorInfo, outputTensorInfo,
+ inputValues, expectedOutputValues);
+}
+
+LayerTestResult<float, 3> Rsqrt3dTest(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+{
+ const armnn::TensorShape inputShape{ 3, 1, 2 };
+ const armnn::TensorShape outputShape{ 3, 1, 2 };
+
+ const armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32);
+ const armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32);
+
+ std::vector<float> inputValues
+ {
+ 1.f, 4.f, 16.f,
+ 25.f, 64.f, 100.f
+ };
+
+ std::vector<float> expectedOutputValues
+ {
+ 1.f, 0.5f, 0.25f,
+ 0.2f, 0.125f, 0.1f
+ };
+
+ auto inputTensor = MakeTensor<float, 3>(inputTensorInfo, std::vector<float>(inputValues));
+
+ LayerTestResult<float, 3> result(outputTensorInfo);
+ result.outputExpected = MakeTensor<float, 3>(outputTensorInfo, std::vector<float >(expectedOutputValues));
+
+ std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
+ std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
+
+ armnn::RsqrtQueueDescriptor descriptor;
+
+ armnn::WorkloadInfo info;
+
+ AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
+ AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
+
+ std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateRsqrt(descriptor, info);
+
+ inputHandle->Allocate();
+ outputHandle->Allocate();
+
+ CopyDataToITensorHandle(inputHandle.get(), &inputTensor[0][0][0]);
+
+ workload->Execute();
+
+ CopyDataFromITensorHandle(&result.output[0][0][0], outputHandle.get());
+
+ return result;
+}
+
+LayerTestResult<float, 2> RsqrtZeroTest(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+{
+ const armnn::TensorShape inputShape{ 1, 2 };
+ const armnn::TensorShape outputShape{ 1, 2 };
+
+ const armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32);
+ const armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32);
+
+ std::vector<float> inputValues
+ {
+ 0.f, -0.f
+ };
+
+ std::vector<float> expectedOutputValues
+ {
+ INFINITY, -INFINITY
+ };
+
+ return Rsqrt2dTestCommon(workloadFactory, memoryManager,
+ inputTensorInfo, outputTensorInfo,
+ inputValues, expectedOutputValues);
+}
+
+LayerTestResult<float, 2> RsqrtNegativeTest(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+{
+ const armnn::TensorShape inputShape{ 1, 2 };
+ const armnn::TensorShape outputShape{ 1, 2 };
+
+ const armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32);
+ const armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32);
+
+ std::vector<float> inputValues
+ {
+ -25.f, -16.f
+ };
+
+ std::vector<float> expectedOutputValues
+ {
+ -NAN, -NAN
+ };
+
+ return Rsqrt2dTestCommon(workloadFactory, memoryManager,
+ inputTensorInfo, outputTensorInfo,
+ inputValues, expectedOutputValues);
+}
+
LayerTestResult<float, 4> BatchNormTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp
index a871594900..98c0806ddf 100644
--- a/src/backends/backendsCommon/test/LayerTests.hpp
+++ b/src/backends/backendsCommon/test/LayerTests.hpp
@@ -639,6 +639,30 @@ LayerTestResult<float, 4> ResizeBilinearMagTest(
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::DataLayout dataLayout);
+LayerTestResult<float, 2> Rsqrt2dTestCommon(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::TensorInfo inputTensorInfo,
+ const armnn::TensorInfo outputTensorInfo,
+ std::vector<float> inputValues,
+ std::vector<float> expectedOutputValues);
+
+LayerTestResult<float, 2> Rsqrt2dTest(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
+
+LayerTestResult<float, 3> Rsqrt3dTest(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
+
+LayerTestResult<float, 2> RsqrtZeroTest(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
+
+LayerTestResult<float, 2> RsqrtNegativeTest(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
+
LayerTestResult<float, 4> BatchNormTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
diff --git a/src/backends/cl/ClWorkloadFactory.cpp b/src/backends/cl/ClWorkloadFactory.cpp
index 0653b41643..6b035851b8 100644
--- a/src/backends/cl/ClWorkloadFactory.cpp
+++ b/src/backends/cl/ClWorkloadFactory.cpp
@@ -350,4 +350,10 @@ std::unique_ptr<IWorkload> ClWorkloadFactory::CreateDebug(const DebugQueueDescri
return MakeWorkload<NullWorkload, NullWorkload>(descriptor, info);
}
+std::unique_ptr<IWorkload> ClWorkloadFactory::CreateRsqrt(const RsqrtQueueDescriptor& descriptor,
+ const WorkloadInfo& info) const
+{
+ return MakeWorkload<NullWorkload, NullWorkload>(descriptor, info);
+}
+
} // namespace armnn
diff --git a/src/backends/cl/ClWorkloadFactory.hpp b/src/backends/cl/ClWorkloadFactory.hpp
index 28447216db..85cbd91e11 100644
--- a/src/backends/cl/ClWorkloadFactory.hpp
+++ b/src/backends/cl/ClWorkloadFactory.hpp
@@ -147,6 +147,9 @@ public:
virtual std::unique_ptr<IWorkload> CreateDebug(const DebugQueueDescriptor& descriptor,
const WorkloadInfo& info) const override;
+ virtual std::unique_ptr<IWorkload> CreateRsqrt(const RsqrtQueueDescriptor& descriptor,
+ const WorkloadInfo& info) const override;
+
private:
template<typename FloatWorkload, typename Uint8Workload, typename QueueDescriptorType, typename... Args>
static std::unique_ptr<IWorkload> MakeWorkload(const QueueDescriptorType& descriptor,
diff --git a/src/backends/neon/NeonWorkloadFactory.cpp b/src/backends/neon/NeonWorkloadFactory.cpp
index e635f0cc8d..ff60efb86f 100644
--- a/src/backends/neon/NeonWorkloadFactory.cpp
+++ b/src/backends/neon/NeonWorkloadFactory.cpp
@@ -318,4 +318,10 @@ std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateDebug(const DebugQueueDesc
return MakeWorkloadHelper<NullWorkload, NullWorkload>(descriptor, info);
}
+std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateRsqrt(const RsqrtQueueDescriptor &descriptor,
+ const WorkloadInfo &info) const
+{
+ return MakeWorkloadHelper<NullWorkload, NullWorkload>(descriptor, info);
+}
+
} // namespace armnn
diff --git a/src/backends/neon/NeonWorkloadFactory.hpp b/src/backends/neon/NeonWorkloadFactory.hpp
index 2f7a2db315..9a6308871a 100644
--- a/src/backends/neon/NeonWorkloadFactory.hpp
+++ b/src/backends/neon/NeonWorkloadFactory.hpp
@@ -148,6 +148,9 @@ public:
virtual std::unique_ptr<IWorkload> CreateDebug(const DebugQueueDescriptor& descriptor,
const WorkloadInfo& info) const override;
+ virtual std::unique_ptr<IWorkload> CreateRsqrt(const RsqrtQueueDescriptor& descriptor,
+ const WorkloadInfo& info) const override;
+
private:
mutable std::shared_ptr<NeonMemoryManager> m_MemoryManager;
};
diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp
index a64339ec69..56d2e4c659 100644
--- a/src/backends/reference/RefLayerSupport.cpp
+++ b/src/backends/reference/RefLayerSupport.cpp
@@ -495,6 +495,17 @@ bool RefLayerSupport::IsResizeBilinearSupported(const TensorInfo& input,
&TrueFunc<>);
}
+bool RefLayerSupport::IsRsqrtSupported(const TensorInfo& input,
+ const TensorInfo& output,
+ Optional<std::string&> reasonIfUnsupported) const
+{
+ ignore_unused(output);
+ return IsSupportedForDataTypeRef(reasonIfUnsupported,
+ input.GetDataType(),
+ &TrueFunc<>,
+ &FalseFuncU8<>);
+}
+
bool RefLayerSupport::IsSoftmaxSupported(const TensorInfo& input,
const TensorInfo& output,
const SoftmaxDescriptor& descriptor,
diff --git a/src/backends/reference/RefLayerSupport.hpp b/src/backends/reference/RefLayerSupport.hpp
index 3941f4bc56..188faa84b6 100644
--- a/src/backends/reference/RefLayerSupport.hpp
+++ b/src/backends/reference/RefLayerSupport.hpp
@@ -185,6 +185,10 @@ public:
bool IsResizeBilinearSupported(const TensorInfo& input,
Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const override;
+ bool IsRsqrtSupported(const TensorInfo& input,
+ const TensorInfo& output,
+ Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const override;
+
bool IsSoftmaxSupported(const TensorInfo& input,
const TensorInfo& output,
const SoftmaxDescriptor& descriptor,
diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp
index eb8807eef6..79293635fb 100644
--- a/src/backends/reference/RefWorkloadFactory.cpp
+++ b/src/backends/reference/RefWorkloadFactory.cpp
@@ -312,4 +312,10 @@ std::unique_ptr<IWorkload> RefWorkloadFactory::CreateDebug(const DebugQueueDescr
return MakeWorkload<RefDebugFloat32Workload, RefDebugUint8Workload>(descriptor, info);
}
-} // namespace armnn
+std::unique_ptr<IWorkload> RefWorkloadFactory::CreateRsqrt(const RsqrtQueueDescriptor& descriptor,
+ const WorkloadInfo& info) const
+{
+ return MakeWorkload<RefRsqrtFloat32Workload, NullWorkload>(descriptor, info);
+}
+
+} // namespace armnn \ No newline at end of file
diff --git a/src/backends/reference/RefWorkloadFactory.hpp b/src/backends/reference/RefWorkloadFactory.hpp
index f4401ccb6e..f6707f5046 100644
--- a/src/backends/reference/RefWorkloadFactory.hpp
+++ b/src/backends/reference/RefWorkloadFactory.hpp
@@ -164,6 +164,9 @@ public:
virtual std::unique_ptr<IWorkload> CreateDebug(const DebugQueueDescriptor& descriptor,
const WorkloadInfo& info) const override;
+
+ virtual std::unique_ptr<IWorkload> CreateRsqrt(const RsqrtQueueDescriptor& descriptor,
+ const WorkloadInfo& info) const override;
private:
template <typename F32Workload, typename U8Workload, typename QueueDescriptorType>
diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk
index b23c752b89..84f15c9c80 100644
--- a/src/backends/reference/backend.mk
+++ b/src/backends/reference/backend.mk
@@ -57,6 +57,7 @@ BACKEND_SOURCES := \
workloads/RefReshapeUint8Workload.cpp \
workloads/RefResizeBilinearFloat32Workload.cpp \
workloads/RefResizeBilinearUint8Workload.cpp \
+ workloads/RefRsqrtFloat32Workload.cpp \
workloads/RefSoftmaxFloat32Workload.cpp \
workloads/RefSoftmaxUint8Workload.cpp \
workloads/RefSpaceToBatchNdWorkload.cpp \
@@ -64,6 +65,7 @@ BACKEND_SOURCES := \
workloads/RefSplitterFloat32Workload.cpp \
workloads/RefSplitterUint8Workload.cpp \
workloads/ResizeBilinear.cpp \
+ workloads/Rsqrt.cpp \
workloads/SpaceToBatchNd.cpp \
workloads/StridedSlice.cpp \
workloads/StringMapping.cpp \
diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp
index 7223f04ea9..50c47aecf9 100644
--- a/src/backends/reference/test/RefLayerTests.cpp
+++ b/src/backends/reference/test/RefLayerTests.cpp
@@ -380,6 +380,12 @@ ARMNN_AUTO_TEST_CASE(SimpleFloor, SimpleFloorTest)
ARMNN_AUTO_TEST_CASE(SimpleReshapeFloat32, SimpleReshapeFloat32Test)
ARMNN_AUTO_TEST_CASE(SimpleReshapeUint8, SimpleReshapeUint8Test)
+// Rsqrt
+ARMNN_AUTO_TEST_CASE(Rsqrt2d, Rsqrt2dTest)
+ARMNN_AUTO_TEST_CASE(Rsqrt3d, Rsqrt3dTest)
+ARMNN_AUTO_TEST_CASE(RsqrtZero, RsqrtZeroTest)
+ARMNN_AUTO_TEST_CASE(RsqrtNegative, RsqrtNegativeTest)
+
// Permute
ARMNN_AUTO_TEST_CASE(SimplePermuteFloat32, SimplePermuteFloat32Test)
ARMNN_AUTO_TEST_CASE(SimplePermuteUint8, SimplePermuteUint8Test)
diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt
index d71e6ea032..d15f77d6e4 100644
--- a/src/backends/reference/workloads/CMakeLists.txt
+++ b/src/backends/reference/workloads/CMakeLists.txt
@@ -94,6 +94,8 @@ list(APPEND armnnRefBackendWorkloads_sources
RefResizeBilinearFloat32Workload.hpp
RefResizeBilinearUint8Workload.cpp
RefResizeBilinearUint8Workload.hpp
+ RefRsqrtFloat32Workload.cpp
+ RefRsqrtFloat32Workload.hpp
RefSoftmaxFloat32Workload.cpp
RefSoftmaxFloat32Workload.hpp
RefSoftmaxUint8Workload.cpp
@@ -110,6 +112,8 @@ list(APPEND armnnRefBackendWorkloads_sources
RefWorkloadUtils.hpp
ResizeBilinear.cpp
ResizeBilinear.hpp
+ Rsqrt.cpp
+ Rsqrt.hpp
Softmax.cpp
Softmax.hpp
SpaceToBatchNd.hpp
diff --git a/src/backends/reference/workloads/RefRsqrtFloat32Workload.cpp b/src/backends/reference/workloads/RefRsqrtFloat32Workload.cpp
new file mode 100644
index 0000000000..c08dbf0cab
--- /dev/null
+++ b/src/backends/reference/workloads/RefRsqrtFloat32Workload.cpp
@@ -0,0 +1,25 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "RefRsqrtFloat32Workload.hpp"
+
+#include "RefWorkloadUtils.hpp"
+#include "Rsqrt.hpp"
+
+#include <Profiling.hpp>
+
+namespace armnn
+{
+
+void RefRsqrtFloat32Workload::Execute() const
+{
+ ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefRsqrtFloat32Workload_Execute");
+
+ Rsqrt(GetInputTensorDataFloat(0, m_Data),
+ GetOutputTensorDataFloat(0, m_Data),
+ GetTensorInfo(m_Data.m_Inputs[0]));
+}
+
+} //namespace armnn
diff --git a/src/backends/reference/workloads/RefRsqrtFloat32Workload.hpp b/src/backends/reference/workloads/RefRsqrtFloat32Workload.hpp
new file mode 100644
index 0000000000..9d1b4505fe
--- /dev/null
+++ b/src/backends/reference/workloads/RefRsqrtFloat32Workload.hpp
@@ -0,0 +1,21 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <backendsCommon/Workload.hpp>
+#include <backendsCommon/WorkloadData.hpp>
+
+namespace armnn
+{
+
+class RefRsqrtFloat32Workload : public Float32Workload<RsqrtQueueDescriptor>
+{
+public:
+ using Float32Workload<RsqrtQueueDescriptor>::Float32Workload;
+ virtual void Execute() const override;
+};
+
+} //namespace armnn
diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp
index ddce68e60c..8beb03fe32 100644
--- a/src/backends/reference/workloads/RefWorkloads.hpp
+++ b/src/backends/reference/workloads/RefWorkloads.hpp
@@ -59,3 +59,4 @@
#include "RefBatchToSpaceNdUint8Workload.hpp"
#include "RefBatchToSpaceNdFloat32Workload.hpp"
#include "RefDebugWorkload.hpp"
+#include "RefRsqrtFloat32Workload.hpp"
diff --git a/src/backends/reference/workloads/Rsqrt.cpp b/src/backends/reference/workloads/Rsqrt.cpp
new file mode 100644
index 0000000000..cee38fc1f1
--- /dev/null
+++ b/src/backends/reference/workloads/Rsqrt.cpp
@@ -0,0 +1,23 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "Rsqrt.hpp"
+
+#include <cmath>
+
+namespace armnn
+{
+
+void Rsqrt(const float* in,
+ float* out,
+ const TensorInfo& tensorInfo)
+{
+ for (size_t i = 0; i < tensorInfo.GetNumElements(); i++)
+ {
+ out[i] = 1.f / sqrtf(in[i]);
+ }
+}
+
+} //namespace armnn \ No newline at end of file
diff --git a/src/backends/reference/workloads/Rsqrt.hpp b/src/backends/reference/workloads/Rsqrt.hpp
new file mode 100644
index 0000000000..35cacede66
--- /dev/null
+++ b/src/backends/reference/workloads/Rsqrt.hpp
@@ -0,0 +1,18 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include <armnn/Tensor.hpp>
+#include <armnn/Types.hpp>
+
+namespace armnn
+{
+
+/// Performs the reciprocal squareroot function elementwise
+/// on the inputs to give the outputs.
+void Rsqrt(const float* in,
+ float* out,
+ const TensorInfo& tensorInfo);
+
+} //namespace armnn