From 4a8692cf18ebd3c4de125274d5c840d7be64e3cd Mon Sep 17 00:00:00 2001 From: David Beck Date: Fri, 7 Sep 2018 16:19:24 +0100 Subject: IVGCVSW-1801 : Cl implementation for SUB Change-Id: Ia2e1dda8653197454a50679d49020397f5327979 --- src/armnn/backends/ClLayerSupport.cpp | 7 +- src/armnn/backends/ClWorkloadFactory.cpp | 2 +- src/armnn/backends/ClWorkloads.hpp | 2 + .../ClWorkloads/ClSubtractionBaseWorkload.cpp | 64 +++++++++++++ .../ClWorkloads/ClSubtractionBaseWorkload.hpp | 29 ++++++ .../ClWorkloads/ClSubtractionFloatWorkload.cpp | 22 +++++ .../ClWorkloads/ClSubtractionFloatWorkload.hpp | 20 ++++ .../ClWorkloads/ClSubtractionUint8Workload.cpp | 18 ++++ .../ClWorkloads/ClSubtractionUint8Workload.hpp | 20 ++++ src/armnn/backends/test/ArmComputeCl.cpp | 19 ++++ src/armnn/backends/test/CreateWorkloadCl.cpp | 101 +++++++++++++-------- src/armnn/backends/test/Reference.cpp | 2 +- src/armnn/test/CreateWorkload.hpp | 33 +++++++ 13 files changed, 298 insertions(+), 41 deletions(-) create mode 100644 src/armnn/backends/ClWorkloads/ClSubtractionBaseWorkload.cpp create mode 100644 src/armnn/backends/ClWorkloads/ClSubtractionBaseWorkload.hpp create mode 100644 src/armnn/backends/ClWorkloads/ClSubtractionFloatWorkload.cpp create mode 100644 src/armnn/backends/ClWorkloads/ClSubtractionFloatWorkload.hpp create mode 100644 src/armnn/backends/ClWorkloads/ClSubtractionUint8Workload.cpp create mode 100644 src/armnn/backends/ClWorkloads/ClSubtractionUint8Workload.hpp (limited to 'src') diff --git a/src/armnn/backends/ClLayerSupport.cpp b/src/armnn/backends/ClLayerSupport.cpp index 7b5fee2175..3dba1ec94c 100644 --- a/src/armnn/backends/ClLayerSupport.cpp +++ b/src/armnn/backends/ClLayerSupport.cpp @@ -29,6 +29,7 @@ #include "ClWorkloads/ClPermuteWorkload.hpp" #include "ClWorkloads/ClNormalizationFloatWorkload.hpp" #include "ClWorkloads/ClSoftmaxBaseWorkload.hpp" +#include "ClWorkloads/ClSubtractionFloatWorkload.hpp" #include "ClWorkloads/ClLstmFloatWorkload.hpp" #endif @@ -255,8 +256,10 @@ bool IsSubtractionSupportedCl(const TensorInfo& input0, const TensorInfo& output, std::string* reasonIfUnsupported) { - // At the moment subtraction is not supported - return false; + return FORWARD_CL_LAYER_SUPPORT_FUNC(ClSubtractionValidate(input0, + input1, + output, + reasonIfUnsupported)); } bool IsFullyConnectedSupportedCl(const TensorInfo& input, diff --git a/src/armnn/backends/ClWorkloadFactory.cpp b/src/armnn/backends/ClWorkloadFactory.cpp index 75a2af8b5a..056a201783 100644 --- a/src/armnn/backends/ClWorkloadFactory.cpp +++ b/src/armnn/backends/ClWorkloadFactory.cpp @@ -172,7 +172,7 @@ std::unique_ptr ClWorkloadFactory::CreateDivision( std::unique_ptr ClWorkloadFactory::CreateSubtraction(const SubtractionQueueDescriptor& descriptor, const WorkloadInfo& info) const { - return MakeWorkload(descriptor, info); + return MakeWorkload(descriptor, info); } std::unique_ptr ClWorkloadFactory::CreateBatchNormalization( diff --git a/src/armnn/backends/ClWorkloads.hpp b/src/armnn/backends/ClWorkloads.hpp index e524a70c69..0800401a22 100644 --- a/src/armnn/backends/ClWorkloads.hpp +++ b/src/armnn/backends/ClWorkloads.hpp @@ -36,5 +36,7 @@ #include "backends/ClWorkloads/ClSoftmaxUint8Workload.hpp" #include "backends/ClWorkloads/ClSplitterFloatWorkload.hpp" #include "backends/ClWorkloads/ClSplitterUint8Workload.hpp" +#include "backends/ClWorkloads/ClSubtractionFloatWorkload.hpp" +#include "backends/ClWorkloads/ClSubtractionUint8Workload.hpp" #include "backends/ClWorkloads/ClConvertFp16ToFp32Workload.hpp" #include "backends/ClWorkloads/ClConvertFp32ToFp16Workload.hpp" diff --git a/src/armnn/backends/ClWorkloads/ClSubtractionBaseWorkload.cpp b/src/armnn/backends/ClWorkloads/ClSubtractionBaseWorkload.cpp new file mode 100644 index 0000000000..2145ed4a2a --- /dev/null +++ b/src/armnn/backends/ClWorkloads/ClSubtractionBaseWorkload.cpp @@ -0,0 +1,64 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "ClSubtractionBaseWorkload.hpp" + +#include "backends/ClTensorHandle.hpp" +#include "backends/CpuTensorHandle.hpp" +#include "backends/ArmComputeTensorUtils.hpp" + +namespace armnn +{ +using namespace armcomputetensorutils; + +static constexpr arm_compute::ConvertPolicy g_AclConvertPolicy = arm_compute::ConvertPolicy::SATURATE; + +template +ClSubtractionBaseWorkload::ClSubtractionBaseWorkload(const SubtractionQueueDescriptor& descriptor, + const WorkloadInfo& info) + : TypedWorkload(descriptor, info) +{ + this->m_Data.ValidateInputsOutputs("ClSubtractionBaseWorkload", 2, 1); + + arm_compute::ICLTensor& input0 = static_cast(this->m_Data.m_Inputs[0])->GetTensor(); + arm_compute::ICLTensor& input1 = static_cast(this->m_Data.m_Inputs[1])->GetTensor(); + arm_compute::ICLTensor& output = static_cast(this->m_Data.m_Outputs[0])->GetTensor(); + m_Layer.configure(&input0, &input1, &output, g_AclConvertPolicy); +} + +template +void ClSubtractionBaseWorkload::Execute() const +{ + ARMNN_SCOPED_PROFILING_EVENT_CL("ClSubtractionBaseWorkload_Execute"); + m_Layer.run(); +} + +bool ClSubtractionValidate(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + std::string* reasonIfUnsupported) +{ + const arm_compute::TensorInfo aclInput0Info = BuildArmComputeTensorInfo(input0); + const arm_compute::TensorInfo aclInput1Info = BuildArmComputeTensorInfo(input1); + const arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output); + + const arm_compute::Status aclStatus = arm_compute::CLArithmeticSubtraction::validate(&aclInput0Info, + &aclInput1Info, + &aclOutputInfo, + g_AclConvertPolicy); + + const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK); + if (!supported && reasonIfUnsupported) + { + *reasonIfUnsupported = aclStatus.error_description(); + } + + return supported; +} + +} //namespace armnn + +template class armnn::ClSubtractionBaseWorkload; +template class armnn::ClSubtractionBaseWorkload; diff --git a/src/armnn/backends/ClWorkloads/ClSubtractionBaseWorkload.hpp b/src/armnn/backends/ClWorkloads/ClSubtractionBaseWorkload.hpp new file mode 100644 index 0000000000..e4595d405a --- /dev/null +++ b/src/armnn/backends/ClWorkloads/ClSubtractionBaseWorkload.hpp @@ -0,0 +1,29 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "backends/ClWorkloadUtils.hpp" + +namespace armnn +{ + +template +class ClSubtractionBaseWorkload : public TypedWorkload +{ +public: + ClSubtractionBaseWorkload(const SubtractionQueueDescriptor& descriptor, const WorkloadInfo& info); + + void Execute() const override; + +private: + mutable arm_compute::CLArithmeticSubtraction m_Layer; +}; + +bool ClSubtractionValidate(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + std::string* reasonIfUnsupported); +} //namespace armnn diff --git a/src/armnn/backends/ClWorkloads/ClSubtractionFloatWorkload.cpp b/src/armnn/backends/ClWorkloads/ClSubtractionFloatWorkload.cpp new file mode 100644 index 0000000000..3321e20100 --- /dev/null +++ b/src/armnn/backends/ClWorkloads/ClSubtractionFloatWorkload.cpp @@ -0,0 +1,22 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "ClSubtractionFloatWorkload.hpp" + +#include "backends/ClTensorHandle.hpp" +#include "backends/CpuTensorHandle.hpp" +#include "backends/ArmComputeTensorUtils.hpp" + +namespace armnn +{ +using namespace armcomputetensorutils; + +void ClSubtractionFloatWorkload::Execute() const +{ + ARMNN_SCOPED_PROFILING_EVENT_CL("ClSubtractionFloatWorkload_Execute"); + ClSubtractionBaseWorkload::Execute(); +} + +} //namespace armnn diff --git a/src/armnn/backends/ClWorkloads/ClSubtractionFloatWorkload.hpp b/src/armnn/backends/ClWorkloads/ClSubtractionFloatWorkload.hpp new file mode 100644 index 0000000000..34a5e40983 --- /dev/null +++ b/src/armnn/backends/ClWorkloads/ClSubtractionFloatWorkload.hpp @@ -0,0 +1,20 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "ClSubtractionBaseWorkload.hpp" + +namespace armnn +{ + +class ClSubtractionFloatWorkload : public ClSubtractionBaseWorkload +{ +public: + using ClSubtractionBaseWorkload::ClSubtractionBaseWorkload; + void Execute() const override; +}; + +} //namespace armnn diff --git a/src/armnn/backends/ClWorkloads/ClSubtractionUint8Workload.cpp b/src/armnn/backends/ClWorkloads/ClSubtractionUint8Workload.cpp new file mode 100644 index 0000000000..966068d648 --- /dev/null +++ b/src/armnn/backends/ClWorkloads/ClSubtractionUint8Workload.cpp @@ -0,0 +1,18 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "ClSubtractionUint8Workload.hpp" + +namespace armnn +{ +using namespace armcomputetensorutils; + +void ClSubtractionUint8Workload::Execute() const +{ + ARMNN_SCOPED_PROFILING_EVENT_CL("ClSubtractionUint8Workload_Execute"); + ClSubtractionBaseWorkload::Execute(); +} + +} //namespace armnn diff --git a/src/armnn/backends/ClWorkloads/ClSubtractionUint8Workload.hpp b/src/armnn/backends/ClWorkloads/ClSubtractionUint8Workload.hpp new file mode 100644 index 0000000000..15b2059615 --- /dev/null +++ b/src/armnn/backends/ClWorkloads/ClSubtractionUint8Workload.hpp @@ -0,0 +1,20 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "ClSubtractionBaseWorkload.hpp" + +namespace armnn +{ + +class ClSubtractionUint8Workload : public ClSubtractionBaseWorkload +{ +public: + using ClSubtractionBaseWorkload::ClSubtractionBaseWorkload; + void Execute() const override; +}; + +} //namespace armnn diff --git a/src/armnn/backends/test/ArmComputeCl.cpp b/src/armnn/backends/test/ArmComputeCl.cpp index 275d570a6c..3303c3fb51 100644 --- a/src/armnn/backends/test/ArmComputeCl.cpp +++ b/src/armnn/backends/test/ArmComputeCl.cpp @@ -139,6 +139,25 @@ ARMNN_AUTO_TEST_CASE(UNSUPPORTED_L2Pooling2dSize9Uint8, L2Pooling2dSize9Uint8Tes // Add ARMNN_AUTO_TEST_CASE(SimpleAdd, AdditionTest) ARMNN_AUTO_TEST_CASE(AddBroadcast1Element, AdditionBroadcast1ElementTest) +ARMNN_AUTO_TEST_CASE(AddBroadcast, AdditionBroadcastTest) + +ARMNN_AUTO_TEST_CASE(AdditionUint8, AdditionUint8Test) +ARMNN_AUTO_TEST_CASE(AddBroadcastUint8, AdditionBroadcastUint8Test) +ARMNN_AUTO_TEST_CASE(AddBroadcast1ElementUint8, AdditionBroadcast1ElementUint8Test) + +// Sub +ARMNN_AUTO_TEST_CASE(SimpleSub, SubtractionTest) + +// TODO : +// 1, enable broadcast tests for SUB when COMPMID-1566 is implemented (IVGCVSW-1837) +// 2, enable quantized tests for SUB when COMPMID-1564 is implemented (IVGCVSW-1836) + +// ARMNN_AUTO_TEST_CASE(SubBroadcast1Element, SubtractionBroadcast1ElementTest) +// ARMNN_AUTO_TEST_CASE(SubBroadcast, SubtractionBroadcastTest) + +// ARMNN_AUTO_TEST_CASE(SubtractionUint8, SubtractionUint8Test) +// ARMNN_AUTO_TEST_CASE(SubBroadcastUint8, SubtractionBroadcastUint8Test) +// ARMNN_AUTO_TEST_CASE(SubBroadcast1ElementUint8, SubtractionBroadcast1ElementUint8Test) // Div ARMNN_AUTO_TEST_CASE(SimpleDivision, DivisionTest) diff --git a/src/armnn/backends/test/CreateWorkloadCl.cpp b/src/armnn/backends/test/CreateWorkloadCl.cpp index 96001a4b78..340279e619 100644 --- a/src/armnn/backends/test/CreateWorkloadCl.cpp +++ b/src/armnn/backends/test/CreateWorkloadCl.cpp @@ -47,15 +47,18 @@ BOOST_AUTO_TEST_CASE(CreateActivationFloat16Workload) ClCreateActivationWorkloadTest(); } -template -static void ClCreateAdditionWorkloadTest() +template +static void ClCreateArithmethicWorkloadTest() { Graph graph; ClWorkloadFactory factory; - auto workload = CreateAdditionWorkloadTest(factory, graph); + auto workload = CreateArithmeticWorkloadTest(factory, graph); - // Checks that inputs/outputs are as we expect them (see definition of CreateAdditionWorkloadTest). - AdditionQueueDescriptor queueDescriptor = workload->GetData(); + // Checks that inputs/outputs are as we expect them (see definition of CreateSubtractionWorkloadTest). + DescriptorType queueDescriptor = workload->GetData(); auto inputHandle1 = boost::polymorphic_downcast(queueDescriptor.m_Inputs[0]); auto inputHandle2 = boost::polymorphic_downcast(queueDescriptor.m_Inputs[1]); auto outputHandle = boost::polymorphic_downcast(queueDescriptor.m_Outputs[0]); @@ -66,12 +69,66 @@ static void ClCreateAdditionWorkloadTest() BOOST_AUTO_TEST_CASE(CreateAdditionFloatWorkload) { - ClCreateAdditionWorkloadTest(); + ClCreateArithmethicWorkloadTest(); } BOOST_AUTO_TEST_CASE(CreateAdditionFloat16Workload) { - ClCreateAdditionWorkloadTest(); + ClCreateArithmethicWorkloadTest(); +} + +BOOST_AUTO_TEST_CASE(CreateSubtractionFloatWorkload) +{ + ClCreateArithmethicWorkloadTest(); +} + +BOOST_AUTO_TEST_CASE(CreateSubtractionFloat16Workload) +{ + ClCreateArithmethicWorkloadTest(); +} + +BOOST_AUTO_TEST_CASE(CreateMultiplicationFloatWorkloadTest) +{ + ClCreateArithmethicWorkloadTest(); +} + +BOOST_AUTO_TEST_CASE(CreateMultiplicationFloat16WorkloadTest) +{ + ClCreateArithmethicWorkloadTest(); +} + +BOOST_AUTO_TEST_CASE(CreateDivisionFloatWorkloadTest) +{ + ClCreateArithmethicWorkloadTest(); +} + +BOOST_AUTO_TEST_CASE(CreateDivisionFloat16WorkloadTest) +{ + ClCreateArithmethicWorkloadTest(); } template @@ -219,36 +276,6 @@ BOOST_AUTO_TEST_CASE(CreateFullyConnectedFloat16WorkloadTest) ClCreateFullyConnectedWorkloadTest(); } - -template -static void ClCreateMultiplicationWorkloadTest() -{ - Graph graph; - ClWorkloadFactory factory; - - auto workload = - CreateMultiplicationWorkloadTest(factory, graph); - - // Checks that inputs/outputs are as we expect them (see definition of CreateMultiplicationWorkloadTest). - MultiplicationQueueDescriptor queueDescriptor = workload->GetData(); - auto inputHandle1 = boost::polymorphic_downcast(queueDescriptor.m_Inputs[0]); - auto inputHandle2 = boost::polymorphic_downcast(queueDescriptor.m_Inputs[1]); - auto outputHandle = boost::polymorphic_downcast(queueDescriptor.m_Outputs[0]); - BOOST_TEST(CompareIClTensorHandleShape(inputHandle1, {2, 3})); - BOOST_TEST(CompareIClTensorHandleShape(inputHandle2, {2, 3})); - BOOST_TEST(CompareIClTensorHandleShape(outputHandle, {2, 3})); -} - -BOOST_AUTO_TEST_CASE(CreateMultiplicationFloatWorkloadTest) -{ - ClCreateMultiplicationWorkloadTest(); -} - -BOOST_AUTO_TEST_CASE(CreateMultiplicationFloat16WorkloadTest) -{ - ClCreateMultiplicationWorkloadTest(); -} - template static void ClNormalizationWorkloadTest() { diff --git a/src/armnn/backends/test/Reference.cpp b/src/armnn/backends/test/Reference.cpp index 5a5f79d965..20e68d0ea1 100644 --- a/src/armnn/backends/test/Reference.cpp +++ b/src/armnn/backends/test/Reference.cpp @@ -151,7 +151,7 @@ ARMNN_AUTO_TEST_CASE(SimpleSub, SubtractionTest) ARMNN_AUTO_TEST_CASE(SubBroadcast1Element, SubtractionBroadcast1ElementTest) ARMNN_AUTO_TEST_CASE(SubBroadcast, SubtractionBroadcastTest) -ARMNN_AUTO_TEST_CASE(SubitionUint8, SubtractionUint8Test) +ARMNN_AUTO_TEST_CASE(SubtractionUint8, SubtractionUint8Test) ARMNN_AUTO_TEST_CASE(SubBroadcastUint8, SubtractionBroadcastUint8Test) ARMNN_AUTO_TEST_CASE(SubBroadcast1ElementUint8, SubtractionBroadcast1ElementUint8Test) diff --git a/src/armnn/test/CreateWorkload.hpp b/src/armnn/test/CreateWorkload.hpp index 6d975d4011..fb562e2ad0 100644 --- a/src/armnn/test/CreateWorkload.hpp +++ b/src/armnn/test/CreateWorkload.hpp @@ -126,6 +126,39 @@ std::unique_ptr CreateAdditionWorkloadTest(armnn::IWorkloadFac return workload; } +template +std::unique_ptr CreateArithmeticWorkloadTest(armnn::IWorkloadFactory& factory, + armnn::Graph& graph) +{ + // Creates the layer we're testing. + Layer* const layer = graph.AddLayer("layer"); + + // Creates extra layers. + Layer* const input1 = graph.AddLayer(1, "input1"); + Layer* const input2 = graph.AddLayer(2, "input2"); + Layer* const output = graph.AddLayer(0, "output"); + + // Connects up. + armnn::TensorInfo tensorInfo({2, 3}, DataType); + Connect(input1, layer, tensorInfo, 0, 0); + Connect(input2, layer, tensorInfo, 0, 1); + Connect(layer, output, tensorInfo); + CreateTensorHandles(graph, factory); + + // Makes the workload and checks it. + auto workload = MakeAndCheckWorkload(*layer, graph, factory); + + DescriptorType queueDescriptor = workload->GetData(); + BOOST_TEST(queueDescriptor.m_Inputs.size() == 2); + BOOST_TEST(queueDescriptor.m_Outputs.size() == 1); + + // Returns so we can do extra, backend-specific tests. + return workload; +} + template std::unique_ptr CreateBatchNormalizationWorkloadTest( armnn::IWorkloadFactory& factory, armnn::Graph& graph) -- cgit v1.2.1