From ae2c5f0350a7033f58578f9c509345445a639865 Mon Sep 17 00:00:00 2001 From: Nattapat Chaimanowong Date: Wed, 24 Apr 2019 16:19:57 +0100 Subject: IVGCVSW-2982 Refactor reference Activation workload Change-Id: Ia3b9a56787cc68822a3c1635de82e03ecc0aae27 Signed-off-by: Nattapat Chaimanowong --- src/backends/backendsCommon/WorkloadData.cpp | 14 ++ src/backends/reference/RefWorkloadFactory.cpp | 6 +- src/backends/reference/backend.mk | 3 +- .../reference/test/RefCreateWorkloadTests.cpp | 8 +- src/backends/reference/workloads/Activation.cpp | 150 ++++++++++++--------- src/backends/reference/workloads/Activation.hpp | 16 ++- src/backends/reference/workloads/CMakeLists.txt | 6 +- src/backends/reference/workloads/Decoders.hpp | 6 +- src/backends/reference/workloads/Encoders.hpp | 8 +- .../workloads/RefActivationFloat32Workload.cpp | 28 ---- .../workloads/RefActivationFloat32Workload.hpp | 20 --- .../workloads/RefActivationUint8Workload.cpp | 38 ------ .../workloads/RefActivationUint8Workload.hpp | 21 --- .../reference/workloads/RefActivationWorkload.cpp | 33 +++++ .../reference/workloads/RefActivationWorkload.hpp | 21 +++ src/backends/reference/workloads/RefWorkloads.hpp | 5 +- 16 files changed, 189 insertions(+), 194 deletions(-) delete mode 100644 src/backends/reference/workloads/RefActivationFloat32Workload.cpp delete mode 100644 src/backends/reference/workloads/RefActivationFloat32Workload.hpp delete mode 100644 src/backends/reference/workloads/RefActivationUint8Workload.cpp delete mode 100644 src/backends/reference/workloads/RefActivationUint8Workload.hpp create mode 100644 src/backends/reference/workloads/RefActivationWorkload.cpp create mode 100644 src/backends/reference/workloads/RefActivationWorkload.hpp diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp index df66b4e4c1..66e30f0592 100644 --- a/src/backends/backendsCommon/WorkloadData.cpp +++ b/src/backends/backendsCommon/WorkloadData.cpp @@ -297,6 +297,20 @@ void ActivationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const "ActivationQueueDescriptor", "input", "output"); + + std::vector supportedTypes = { + DataType::Float32, + DataType::Float16, + DataType::QuantisedAsymm8 + }; + + ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], + supportedTypes, + "ActivationQueueDescriptor"); + + ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0], + {workloadInfo.m_InputTensorInfos[0].GetDataType()}, + "ActivationQueueDescriptor"); } //--------------------------------------------------------------- diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp index b1c3ad79ac..8887bb719a 100644 --- a/src/backends/reference/RefWorkloadFactory.cpp +++ b/src/backends/reference/RefWorkloadFactory.cpp @@ -113,7 +113,11 @@ std::unique_ptr RefWorkloadFactory::CreateOutput(const OutputQueueDes std::unique_ptr RefWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor, const WorkloadInfo& info) const { - return MakeWorkload(descriptor, info); + if (IsFloat16(info)) + { + return MakeWorkload(descriptor, info); + } + return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateSoftmax(const SoftmaxQueueDescriptor& descriptor, diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk index e74e85378f..06459ed31b 100644 --- a/src/backends/reference/backend.mk +++ b/src/backends/reference/backend.mk @@ -24,8 +24,7 @@ BACKEND_SOURCES := \ workloads/Merger.cpp \ workloads/Pad.cpp \ workloads/Pooling2d.cpp \ - workloads/RefActivationFloat32Workload.cpp \ - workloads/RefActivationUint8Workload.cpp \ + workloads/RefActivationWorkload.cpp \ workloads/RefBatchNormalizationFloat32Workload.cpp \ workloads/RefBatchNormalizationUint8Workload.cpp \ workloads/RefBatchToSpaceNdFloat32Workload.cpp \ diff --git a/src/backends/reference/test/RefCreateWorkloadTests.cpp b/src/backends/reference/test/RefCreateWorkloadTests.cpp index 4b4e5449b4..5da1f94f6e 100644 --- a/src/backends/reference/test/RefCreateWorkloadTests.cpp +++ b/src/backends/reference/test/RefCreateWorkloadTests.cpp @@ -55,12 +55,12 @@ static void RefCreateActivationWorkloadTest() BOOST_AUTO_TEST_CASE(CreateActivationFloat32Workload) { - RefCreateActivationWorkloadTest(); + RefCreateActivationWorkloadTest(); } BOOST_AUTO_TEST_CASE(CreateActivationUint8Workload) { - RefCreateActivationWorkloadTest(); + RefCreateActivationWorkloadTest(); } template (); } BOOST_AUTO_TEST_CASE(CreateSingleOutputMultipleInputsUint8) { - RefCreateSingleOutputMultipleInputsTest(); } diff --git a/src/backends/reference/workloads/Activation.cpp b/src/backends/reference/workloads/Activation.cpp index ef4903074b..760c9a0ccd 100644 --- a/src/backends/reference/workloads/Activation.cpp +++ b/src/backends/reference/workloads/Activation.cpp @@ -11,6 +11,91 @@ namespace armnn { +float Activation(float in, + ActivationFunction function, + float a, + float b) +{ + float output; + + // Compute the result of the activation function. + switch (function) + { + case ActivationFunction::Linear: + { + output = a * in + b; + break; + } + case ActivationFunction::Sigmoid: + { + output = 1.f / (1.f + expf(-in)); + break; + } + case ActivationFunction::ReLu: + { + output = std::max(0.f, in); + break; + } + case ActivationFunction::BoundedReLu: + { + output = std::min(a, std::max(b, in)); + break; + } + case ActivationFunction::SoftReLu: + { + output = logf(1.0f + expf(in)); + break; + } + case ActivationFunction::LeakyReLu: + { + output = in > 0.0f ? in : (in * a); + break; + } + case ActivationFunction::Abs: + { + output = in < 0 ? -in : in; + break; + } + case ActivationFunction::Sqrt: + { + output = sqrtf(in); + break; + } + case ActivationFunction::Square: + { + output = in * in; + break; + } + case ActivationFunction::TanH: + { + output = a * tanhf(b * in); + break; + } + default: + { + throw InvalidArgumentException("Unsupported activation function"); + } + } + + return output; +} + + +void Activation(Decoder& in, + Encoder& out, + const TensorInfo& tensorInfo, + ActivationFunction function, + float a, + float b) +{ + for (size_t i = 0; i 0.0f ? input : (input * a); - break; - } - case ActivationFunction::Abs: - { - output = input < 0 ? -input : input; - break; - } - case ActivationFunction::Sqrt: - { - output = sqrtf(input); - break; - } - case ActivationFunction::Square: - { - output = input * input; - break; - } - case ActivationFunction::TanH: - { - output = a * tanhf(b * input); - break; - } - default: - { - BOOST_LOG_TRIVIAL(error) << "Unsupported activation function"; - return; - } - } - - out[i] = output; + out[i] = Activation(in[i], function, a, b); } } diff --git a/src/backends/reference/workloads/Activation.hpp b/src/backends/reference/workloads/Activation.hpp index c8a23114f0..ffe3c5fc5d 100644 --- a/src/backends/reference/workloads/Activation.hpp +++ b/src/backends/reference/workloads/Activation.hpp @@ -3,18 +3,30 @@ // SPDX-License-Identifier: MIT // +#include "BaseIterator.hpp" + #include #include namespace armnn { +float Activation(float in, + ActivationFunction function, + float a, + float b); -/// Performs the ActivationFunction elementwise on the inputs to give the outputs. +void Activation(Decoder& in, + Encoder& out, + const TensorInfo& tensorInfo, + ActivationFunction function, + float a, + float b); + +// This is still used by Reference LSTM implementation void Activation(const float* in, float* out, const TensorInfo& tensorInfo, ActivationFunction function, float a, float b); - } //namespace armnn diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt index e94b031060..596c0993e0 100644 --- a/src/backends/reference/workloads/CMakeLists.txt +++ b/src/backends/reference/workloads/CMakeLists.txt @@ -34,10 +34,8 @@ list(APPEND armnnRefBackendWorkloads_sources Pad.hpp Pooling2d.cpp Pooling2d.hpp - RefActivationFloat32Workload.cpp - RefActivationFloat32Workload.hpp - RefActivationUint8Workload.cpp - RefActivationUint8Workload.hpp + RefActivationWorkload.cpp + RefActivationWorkload.hpp RefBatchNormalizationFloat32Workload.cpp RefBatchNormalizationFloat32Workload.hpp RefBatchNormalizationUint8Workload.cpp diff --git a/src/backends/reference/workloads/Decoders.hpp b/src/backends/reference/workloads/Decoders.hpp index 4112e7d454..acf20c4b69 100644 --- a/src/backends/reference/workloads/Decoders.hpp +++ b/src/backends/reference/workloads/Decoders.hpp @@ -11,10 +11,10 @@ namespace armnn { template -std::unique_ptr> MakeDecoder(const TensorInfo& info, const void* data); +inline std::unique_ptr> MakeDecoder(const TensorInfo& info, const void* data); template<> -std::unique_ptr> MakeDecoder(const TensorInfo& info, const void* data) +inline std::unique_ptr> MakeDecoder(const TensorInfo& info, const void* data) { switch(info.GetDataType()) { @@ -45,4 +45,4 @@ std::unique_ptr> MakeDecoder(const TensorInfo& info, const void* return nullptr; } -} //namespace armnn \ No newline at end of file +} //namespace armnn diff --git a/src/backends/reference/workloads/Encoders.hpp b/src/backends/reference/workloads/Encoders.hpp index 90300aa0f7..547bead98a 100644 --- a/src/backends/reference/workloads/Encoders.hpp +++ b/src/backends/reference/workloads/Encoders.hpp @@ -11,10 +11,10 @@ namespace armnn { template -std::unique_ptr> MakeEncoder(const TensorInfo& info, void* data); +inline std::unique_ptr> MakeEncoder(const TensorInfo& info, void* data); template<> -std::unique_ptr> MakeEncoder(const TensorInfo& info, void* data) +inline std::unique_ptr> MakeEncoder(const TensorInfo& info, void* data) { switch(info.GetDataType()) { @@ -46,7 +46,7 @@ std::unique_ptr> MakeEncoder(const TensorInfo& info, void* data) } template<> -std::unique_ptr> MakeEncoder(const TensorInfo& info, void* data) +inline std::unique_ptr> MakeEncoder(const TensorInfo& info, void* data) { switch(info.GetDataType()) { @@ -63,4 +63,4 @@ std::unique_ptr> MakeEncoder(const TensorInfo& info, void* data) return nullptr; } -} //namespace armnn \ No newline at end of file +} //namespace armnn diff --git a/src/backends/reference/workloads/RefActivationFloat32Workload.cpp b/src/backends/reference/workloads/RefActivationFloat32Workload.cpp deleted file mode 100644 index 3cc59be7a4..0000000000 --- a/src/backends/reference/workloads/RefActivationFloat32Workload.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#include "RefActivationFloat32Workload.hpp" - -#include "Activation.hpp" -#include "RefWorkloadUtils.hpp" - -#include "Profiling.hpp" - -namespace armnn -{ - -void RefActivationFloat32Workload::Execute() const -{ - ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefActivationFloat32Workload_Execute"); - - Activation(GetInputTensorDataFloat(0, m_Data), - GetOutputTensorDataFloat(0, m_Data), - GetTensorInfo(m_Data.m_Inputs[0]), - m_Data.m_Parameters.m_Function, - m_Data.m_Parameters.m_A, - m_Data.m_Parameters.m_B); -} - -} //namespace armnn diff --git a/src/backends/reference/workloads/RefActivationFloat32Workload.hpp b/src/backends/reference/workloads/RefActivationFloat32Workload.hpp deleted file mode 100644 index dd65697e57..0000000000 --- a/src/backends/reference/workloads/RefActivationFloat32Workload.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#pragma once - -#include - -namespace armnn -{ - -class RefActivationFloat32Workload : public Float32Workload -{ -public: - using Float32Workload::Float32Workload; - virtual void Execute() const override; -}; - -} //namespace armnn diff --git a/src/backends/reference/workloads/RefActivationUint8Workload.cpp b/src/backends/reference/workloads/RefActivationUint8Workload.cpp deleted file mode 100644 index b95c2e22a8..0000000000 --- a/src/backends/reference/workloads/RefActivationUint8Workload.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#include "RefActivationUint8Workload.hpp" - -#include "Activation.hpp" -#include "RefWorkloadUtils.hpp" - -#include "Profiling.hpp" - -#include - -namespace armnn -{ - -void RefActivationUint8Workload::Execute() const -{ - ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefActivationUint8Workload_Execute"); - - const TensorInfo& tensorInfo = GetTensorInfo(m_Data.m_Inputs[0]); - - auto dequant = Dequantize(GetInputTensorDataU8(0, m_Data), tensorInfo); - - std::vector results(tensorInfo.GetNumElements()); - - Activation(dequant.data(), - results.data(), - tensorInfo, - m_Data.m_Parameters.m_Function, - m_Data.m_Parameters.m_A, - m_Data.m_Parameters.m_B); - - Quantize(GetOutputTensorDataU8(0, m_Data), results.data(), GetTensorInfo(m_Data.m_Outputs[0])); -} - -} //namespace armnn diff --git a/src/backends/reference/workloads/RefActivationUint8Workload.hpp b/src/backends/reference/workloads/RefActivationUint8Workload.hpp deleted file mode 100644 index 66f5e327f1..0000000000 --- a/src/backends/reference/workloads/RefActivationUint8Workload.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#pragma once - -#include -#include - -namespace armnn -{ - -class RefActivationUint8Workload : public Uint8Workload -{ -public: - using Uint8Workload::Uint8Workload; - virtual void Execute() const override; -}; - -} //namespace armnn diff --git a/src/backends/reference/workloads/RefActivationWorkload.cpp b/src/backends/reference/workloads/RefActivationWorkload.cpp new file mode 100644 index 0000000000..78c971e183 --- /dev/null +++ b/src/backends/reference/workloads/RefActivationWorkload.cpp @@ -0,0 +1,33 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "RefActivationWorkload.hpp" + +#include "Activation.hpp" +#include "Decoders.hpp" +#include "Encoders.hpp" +#include "RefWorkloadUtils.hpp" + +#include "Profiling.hpp" + +namespace armnn +{ + +void RefActivationWorkload::Execute() const +{ + ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefActivationWorkload_Execute"); + + const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]); + const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]); + + Activation(*MakeDecoder(inputInfo, m_Data.m_Inputs[0]->Map()), + *MakeEncoder(outputInfo, m_Data.m_Outputs[0]->Map()), + inputInfo, + m_Data.m_Parameters.m_Function, + m_Data.m_Parameters.m_A, + m_Data.m_Parameters.m_B); +} + +} //namespace armnn diff --git a/src/backends/reference/workloads/RefActivationWorkload.hpp b/src/backends/reference/workloads/RefActivationWorkload.hpp new file mode 100644 index 0000000000..a3b001e61f --- /dev/null +++ b/src/backends/reference/workloads/RefActivationWorkload.hpp @@ -0,0 +1,21 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include +#include + +namespace armnn +{ + +class RefActivationWorkload : public BaseWorkload +{ +public: + using BaseWorkload::BaseWorkload; + virtual void Execute() const override; +}; + +} //namespace armnn diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp index a1b584759b..7871a1b806 100644 --- a/src/backends/reference/workloads/RefWorkloads.hpp +++ b/src/backends/reference/workloads/RefWorkloads.hpp @@ -13,7 +13,7 @@ #include "RefSplitterUint8Workload.hpp" #include "RefResizeBilinearUint8Workload.hpp" #include "RefL2NormalizationFloat32Workload.hpp" -#include "RefActivationUint8Workload.hpp" +#include "RefActivationWorkload.hpp" #include "RefPooling2dFloat32Workload.hpp" #include "RefWorkloadUtils.hpp" #include "RefMergerUint8Workload.hpp" @@ -47,7 +47,6 @@ #include "RefSpaceToBatchNdWorkload.hpp" #include "RefSplitterFloat32Workload.hpp" #include "RefStridedSliceWorkload.hpp" -#include "RefActivationFloat32Workload.hpp" #include "RefConvolution2dFloat32Workload.hpp" #include "Pooling2d.hpp" #include "RefFakeQuantizationFloat32Workload.hpp" @@ -64,4 +63,4 @@ #include "RefRsqrtFloat32Workload.hpp" #include "RefDequantizeWorkload.hpp" -#include "RefQuantizeWorkload.hpp" \ No newline at end of file +#include "RefQuantizeWorkload.hpp" -- cgit v1.2.1