From 91e4c6d43921b735e6aee78d8611bc0372eda4df Mon Sep 17 00:00:00 2001 From: Nikhil Raj Date: Fri, 5 Jul 2019 12:22:58 +0100 Subject: [PATCH] IVGCVSW-3293 Add CL backend support for PReLU Change-Id: I1bb187db89bb3eb883b8f0aca4c3439d82b56583 Signed-off-by: Nikhil Raj --- src/backends/cl/ClLayerSupport.cpp | 9 +++++ src/backends/cl/ClLayerSupport.hpp | 5 +++ src/backends/cl/ClWorkloadFactory.cpp | 6 ++++ src/backends/cl/ClWorkloadFactory.hpp | 3 ++ src/backends/cl/backend.mk | 1 + src/backends/cl/test/ClCreateWorkloadTests.cpp | 42 ++++++++++++++++++++++ src/backends/cl/test/ClLayerTests.cpp | 4 +++ src/backends/cl/workloads/CMakeLists.txt | 2 ++ src/backends/cl/workloads/ClPreluWorkload.cpp | 48 ++++++++++++++++++++++++++ src/backends/cl/workloads/ClPreluWorkload.hpp | 28 +++++++++++++++ src/backends/cl/workloads/ClWorkloads.hpp | 1 + 11 files changed, 149 insertions(+) create mode 100644 src/backends/cl/workloads/ClPreluWorkload.cpp create mode 100644 src/backends/cl/workloads/ClPreluWorkload.hpp diff --git a/src/backends/cl/ClLayerSupport.cpp b/src/backends/cl/ClLayerSupport.cpp index d79f612..a6baa3c 100644 --- a/src/backends/cl/ClLayerSupport.cpp +++ b/src/backends/cl/ClLayerSupport.cpp @@ -39,6 +39,7 @@ #include "workloads/ClPadWorkload.hpp" #include "workloads/ClPermuteWorkload.hpp" #include "workloads/ClPooling2dWorkload.hpp" +#include "workloads/ClPreluWorkload.hpp" #include "workloads/ClQuantizeWorkload.hpp" #include "workloads/ClSoftmaxBaseWorkload.hpp" #include "workloads/ClSpaceToBatchNdWorkload.hpp" @@ -571,6 +572,14 @@ bool ClLayerSupport::IsPooling2dSupported(const TensorInfo& input, FORWARD_WORKLOAD_VALIDATE_FUNC(ClPooling2dWorkloadValidate, reasonIfUnsupported, input, output, descriptor); } +bool ClLayerSupport::IsPreluSupported(const armnn::TensorInfo &input, + const armnn::TensorInfo &alpha, + const armnn::TensorInfo &output, + armnn::Optional reasonIfUnsupported) const +{ + FORWARD_WORKLOAD_VALIDATE_FUNC(ClPreluWorkloadValidate, reasonIfUnsupported, input, alpha, output); +} + bool ClLayerSupport::IsQuantizeSupported(const TensorInfo& input, const TensorInfo& output, Optional reasonIfUnsupported) const diff --git a/src/backends/cl/ClLayerSupport.hpp b/src/backends/cl/ClLayerSupport.hpp index 1461f41..f77889b 100644 --- a/src/backends/cl/ClLayerSupport.hpp +++ b/src/backends/cl/ClLayerSupport.hpp @@ -190,6 +190,11 @@ public: const Pooling2dDescriptor& descriptor, Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsPreluSupported(const TensorInfo& input, + const TensorInfo& alpha, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsQuantizeSupported(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 c662a9d..307f954 100644 --- a/src/backends/cl/ClWorkloadFactory.cpp +++ b/src/backends/cl/ClWorkloadFactory.cpp @@ -180,6 +180,12 @@ std::unique_ptr ClWorkloadFactory::CreatePooling2d(const Pooli return MakeWorkload(descriptor, info); } +std::unique_ptr ClWorkloadFactory::CreatePrelu(const armnn::PreluQueueDescriptor &descriptor, + const armnn::WorkloadInfo &info) const +{ + return MakeWorkload(descriptor, info); +} + std::unique_ptr ClWorkloadFactory::CreateConvolution2d(const Convolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const { diff --git a/src/backends/cl/ClWorkloadFactory.hpp b/src/backends/cl/ClWorkloadFactory.hpp index 32925f7..5448504 100644 --- a/src/backends/cl/ClWorkloadFactory.hpp +++ b/src/backends/cl/ClWorkloadFactory.hpp @@ -64,6 +64,9 @@ public: std::unique_ptr CreatePooling2d(const Pooling2dQueueDescriptor& descriptor, const WorkloadInfo& info) const override; + std::unique_ptr CreatePrelu(const PreluQueueDescriptor& descriptor, + const WorkloadInfo& info) const override; + std::unique_ptr CreateConvolution2d(const Convolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const override; diff --git a/src/backends/cl/backend.mk b/src/backends/cl/backend.mk index 137cf76..87964cd 100644 --- a/src/backends/cl/backend.mk +++ b/src/backends/cl/backend.mk @@ -45,6 +45,7 @@ BACKEND_SOURCES := \ workloads/ClPadWorkload.cpp \ workloads/ClPermuteWorkload.cpp \ workloads/ClPooling2dWorkload.cpp \ + workloads/ClPreluWorkload.cpp \ workloads/ClQuantizeWorkload.cpp \ workloads/ClReshapeWorkload.cpp \ workloads/ClResizeBilinearFloatWorkload.cpp \ diff --git a/src/backends/cl/test/ClCreateWorkloadTests.cpp b/src/backends/cl/test/ClCreateWorkloadTests.cpp index aa1393f..9e4f85b 100644 --- a/src/backends/cl/test/ClCreateWorkloadTests.cpp +++ b/src/backends/cl/test/ClCreateWorkloadTests.cpp @@ -452,6 +452,48 @@ BOOST_AUTO_TEST_CASE(CreatePooling2dFloat16NhwcWorkload) ClPooling2dWorkloadTest(DataLayout::NHWC); } +static void ClCreatePreluWorkloadTest(const armnn::TensorShape& inputShape, + const armnn::TensorShape& alphaShape, + const armnn::TensorShape& outputShape, + armnn::DataType dataType) +{ + Graph graph; + ClWorkloadFactory factory = + ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager()); + + auto workload = CreatePreluWorkloadTest(factory, + graph, + inputShape, + alphaShape, + outputShape, + dataType); + + // Checks that outputs and inputs are as we expect them (see definition of CreatePreluWorkloadTest). + PreluQueueDescriptor queueDescriptor = workload->GetData(); + auto inputHandle = boost::polymorphic_downcast(queueDescriptor.m_Inputs[0]); + auto alphaHandle = boost::polymorphic_downcast(queueDescriptor.m_Inputs[1]); + auto outputHandle = boost::polymorphic_downcast(queueDescriptor.m_Outputs[0]); + + BOOST_TEST((inputHandle->GetShape() == inputShape)); + BOOST_TEST((alphaHandle->GetShape() == alphaShape)); + BOOST_TEST((outputHandle->GetShape() == outputShape)); +} + +BOOST_AUTO_TEST_CASE(CreatePreluFloat16Workload) +{ + ClCreatePreluWorkloadTest({ 1, 4, 1, 2 }, { 5, 4, 3, 1 }, { 5, 4, 3, 2 }, DataType::Float16); +} + +BOOST_AUTO_TEST_CASE(CreatePreluFloatWorkload) +{ + ClCreatePreluWorkloadTest({ 1, 4, 1, 2 }, { 5, 4, 3, 1 }, { 5, 4, 3, 2 }, DataType::Float32); +} + +BOOST_AUTO_TEST_CASE(CreatePreluUint8Workload) +{ + ClCreatePreluWorkloadTest({ 1, 4, 1, 2 }, { 5, 4, 3, 1 }, { 5, 4, 3, 2 }, DataType::QuantisedAsymm8); +} + template static void ClCreateReshapeWorkloadTest() { diff --git a/src/backends/cl/test/ClLayerTests.cpp b/src/backends/cl/test/ClLayerTests.cpp index 3618adc..9ac244e 100644 --- a/src/backends/cl/test/ClLayerTests.cpp +++ b/src/backends/cl/test/ClLayerTests.cpp @@ -331,6 +331,10 @@ ARMNN_AUTO_TEST_CASE(PadFloat322d, PadFloat322dTest) ARMNN_AUTO_TEST_CASE(PadFloat323d, PadFloat323dTest) ARMNN_AUTO_TEST_CASE(PadFloat324d, PadFloat324dTest) +// PReLU +ARMNN_AUTO_TEST_CASE(PreluFloat32, PreluTest) +ARMNN_AUTO_TEST_CASE(PreluUint8, PreluTest) + // Permute ARMNN_AUTO_TEST_CASE(SimplePermuteFloat32, SimplePermuteFloat32Test) ARMNN_AUTO_TEST_CASE(SimplePermuteUint8, SimplePermuteUint8Test) diff --git a/src/backends/cl/workloads/CMakeLists.txt b/src/backends/cl/workloads/CMakeLists.txt index 1b4c85b..40c5f76 100644 --- a/src/backends/cl/workloads/CMakeLists.txt +++ b/src/backends/cl/workloads/CMakeLists.txt @@ -54,6 +54,8 @@ list(APPEND armnnClBackendWorkloads_sources ClPermuteWorkload.hpp ClPooling2dWorkload.cpp ClPooling2dWorkload.hpp + ClPreluWorkload.cpp + ClPreluWorkload.hpp ClQuantizeWorkload.cpp ClQuantizeWorkload.hpp ClReshapeWorkload.cpp diff --git a/src/backends/cl/workloads/ClPreluWorkload.cpp b/src/backends/cl/workloads/ClPreluWorkload.cpp new file mode 100644 index 0000000..1813105 --- /dev/null +++ b/src/backends/cl/workloads/ClPreluWorkload.cpp @@ -0,0 +1,48 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "ClPreluWorkload.hpp" +#include "ClWorkloadUtils.hpp" +#include +#include +#include +#include + +namespace armnn +{ + +arm_compute::Status ClPreluWorkloadValidate(const TensorInfo& input, + const TensorInfo& alpha, + const TensorInfo& output) +{ + const arm_compute::TensorInfo aclInput = armcomputetensorutils::BuildArmComputeTensorInfo(input); + const arm_compute::TensorInfo aclAlpha = armcomputetensorutils::BuildArmComputeTensorInfo(alpha); + const arm_compute::TensorInfo aclOutput = armcomputetensorutils::BuildArmComputeTensorInfo(output); + + return arm_compute::CLPReluLayer::validate(&aclInput, + &aclAlpha, + &aclOutput); +} + +ClPreluWorkload::ClPreluWorkload(const PreluQueueDescriptor& descriptor, + const WorkloadInfo& info) + : BaseWorkload(descriptor, info) +{ + m_Data.ValidateInputsOutputs("ClPreluWorkload", 1, 1); + + arm_compute::ICLTensor& input = static_cast(m_Data.m_Inputs[0])->GetTensor(); + arm_compute::ICLTensor& alpha = static_cast(m_Data.m_Inputs[1])->GetTensor(); + arm_compute::ICLTensor& output = static_cast(m_Data.m_Outputs[0])->GetTensor(); + + m_PreluLayer.configure(&input, &alpha, &output); +} + +void ClPreluWorkload::Execute() const +{ + ARMNN_SCOPED_PROFILING_EVENT_CL("ClPreluWorkload_Execute"); + RunClFunction(m_PreluLayer, CHECK_LOCATION()); +} + +} //namespace armnn diff --git a/src/backends/cl/workloads/ClPreluWorkload.hpp b/src/backends/cl/workloads/ClPreluWorkload.hpp new file mode 100644 index 0000000..6ffe4ca --- /dev/null +++ b/src/backends/cl/workloads/ClPreluWorkload.hpp @@ -0,0 +1,28 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include + +#include + +namespace armnn +{ +arm_compute::Status ClPreluWorkloadValidate(const TensorInfo& input, + const TensorInfo& alpha, + const TensorInfo& output); + +class ClPreluWorkload : public BaseWorkload +{ +public: + ClPreluWorkload(const PreluQueueDescriptor& descriptor, const WorkloadInfo& info); + void Execute() const override; + +private: + mutable arm_compute::CLPReluLayer m_PreluLayer; +}; + +} //namespace armnn diff --git a/src/backends/cl/workloads/ClWorkloads.hpp b/src/backends/cl/workloads/ClWorkloads.hpp index e82afc5..6ba8138 100644 --- a/src/backends/cl/workloads/ClWorkloads.hpp +++ b/src/backends/cl/workloads/ClWorkloads.hpp @@ -27,6 +27,7 @@ #include "ClPermuteWorkload.hpp" #include "ClPadWorkload.hpp" #include "ClPooling2dWorkload.hpp" +#include "ClPreluWorkload.hpp" #include "ClQuantizeWorkload.hpp" #include "ClReshapeWorkload.hpp" #include "ClResizeBilinearFloatWorkload.hpp" -- 2.7.4