From 4a3c61091037e7e86e8b03bb060d8c1ab82731a9 Mon Sep 17 00:00:00 2001 From: josh minor Date: Mon, 6 Jan 2020 16:40:46 -0600 Subject: IVGCVSW-4259 Add frontend and reference workload for UnaryOperationLayer * Added new layer named ElementwiseUnary * Deprecated existing Abs/Rsqrt layer functions * Updated existing Abs/Rsqrt test infrastructure to use new layer * Added boilerplate for new Exp,Neg,Sqrt elemwise op layers * AbsQuantize test removed pending future commit * Serialization support added !android-nn-driver:2550 Change-Id: Ic595c645925e17b45db568187fd05646daf2e87f Signed-off-by: josh minor --- src/backends/cl/ClLayerSupport.cpp | 32 +++++++++++++++++++---- src/backends/cl/ClLayerSupport.hpp | 7 +++++ src/backends/cl/ClWorkloadFactory.cpp | 36 ++++++++++++++++++++++++-- src/backends/cl/ClWorkloadFactory.hpp | 5 ++++ src/backends/cl/test/ClCreateWorkloadTests.cpp | 14 ++++------ src/backends/cl/test/ClEndToEndTests.cpp | 12 +++++++-- 6 files changed, 88 insertions(+), 18 deletions(-) (limited to 'src/backends/cl') diff --git a/src/backends/cl/ClLayerSupport.cpp b/src/backends/cl/ClLayerSupport.cpp index f7129d6035..f8cc5074b3 100644 --- a/src/backends/cl/ClLayerSupport.cpp +++ b/src/backends/cl/ClLayerSupport.cpp @@ -160,10 +160,8 @@ bool ClLayerSupport::IsAbsSupported(const TensorInfo& input, const TensorInfo& output, Optional reasonIfUnsupported) const { - FORWARD_WORKLOAD_VALIDATE_FUNC(ClAbsWorkloadValidate, - reasonIfUnsupported, - input, - output); + ElementwiseUnaryDescriptor descriptor(UnaryOperation::Abs); + return IsElementwiseUnarySupported(input, output, descriptor, reasonIfUnsupported); } bool ClLayerSupport::IsActivationSupported(const TensorInfo& input, @@ -425,6 +423,29 @@ bool ClLayerSupport::IsDivisionSupported(const TensorInfo& input0, output); } +bool ClLayerSupport::IsElementwiseUnarySupported(const TensorInfo& input, + const TensorInfo& output, + const ElementwiseUnaryDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + if (descriptor.m_Operation == UnaryOperation::Abs) + { + FORWARD_WORKLOAD_VALIDATE_FUNC(ClAbsWorkloadValidate, + reasonIfUnsupported, + input, + output); + } + else if (descriptor.m_Operation == UnaryOperation::Rsqrt) + { + FORWARD_WORKLOAD_VALIDATE_FUNC(ClRsqrtWorkloadValidate, + reasonIfUnsupported, + input, + output); + } + + return false; +} + bool ClLayerSupport::IsFloorSupported(const TensorInfo& input, const TensorInfo& output, Optional reasonIfUnsupported) const @@ -685,7 +706,8 @@ bool ClLayerSupport::IsRsqrtSupported(const TensorInfo& input, const TensorInfo& output, Optional reasonIfUnsupported) const { - FORWARD_WORKLOAD_VALIDATE_FUNC(ClRsqrtWorkloadValidate, reasonIfUnsupported, input, output); + ElementwiseUnaryDescriptor descriptor(UnaryOperation::Rsqrt); + return IsElementwiseUnarySupported(input, output, descriptor, reasonIfUnsupported); } bool ClLayerSupport::IsSliceSupported(const TensorInfo& input, diff --git a/src/backends/cl/ClLayerSupport.hpp b/src/backends/cl/ClLayerSupport.hpp index a21589d555..9371717013 100644 --- a/src/backends/cl/ClLayerSupport.hpp +++ b/src/backends/cl/ClLayerSupport.hpp @@ -12,6 +12,7 @@ namespace armnn class ClLayerSupport : public LayerSupportBase { public: + ARMNN_DEPRECATED_MSG("Use IsElementwiseUnarySupported instead") bool IsAbsSupported(const TensorInfo& input, const TensorInfo& output, Optional reasonIfUnsupported = EmptyOptional()) const override; @@ -102,6 +103,11 @@ public: const TensorInfo& output, Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsElementwiseUnarySupported(const TensorInfo& input, + const TensorInfo& ouput, + const ElementwiseUnaryDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsFloorSupported(const TensorInfo& input, const TensorInfo& output, Optional reasonIfUnsupported = EmptyOptional()) const override; @@ -223,6 +229,7 @@ public: const TensorInfo& output, Optional reasonIfUnsupported = EmptyOptional()) const override; + ARMNN_DEPRECATED_MSG("Use IsElementwiseUnarySupported instead") bool IsRsqrtSupported(const TensorInfo& input, const TensorInfo& output, Optional reasonIfUnsupported = EmptyOptional()) const override; diff --git a/src/backends/cl/ClWorkloadFactory.cpp b/src/backends/cl/ClWorkloadFactory.cpp index f9e6632b0c..4bb2e2a8ce 100644 --- a/src/backends/cl/ClWorkloadFactory.cpp +++ b/src/backends/cl/ClWorkloadFactory.cpp @@ -131,7 +131,12 @@ std::unique_ptr ClWorkloadFactory::CreateSubTensorHandle(ITensorH std::unique_ptr ClWorkloadFactory::CreateAbs(const AbsQueueDescriptor& descriptor, const WorkloadInfo& info) const { - return MakeWorkload(descriptor, info); + boost::ignore_unused(descriptor); + + ElementwiseUnaryQueueDescriptor elementwiseUnaryDescriptor; + elementwiseUnaryDescriptor.m_Parameters = ElementwiseUnaryDescriptor(UnaryOperation::Abs); + + return CreateElementwiseUnary(elementwiseUnaryDescriptor, info); } std::unique_ptr ClWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor, @@ -249,6 +254,28 @@ std::unique_ptr ClWorkloadFactory::CreateDivision(const DivisionQueue return MakeWorkload(descriptor, info); } +std::unique_ptr ClWorkloadFactory::CreateElementwiseUnary(const ElementwiseUnaryQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + if (descriptor.m_Parameters.m_Operation == UnaryOperation::Abs) + { + AbsQueueDescriptor absQueueDescriptor; + absQueueDescriptor.m_Inputs = descriptor.m_Inputs; + absQueueDescriptor.m_Outputs = descriptor.m_Outputs; + + return MakeWorkload(absQueueDescriptor, info); + } + else if (descriptor.m_Parameters.m_Operation == UnaryOperation::Rsqrt) + { + RsqrtQueueDescriptor rsqrtQueueDescriptor; + rsqrtQueueDescriptor.m_Inputs = descriptor.m_Inputs; + rsqrtQueueDescriptor.m_Outputs = descriptor.m_Outputs; + + return MakeWorkload(rsqrtQueueDescriptor, info); + } + return MakeWorkload(descriptor, info); +} + std::unique_ptr ClWorkloadFactory::CreateEqual(const EqualQueueDescriptor& descriptor, const WorkloadInfo& info) const { @@ -450,7 +477,12 @@ std::unique_ptr ClWorkloadFactory::CreateResizeBilinear(const ResizeB std::unique_ptr ClWorkloadFactory::CreateRsqrt(const RsqrtQueueDescriptor& descriptor, const WorkloadInfo& info) const { - return MakeWorkload(descriptor, info); + boost::ignore_unused(descriptor); + + ElementwiseUnaryQueueDescriptor elementwiseUnaryDescriptor; + elementwiseUnaryDescriptor.m_Parameters = ElementwiseUnaryDescriptor(UnaryOperation::Rsqrt); + + return CreateElementwiseUnary(elementwiseUnaryDescriptor, info); } std::unique_ptr ClWorkloadFactory::CreateSlice(const SliceQueueDescriptor& descriptor, diff --git a/src/backends/cl/ClWorkloadFactory.hpp b/src/backends/cl/ClWorkloadFactory.hpp index 8f377e959d..980be9192e 100644 --- a/src/backends/cl/ClWorkloadFactory.hpp +++ b/src/backends/cl/ClWorkloadFactory.hpp @@ -38,6 +38,7 @@ public: DataLayout dataLayout, const bool IsMemoryManaged = true) const override; + ARMNN_DEPRECATED_MSG("Use CreateElementwiseUnary instead") std::unique_ptr CreateAbs(const AbsQueueDescriptor& descriptor, const WorkloadInfo& info) const override; @@ -92,6 +93,9 @@ public: std::unique_ptr CreateDivision(const DivisionQueueDescriptor& descriptor, const WorkloadInfo& info) const override; + std::unique_ptr CreateElementwiseUnary(const ElementwiseUnaryQueueDescriptor& descriptor, + const WorkloadInfo& info) const override; + std::unique_ptr CreateEqual(const EqualQueueDescriptor& descriptor, const WorkloadInfo& info) const override; @@ -178,6 +182,7 @@ public: std::unique_ptr CreateResizeBilinear(const ResizeBilinearQueueDescriptor& descriptor, const WorkloadInfo& info) const override; + ARMNN_DEPRECATED_MSG("Use CreateElementwiseUnary instead") std::unique_ptr CreateRsqrt(const RsqrtQueueDescriptor& descriptor, const WorkloadInfo& info) const override; diff --git a/src/backends/cl/test/ClCreateWorkloadTests.cpp b/src/backends/cl/test/ClCreateWorkloadTests.cpp index d79745c420..92e771760f 100644 --- a/src/backends/cl/test/ClCreateWorkloadTests.cpp +++ b/src/backends/cl/test/ClCreateWorkloadTests.cpp @@ -146,18 +146,16 @@ BOOST_AUTO_TEST_CASE(CreateDivisionFloat16WorkloadTest) armnn::DataType::Float16>(); } -template -static void ClCreateElementwiseUnaryWorkloadTest() +static void ClCreateElementwiseUnaryWorkloadTest(armnn::UnaryOperation op) { Graph graph; ClWorkloadFactory factory = ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager()); - auto workload = CreateElementwiseUnaryWorkloadTest - (factory, graph); + auto workload = CreateElementwiseUnaryWorkloadTest(factory, graph, op); DescriptorType queueDescriptor = workload->GetData(); @@ -170,10 +168,8 @@ static void ClCreateElementwiseUnaryWorkloadTest() BOOST_AUTO_TEST_CASE(CreateRsqrtFloat32WorkloadTest) { - ClCreateElementwiseUnaryWorkloadTest(); + ClCreateElementwiseUnaryWorkloadTest( + UnaryOperation::Rsqrt); } template diff --git a/src/backends/cl/test/ClEndToEndTests.cpp b/src/backends/cl/test/ClEndToEndTests.cpp index 260f8f68cd..eafdb7c3e5 100644 --- a/src/backends/cl/test/ClEndToEndTests.cpp +++ b/src/backends/cl/test/ClEndToEndTests.cpp @@ -5,12 +5,12 @@ #include -#include #include #include #include #include #include +#include #include #include #include @@ -27,7 +27,15 @@ std::vector defaultBackends = {armnn::Compute::GpuAcc}; // Abs BOOST_AUTO_TEST_CASE(ClAbsEndToEndTestFloat32) { - AbsEndToEnd(defaultBackends); + std::vector expectedOutput = + { + 1.f, 1.f, 1.f, 1.f, 5.f, 5.f, 5.f, 5.f, + 3.f, 3.f, 3.f, 3.f, 4.f, 4.f, 4.f, 4.f + }; + + ElementwiseUnarySimpleEndToEnd(defaultBackends, + UnaryOperation::Abs, + expectedOutput); } // Constant -- cgit v1.2.1