From a1d3c6a49f35d7d3f11cc7e1b588d1d5401bdbf1 Mon Sep 17 00:00:00 2001 From: Mohamed Nour Abouelseoud Date: Thu, 27 Dec 2018 12:39:16 +0000 Subject: IVGCVSW-2371 Add Rsqrt Ref implementation *Added Unit Tests Change-Id: I6cceb8e6dcda35ce08415f8e5ca86019a64d26e3 --- src/armnn/InternalTypes.cpp | 1 + src/armnn/InternalTypes.hpp | 1 + src/armnn/LayerSupport.cpp | 9 ++ src/armnn/LayersFwd.hpp | 2 + src/armnn/Network.cpp | 5 + src/armnn/Network.hpp | 2 + src/armnn/layers/RsqrtLayer.cpp | 48 ++++++ src/armnn/layers/RsqrtLayer.hpp | 40 +++++ src/backends/backendsCommon/ILayerSupport.cpp | 7 + src/backends/backendsCommon/WorkloadData.cpp | 11 ++ src/backends/backendsCommon/WorkloadData.hpp | 5 + src/backends/backendsCommon/WorkloadFactory.cpp | 9 ++ src/backends/backendsCommon/WorkloadFactory.hpp | 3 + .../test/IsLayerSupportedTestImpl.hpp | 2 + src/backends/backendsCommon/test/LayerTests.cpp | 164 +++++++++++++++++++++ src/backends/backendsCommon/test/LayerTests.hpp | 24 +++ src/backends/cl/ClWorkloadFactory.cpp | 6 + src/backends/cl/ClWorkloadFactory.hpp | 3 + src/backends/neon/NeonWorkloadFactory.cpp | 6 + src/backends/neon/NeonWorkloadFactory.hpp | 3 + src/backends/reference/RefLayerSupport.cpp | 11 ++ src/backends/reference/RefLayerSupport.hpp | 4 + src/backends/reference/RefWorkloadFactory.cpp | 8 +- src/backends/reference/RefWorkloadFactory.hpp | 3 + src/backends/reference/backend.mk | 2 + src/backends/reference/test/RefLayerTests.cpp | 6 + src/backends/reference/workloads/CMakeLists.txt | 4 + .../workloads/RefRsqrtFloat32Workload.cpp | 25 ++++ .../workloads/RefRsqrtFloat32Workload.hpp | 21 +++ src/backends/reference/workloads/RefWorkloads.hpp | 1 + src/backends/reference/workloads/Rsqrt.cpp | 23 +++ src/backends/reference/workloads/Rsqrt.hpp | 18 +++ 32 files changed, 476 insertions(+), 1 deletion(-) create mode 100644 src/armnn/layers/RsqrtLayer.cpp create mode 100644 src/armnn/layers/RsqrtLayer.hpp create mode 100644 src/backends/reference/workloads/RefRsqrtFloat32Workload.cpp create mode 100644 src/backends/reference/workloads/RefRsqrtFloat32Workload.hpp create mode 100644 src/backends/reference/workloads/Rsqrt.cpp create mode 100644 src/backends/reference/workloads/Rsqrt.hpp (limited to 'src') 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(name); } +IConnectableLayer* Network::AddRsqrtLayer(const char * name) +{ + return m_Graph->AddLayer(name); +} + OptimizedNetwork::OptimizedNetwork(std::unique_ptr 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 +#include +#include + +namespace armnn +{ + +RsqrtLayer::RsqrtLayer(const char* name) + : Layer(1, 1, LayerType::Rsqrt, name) +{ +} + +std::unique_ptr 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(graph, GetName()); +} + +void RsqrtLayer::ValidateTensorShapesFromInputs() +{ + VerifyLayerConnections(1, CHECK_LOCATION()); + + auto inferredShapes = InferOutputShapes({ GetInputSlot(0).GetConnection()->GetTensorInfo().GetShape() }); + + BOOST_ASSERT(inferredShapes.size() == 1); + + ConditionalThrowIfNotEqual( + "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 + +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 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 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 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(&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 CreateDebug(const DebugQueueDescriptor& descriptor, const WorkloadInfo& info) const = 0; + + virtual std::unique_ptr 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 ResizeBilinearMagUint8Test( return result; } +LayerTestResult Rsqrt2dTestCommon( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::TensorInfo inputTensorInfo, + const armnn::TensorInfo outputTensorInfo, + std::vector inputValues, + std::vector expectedOutputValues) +{ + auto inputTensor = MakeTensor(inputTensorInfo, std::vector(inputValues)); + + LayerTestResult result(outputTensorInfo); + result.outputExpected = MakeTensor(outputTensorInfo, std::vector(expectedOutputValues)); + + std::unique_ptr inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo); + std::unique_ptr 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 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 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 inputValues + { + 1.f, 4.f, + 16.f, 25.f + }; + + std::vector expectedOutputValues + { + 1.f, 0.5f, + 0.25f, 0.2f + }; + + return Rsqrt2dTestCommon(workloadFactory, memoryManager, + inputTensorInfo, outputTensorInfo, + inputValues, expectedOutputValues); +} + +LayerTestResult 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 inputValues + { + 1.f, 4.f, 16.f, + 25.f, 64.f, 100.f + }; + + std::vector expectedOutputValues + { + 1.f, 0.5f, 0.25f, + 0.2f, 0.125f, 0.1f + }; + + auto inputTensor = MakeTensor(inputTensorInfo, std::vector(inputValues)); + + LayerTestResult result(outputTensorInfo); + result.outputExpected = MakeTensor(outputTensorInfo, std::vector(expectedOutputValues)); + + std::unique_ptr inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo); + std::unique_ptr 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 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 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 inputValues + { + 0.f, -0.f + }; + + std::vector expectedOutputValues + { + INFINITY, -INFINITY + }; + + return Rsqrt2dTestCommon(workloadFactory, memoryManager, + inputTensorInfo, outputTensorInfo, + inputValues, expectedOutputValues); +} + +LayerTestResult 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 inputValues + { + -25.f, -16.f + }; + + std::vector expectedOutputValues + { + -NAN, -NAN + }; + + return Rsqrt2dTestCommon(workloadFactory, memoryManager, + inputTensorInfo, outputTensorInfo, + inputValues, expectedOutputValues); +} + LayerTestResult 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 ResizeBilinearMagTest( const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, const armnn::DataLayout dataLayout); +LayerTestResult Rsqrt2dTestCommon( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::TensorInfo inputTensorInfo, + const armnn::TensorInfo outputTensorInfo, + std::vector inputValues, + std::vector expectedOutputValues); + +LayerTestResult Rsqrt2dTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult Rsqrt3dTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult RsqrtZeroTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult RsqrtNegativeTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + LayerTestResult 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 ClWorkloadFactory::CreateDebug(const DebugQueueDescri return MakeWorkload(descriptor, info); } +std::unique_ptr ClWorkloadFactory::CreateRsqrt(const RsqrtQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + return MakeWorkload(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 CreateDebug(const DebugQueueDescriptor& descriptor, const WorkloadInfo& info) const override; + virtual std::unique_ptr CreateRsqrt(const RsqrtQueueDescriptor& descriptor, + const WorkloadInfo& info) const override; + private: template static std::unique_ptr 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 NeonWorkloadFactory::CreateDebug(const DebugQueueDesc return MakeWorkloadHelper(descriptor, info); } +std::unique_ptr NeonWorkloadFactory::CreateRsqrt(const RsqrtQueueDescriptor &descriptor, + const WorkloadInfo &info) const +{ + return MakeWorkloadHelper(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 CreateDebug(const DebugQueueDescriptor& descriptor, const WorkloadInfo& info) const override; + virtual std::unique_ptr CreateRsqrt(const RsqrtQueueDescriptor& descriptor, + const WorkloadInfo& info) const override; + private: mutable std::shared_ptr 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 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 reasonIfUnsupported = EmptyOptional()) const override; + bool IsRsqrtSupported(const TensorInfo& input, + const TensorInfo& output, + Optional 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 RefWorkloadFactory::CreateDebug(const DebugQueueDescr return MakeWorkload(descriptor, info); } -} // namespace armnn +std::unique_ptr RefWorkloadFactory::CreateRsqrt(const RsqrtQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + return MakeWorkload(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 CreateDebug(const DebugQueueDescriptor& descriptor, const WorkloadInfo& info) const override; + + virtual std::unique_ptr CreateRsqrt(const RsqrtQueueDescriptor& descriptor, + const WorkloadInfo& info) const override; private: template 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 + +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 +#include + +namespace armnn +{ + +class RefRsqrtFloat32Workload : public Float32Workload +{ +public: + using Float32Workload::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 + +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 +#include + +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 -- cgit v1.2.1