From 2dc0572f4d9f28b2e0c38b8ff183b3f7bd9900da Mon Sep 17 00:00:00 2001 From: James Conroy Date: Thu, 19 Sep 2019 17:00:31 +0100 Subject: IVGCVSW-3695 Add CL ArgMinMax workload * Also enabled copy to/from CL for Signed32. Signed-off-by: James Conroy Change-Id: I0113182891f9767de73f04dcd81252c84c996eda --- src/backends/cl/ClLayerSupport.cpp | 13 ++++ src/backends/cl/ClLayerSupport.hpp | 5 ++ src/backends/cl/ClTensorHandle.hpp | 16 +++++ src/backends/cl/ClWorkloadFactory.cpp | 6 ++ src/backends/cl/ClWorkloadFactory.hpp | 3 + src/backends/cl/backend.mk | 1 + src/backends/cl/test/ClLayerTests.cpp | 8 +++ src/backends/cl/workloads/CMakeLists.txt | 2 + src/backends/cl/workloads/ClArgMinMaxWorkload.cpp | 82 +++++++++++++++++++++++ src/backends/cl/workloads/ClArgMinMaxWorkload.hpp | 30 +++++++++ src/backends/cl/workloads/ClWorkloads.hpp | 1 + src/backends/neon/test/NeonLayerTests.cpp | 2 + 12 files changed, 169 insertions(+) create mode 100644 src/backends/cl/workloads/ClArgMinMaxWorkload.cpp create mode 100644 src/backends/cl/workloads/ClArgMinMaxWorkload.hpp diff --git a/src/backends/cl/ClLayerSupport.cpp b/src/backends/cl/ClLayerSupport.cpp index 6dcda96100..ed570bc448 100644 --- a/src/backends/cl/ClLayerSupport.cpp +++ b/src/backends/cl/ClLayerSupport.cpp @@ -19,6 +19,7 @@ #include "workloads/ClAbsWorkload.hpp" #include "workloads/ClAdditionWorkload.hpp" #include "workloads/ClActivationWorkload.hpp" +#include "workloads/ClArgMinMaxWorkload.hpp" #include "workloads/ClBatchNormalizationFloatWorkload.hpp" #include "workloads/ClBatchToSpaceNdWorkload.hpp" #include "workloads/ClConvertFp16ToFp32Workload.hpp" @@ -178,6 +179,18 @@ bool ClLayerSupport::IsAdditionSupported(const TensorInfo& input0, output); } +bool ClLayerSupport::IsArgMinMaxSupported(const TensorInfo& input, + const TensorInfo& output, + const ArgMinMaxDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + FORWARD_WORKLOAD_VALIDATE_FUNC(ClArgMinMaxWorkloadValidate, + reasonIfUnsupported, + input, + output, + descriptor); +} + bool ClLayerSupport::IsBatchNormalizationSupported(const TensorInfo& input, const TensorInfo& output, const TensorInfo& mean, diff --git a/src/backends/cl/ClLayerSupport.hpp b/src/backends/cl/ClLayerSupport.hpp index 26eb42e092..219ce3b49e 100644 --- a/src/backends/cl/ClLayerSupport.hpp +++ b/src/backends/cl/ClLayerSupport.hpp @@ -26,6 +26,11 @@ public: const TensorInfo& output, Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsArgMinMaxSupported(const TensorInfo& input, + const TensorInfo& output, + const ArgMinMaxDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsBatchNormalizationSupported(const TensorInfo& input, const TensorInfo& output, const TensorInfo& mean, diff --git a/src/backends/cl/ClTensorHandle.hpp b/src/backends/cl/ClTensorHandle.hpp index f5583c0b97..2423a8bbcb 100644 --- a/src/backends/cl/ClTensorHandle.hpp +++ b/src/backends/cl/ClTensorHandle.hpp @@ -110,6 +110,10 @@ private: armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(), static_cast(memory)); break; + case arm_compute::DataType::S32: + armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(), + static_cast(memory)); + break; default: { throw armnn::UnimplementedException(); @@ -142,6 +146,10 @@ private: armcomputetensorutils::CopyArmComputeITensorData(static_cast(memory), this->GetTensor()); break; + case arm_compute::DataType::S32: + armcomputetensorutils::CopyArmComputeITensorData(static_cast(memory), + this->GetTensor()); + break; default: { throw armnn::UnimplementedException(); @@ -222,6 +230,10 @@ private: armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(), static_cast(memory)); break; + case arm_compute::DataType::S32: + armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(), + static_cast(memory)); + break; default: { throw armnn::UnimplementedException(); @@ -254,6 +266,10 @@ private: armcomputetensorutils::CopyArmComputeITensorData(static_cast(memory), this->GetTensor()); break; + case arm_compute::DataType::S32: + armcomputetensorutils::CopyArmComputeITensorData(static_cast(memory), + this->GetTensor()); + break; default: { throw armnn::UnimplementedException(); diff --git a/src/backends/cl/ClWorkloadFactory.cpp b/src/backends/cl/ClWorkloadFactory.cpp index 04e09f4ff1..2a7c8fe4ef 100644 --- a/src/backends/cl/ClWorkloadFactory.cpp +++ b/src/backends/cl/ClWorkloadFactory.cpp @@ -144,6 +144,12 @@ std::unique_ptr ClWorkloadFactory::CreateAddition(const AdditionQueue return MakeWorkload(descriptor, info); } +std::unique_ptr ClWorkloadFactory::CreateArgMinMax(const ArgMinMaxQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + return std::make_unique(descriptor, info); +} + std::unique_ptr ClWorkloadFactory::CreateBatchNormalization( const BatchNormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const diff --git a/src/backends/cl/ClWorkloadFactory.hpp b/src/backends/cl/ClWorkloadFactory.hpp index 1cae6e1faf..18d12bedf2 100644 --- a/src/backends/cl/ClWorkloadFactory.hpp +++ b/src/backends/cl/ClWorkloadFactory.hpp @@ -47,6 +47,9 @@ public: std::unique_ptr CreateAddition(const AdditionQueueDescriptor& descriptor, const WorkloadInfo& info) const override; + std::unique_ptr CreateArgMinMax(const ArgMinMaxQueueDescriptor& descriptor, + const WorkloadInfo& info) const override; + std::unique_ptr CreateBatchNormalization(const BatchNormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const override; diff --git a/src/backends/cl/backend.mk b/src/backends/cl/backend.mk index b78bae1582..c43918693c 100644 --- a/src/backends/cl/backend.mk +++ b/src/backends/cl/backend.mk @@ -25,6 +25,7 @@ BACKEND_SOURCES := \ workloads/ClAbsWorkload.cpp \ workloads/ClActivationWorkload.cpp \ workloads/ClAdditionWorkload.cpp \ + workloads/ClArgMinMaxWorkload.cpp \ workloads/ClBatchNormalizationFloatWorkload.cpp \ workloads/ClBatchToSpaceNdWorkload.cpp \ workloads/ClConcatWorkload.cpp \ diff --git a/src/backends/cl/test/ClLayerTests.cpp b/src/backends/cl/test/ClLayerTests.cpp index 0fc8ece498..7d1fb8b251 100644 --- a/src/backends/cl/test/ClLayerTests.cpp +++ b/src/backends/cl/test/ClLayerTests.cpp @@ -872,6 +872,14 @@ ARMNN_AUTO_TEST_CASE(Abs3dFloat16, Abs3dTest) ARMNN_AUTO_TEST_CASE(AbsZeroFloat16, AbsZeroTest) +// ArgMinMax +ARMNN_AUTO_TEST_CASE(ArgMinFloat32, ArgMinSimpleTest) +ARMNN_AUTO_TEST_CASE(ArgMaxFloat32, ArgMaxSimpleTest) +ARMNN_AUTO_TEST_CASE(ArgMinChannel, ArgMinChannelTest) +ARMNN_AUTO_TEST_CASE(ArgMaxChannel, ArgMaxChannelTest) +ARMNN_AUTO_TEST_CASE(ArgMaxHeight, ArgMaxHeightTest) +ARMNN_AUTO_TEST_CASE(ArgMinWidth, ArgMinWidthTest) + #if defined(ARMNNREF_ENABLED) // The ARMNN_COMPARE_REF_AUTO_TEST_CASE and the ARMNN_COMPARE_REF_FIXTURE_TEST_CASE test units are not available diff --git a/src/backends/cl/workloads/CMakeLists.txt b/src/backends/cl/workloads/CMakeLists.txt index a9f320d51f..94c4a3e967 100644 --- a/src/backends/cl/workloads/CMakeLists.txt +++ b/src/backends/cl/workloads/CMakeLists.txt @@ -10,6 +10,8 @@ list(APPEND armnnClBackendWorkloads_sources ClActivationWorkload.hpp ClAdditionWorkload.cpp ClAdditionWorkload.hpp + ClArgMinMaxWorkload.cpp + ClArgMinMaxWorkload.hpp ClBatchNormalizationFloatWorkload.cpp ClBatchNormalizationFloatWorkload.hpp ClBatchToSpaceNdWorkload.cpp diff --git a/src/backends/cl/workloads/ClArgMinMaxWorkload.cpp b/src/backends/cl/workloads/ClArgMinMaxWorkload.cpp new file mode 100644 index 0000000000..3270b0a2f3 --- /dev/null +++ b/src/backends/cl/workloads/ClArgMinMaxWorkload.cpp @@ -0,0 +1,82 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "ClArgMinMaxWorkload.hpp" +#include "ClWorkloadUtils.hpp" + +#include + +#include + +#include + +#include +#include + +namespace +{ +unsigned int CalcAclAxis(unsigned int numDimensions, unsigned int axisIndex) +{ + return (numDimensions - axisIndex) - 1; +} + +} //namespace + +namespace armnn +{ + +arm_compute::Status ClArgMinMaxWorkloadValidate(const TensorInfo& input, + const TensorInfo& output, + const ArgMinMaxDescriptor& descriptor) +{ + const arm_compute::TensorInfo aclInput = armcomputetensorutils::BuildArmComputeTensorInfo(input); + const arm_compute::TensorInfo aclOutput = armcomputetensorutils::BuildArmComputeTensorInfo(output); + + auto numDims = input.GetNumDimensions(); + auto unsignedAxis = armnnUtils::GetUnsignedAxis(numDims, descriptor.m_Axis); + int aclAxis = boost::numeric_cast(CalcAclAxis(numDims, unsignedAxis)); + + if (descriptor.m_Function == ArgMinMaxFunction::Max) + { + return arm_compute::CLArgMinMaxLayer::validate(&aclInput, aclAxis, &aclOutput, + arm_compute::ReductionOperation::ARG_IDX_MAX); + } + else + { + return arm_compute::CLArgMinMaxLayer::validate(&aclInput, aclAxis, &aclOutput, + arm_compute::ReductionOperation::ARG_IDX_MIN); + } +} + + +ClArgMinMaxWorkload::ClArgMinMaxWorkload(const ArgMinMaxQueueDescriptor& descriptor, + const WorkloadInfo& info) + : BaseWorkload(descriptor, info) +{ + arm_compute::ICLTensor& input = static_cast(this->m_Data.m_Inputs[0])->GetTensor(); + arm_compute::ICLTensor& output = static_cast(this->m_Data.m_Outputs[0])->GetTensor(); + + auto numDims = info.m_InputTensorInfos[0].GetNumDimensions(); + auto unsignedAxis = armnnUtils::GetUnsignedAxis(numDims, m_Data.m_Parameters.m_Axis); + int aclAxis = boost::numeric_cast(CalcAclAxis(numDims, unsignedAxis)); + + if (m_Data.m_Parameters.m_Function == ArgMinMaxFunction::Max) + { + m_ArgMinMaxLayer.configure(&input, aclAxis, &output, arm_compute::ReductionOperation::ARG_IDX_MAX); + } + else + { + m_ArgMinMaxLayer.configure(&input, aclAxis, &output, arm_compute::ReductionOperation::ARG_IDX_MIN); + } +} + +void ClArgMinMaxWorkload::Execute() const +{ + ARMNN_SCOPED_PROFILING_EVENT_CL("ClArgMinMaxWorkload_Execute"); + RunClFunction(m_ArgMinMaxLayer, CHECK_LOCATION()); +} + +} //namespace armnn + diff --git a/src/backends/cl/workloads/ClArgMinMaxWorkload.hpp b/src/backends/cl/workloads/ClArgMinMaxWorkload.hpp new file mode 100644 index 0000000000..54f28e6175 --- /dev/null +++ b/src/backends/cl/workloads/ClArgMinMaxWorkload.hpp @@ -0,0 +1,30 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include + +#include +#include + +namespace armnn +{ + +arm_compute::Status ClArgMinMaxWorkloadValidate(const TensorInfo& input, + const TensorInfo& output, + const ArgMinMaxDescriptor& descriptor); + +class ClArgMinMaxWorkload : public BaseWorkload +{ +public: + ClArgMinMaxWorkload(const ArgMinMaxQueueDescriptor& descriptor, const WorkloadInfo& info); + virtual void Execute() const override; + +private: + mutable arm_compute::CLArgMinMaxLayer m_ArgMinMaxLayer; +}; + +} //namespace armnn diff --git a/src/backends/cl/workloads/ClWorkloads.hpp b/src/backends/cl/workloads/ClWorkloads.hpp index cd6ca5fe17..dd8c6996d4 100644 --- a/src/backends/cl/workloads/ClWorkloads.hpp +++ b/src/backends/cl/workloads/ClWorkloads.hpp @@ -7,6 +7,7 @@ #include "ClAbsWorkload.hpp" #include "ClActivationWorkload.hpp" #include "ClAdditionWorkload.hpp" +#include "ClArgMinMaxWorkload.hpp" #include "ClConstantWorkload.hpp" #include "ClBatchNormalizationFloatWorkload.hpp" #include "ClBatchToSpaceNdWorkload.hpp" diff --git a/src/backends/neon/test/NeonLayerTests.cpp b/src/backends/neon/test/NeonLayerTests.cpp index ef3c8379eb..ea9c813d34 100644 --- a/src/backends/neon/test/NeonLayerTests.cpp +++ b/src/backends/neon/test/NeonLayerTests.cpp @@ -955,6 +955,8 @@ ARMNN_AUTO_TEST_CASE(ArgMinFloat32, ArgMinSimpleTest) ARMNN_AUTO_TEST_CASE(ArgMaxFloat32, ArgMaxSimpleTest) ARMNN_AUTO_TEST_CASE(ArgMinChannel, ArgMinChannelTest) ARMNN_AUTO_TEST_CASE(ArgMaxChannel, ArgMaxChannelTest) +ARMNN_AUTO_TEST_CASE(ArgMaxHeight, ArgMaxHeightTest) +ARMNN_AUTO_TEST_CASE(ArgMinWidth, ArgMinWidthTest) #if defined(ARMNNREF_ENABLED) -- cgit v1.2.1