diff options
author | Aron Virginas-Tar <Aron.Virginas-Tar@arm.com> | 2019-10-14 15:12:00 +0100 |
---|---|---|
committer | Áron Virginás-Tar <aron.virginas-tar@arm.com> | 2019-10-15 11:46:03 +0000 |
commit | e662a940d3378cfe669ff7e259a6911713fc0df9 (patch) | |
tree | 40c6b83f2d4b936da053bcb74784a8a849c4c9bc /src/backends/reference/workloads | |
parent | f4d59a678d8ef8420f52d341bb60f1a583269e24 (diff) | |
download | armnn-e662a940d3378cfe669ff7e259a6911713fc0df9.tar.gz |
IVGCVSW-3975 Add reference workload for LOG_SOFTMAX
Signed-off-by: Aron Virginas-Tar <Aron.Virginas-Tar@arm.com>
Change-Id: I10bb7133e0e2d6d7199abdf39562b1226bbbd3e7
Diffstat (limited to 'src/backends/reference/workloads')
6 files changed, 173 insertions, 0 deletions
diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt index 9a5f427d37..b8eb95c729 100644 --- a/src/backends/reference/workloads/CMakeLists.txt +++ b/src/backends/reference/workloads/CMakeLists.txt @@ -37,6 +37,8 @@ list(APPEND armnnRefBackendWorkloads_sources Gather.hpp InstanceNorm.cpp InstanceNorm.hpp + LogSoftmax.cpp + LogSoftmax.hpp LstmUtils.hpp LstmUtils.cpp Maximum.hpp @@ -95,6 +97,8 @@ list(APPEND armnnRefBackendWorkloads_sources RefInstanceNormalizationWorkload.hpp RefL2NormalizationWorkload.cpp RefL2NormalizationWorkload.hpp + RefLogSoftmaxWorkload.cpp + RefLogSoftmaxWorkload.hpp RefLstmWorkload.cpp RefLstmWorkload.hpp RefMeanWorkload.cpp diff --git a/src/backends/reference/workloads/LogSoftmax.cpp b/src/backends/reference/workloads/LogSoftmax.cpp new file mode 100644 index 0000000000..3fa3dc0d8c --- /dev/null +++ b/src/backends/reference/workloads/LogSoftmax.cpp @@ -0,0 +1,91 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "LogSoftmax.hpp" + +#include <TensorUtils.hpp> + +#include <cmath> + +#include <boost/assert.hpp> +#include <boost/core/ignore_unused.hpp> +#include <boost/numeric/conversion/cast.hpp> + +namespace +{ + +inline bool ValidateAxis(int axis, unsigned int numDimensions) +{ + const int sNumDimensions = boost::numeric_cast<int>(numDimensions); + return axis < sNumDimensions && axis >= -sNumDimensions; +} + +} // anonymous namespace + +namespace armnn +{ + +void LogSoftmax(Decoder<float>& input, + Encoder<float>& output, + const TensorInfo& inputInfo, + const LogSoftmaxDescriptor& descriptor) +{ + const unsigned int numDimensions = inputInfo.GetNumDimensions(); + + bool axisIsValid = ValidateAxis(descriptor.m_Axis, numDimensions); + BOOST_ASSERT_MSG(axisIsValid, + "Axis index is not in range [-numDimensions, numDimensions)."); + boost::ignore_unused(axisIsValid); + + unsigned int uAxis = descriptor.m_Axis < 0 ? + numDimensions - boost::numeric_cast<unsigned int>(std::abs(descriptor.m_Axis)) : + boost::numeric_cast<unsigned int>(descriptor.m_Axis); + + const TensorShape& inputShape = inputInfo.GetShape(); + const unsigned int outerSize = armnnUtils::GetNumElementsBetween(inputShape, 0, uAxis); + const unsigned int axisSize = inputShape[uAxis]; + const unsigned int innerSize = armnnUtils::GetNumElementsBetween(inputShape, + uAxis + 1, + inputShape.GetNumDimensions()); + + for (unsigned int outer = 0; outer < outerSize; ++outer) + { + for (unsigned int inner = 0; inner < innerSize; ++inner) + { + // Find max + input[outer * axisSize * innerSize + inner]; + float maxValue = input.Get(); + for (unsigned int i = 1u; i < axisSize; ++i) + { + input[(outer * axisSize + i) * innerSize + inner]; + maxValue = std::max(maxValue, input.Get()); + } + + // Compute sum + float sum = 0.0f; + for (unsigned int i = 0u; i < axisSize; ++i) + { + input[(outer * axisSize + i) * innerSize + inner]; + sum += std::exp((input.Get() - maxValue) * descriptor.m_Beta); + } + + // Compute log sum + const float logSum = std::log(sum); + + // Compute result + for (unsigned int i = 0u; i < axisSize; ++i) + { + const unsigned int index = (outer * axisSize + i) * innerSize + inner; + + input [index]; + output[index]; + + output.Set((input.Get() - maxValue) * descriptor.m_Beta - logSum); + } + } + } +} + +} // namespace armnn diff --git a/src/backends/reference/workloads/LogSoftmax.hpp b/src/backends/reference/workloads/LogSoftmax.hpp new file mode 100644 index 0000000000..2e383992c9 --- /dev/null +++ b/src/backends/reference/workloads/LogSoftmax.hpp @@ -0,0 +1,20 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "BaseIterator.hpp" + +#include <armnn/Tensor.hpp> + +namespace armnn +{ + +void LogSoftmax(Decoder<float>& input, + Encoder<float>& output, + const TensorInfo& inputInfo, + const LogSoftmaxDescriptor& descriptor); + +} // namespace armnn diff --git a/src/backends/reference/workloads/RefLogSoftmaxWorkload.cpp b/src/backends/reference/workloads/RefLogSoftmaxWorkload.cpp new file mode 100644 index 0000000000..a987e79dda --- /dev/null +++ b/src/backends/reference/workloads/RefLogSoftmaxWorkload.cpp @@ -0,0 +1,36 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "RefLogSoftmaxWorkload.hpp" + +#include "Decoders.hpp" +#include "Encoders.hpp" +#include "LogSoftmax.hpp" +#include "RefWorkloadUtils.hpp" + +#include <Profiling.hpp> + +#include <boost/assert.hpp> + +namespace armnn +{ + +void RefLogSoftmaxWorkload::Execute() const +{ + ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefLogSoftmaxWorkload_Execute"); + + const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]); + const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]); + + std::unique_ptr<Decoder<float>> decoder = MakeDecoder<float>(inputInfo, m_Data.m_Inputs[0]->Map()); + std::unique_ptr<Encoder<float>> encoder = MakeEncoder<float>(outputInfo, m_Data.m_Outputs[0]->Map()); + + BOOST_ASSERT(decoder != nullptr); + BOOST_ASSERT(encoder != nullptr); + + LogSoftmax(*decoder, *encoder, inputInfo, m_Data.m_Parameters); +} + +} // namespace armnn diff --git a/src/backends/reference/workloads/RefLogSoftmaxWorkload.hpp b/src/backends/reference/workloads/RefLogSoftmaxWorkload.hpp new file mode 100644 index 0000000000..f5048d90b3 --- /dev/null +++ b/src/backends/reference/workloads/RefLogSoftmaxWorkload.hpp @@ -0,0 +1,21 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include <backendsCommon/Workload.hpp> +#include <backendsCommon/WorkloadData.hpp> + +namespace armnn +{ + +class RefLogSoftmaxWorkload : public BaseWorkload<LogSoftmaxQueueDescriptor> +{ +public: + using BaseWorkload<LogSoftmaxQueueDescriptor>::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 39dfa0517b..79d1935823 100644 --- a/src/backends/reference/workloads/RefWorkloads.hpp +++ b/src/backends/reference/workloads/RefWorkloads.hpp @@ -38,6 +38,7 @@ #include "RefGatherWorkload.hpp" #include "RefInstanceNormalizationWorkload.hpp" #include "RefL2NormalizationWorkload.hpp" +#include "RefLogSoftmaxWorkload.hpp" #include "RefLstmWorkload.hpp" #include "RefMeanWorkload.hpp" #include "RefNormalizationWorkload.hpp" |