From b2d3ec5b1e938ef34facfdbcff83fc8e845d5f7c Mon Sep 17 00:00:00 2001 From: Teresa Charlin Date: Tue, 12 Apr 2022 22:07:09 +0100 Subject: IVGCVSW-6856 Add GATHERNd FrontEnd and Ref Implementation * Add front end * Add reference workload * Add unit tests * Add EndToEnd test Signed-off-by: Teresa Charlin Change-Id: I4cebd17b18476df86162e2dda3366c10e80bd2f8 --- src/backends/reference/workloads/CMakeLists.txt | 2 + .../reference/workloads/RefGatherNdWorkload.cpp | 91 ++++++++++++++++++++++ .../reference/workloads/RefGatherNdWorkload.hpp | 24 ++++++ .../reference/workloads/RefGatherWorkload.cpp | 2 +- src/backends/reference/workloads/RefWorkloads.hpp | 1 + 5 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 src/backends/reference/workloads/RefGatherNdWorkload.cpp create mode 100644 src/backends/reference/workloads/RefGatherNdWorkload.hpp (limited to 'src/backends/reference/workloads') diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt index c18342fb73..b1f6d8b250 100644 --- a/src/backends/reference/workloads/CMakeLists.txt +++ b/src/backends/reference/workloads/CMakeLists.txt @@ -118,6 +118,8 @@ list(APPEND armnnRefBackendWorkloads_sources RefFloorWorkload.hpp RefFullyConnectedWorkload.cpp RefFullyConnectedWorkload.hpp + RefGatherNdWorkload.cpp + RefGatherNdWorkload.hpp RefGatherWorkload.cpp RefGatherWorkload.hpp RefInstanceNormalizationWorkload.cpp diff --git a/src/backends/reference/workloads/RefGatherNdWorkload.cpp b/src/backends/reference/workloads/RefGatherNdWorkload.cpp new file mode 100644 index 0000000000..4c6b559943 --- /dev/null +++ b/src/backends/reference/workloads/RefGatherNdWorkload.cpp @@ -0,0 +1,91 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "RefGatherNdWorkload.hpp" + +#include "Gather.hpp" +#include "Profiling.hpp" +#include "RefWorkloadUtils.hpp" +#include "backendsCommon/WorkloadUtils.hpp" + +namespace armnn +{ + +void RefGatherNdWorkload::Execute() const +{ + Execute(m_Data.m_Inputs, m_Data.m_Outputs); +} + +void RefGatherNdWorkload::ExecuteAsync(WorkingMemDescriptor &workingMemDescriptor) +{ + Execute(workingMemDescriptor.m_Inputs, workingMemDescriptor.m_Outputs); +} + +void RefGatherNdWorkload::Execute(std::vector inputs, std::vector outputs) const +{ + ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefGatherNdWorkload_Execute"); + + const TensorInfo& inputInfo0 = GetTensorInfo(inputs[0]); + const TensorInfo& inputInfo1 = GetTensorInfo(inputs[1]); + const TensorInfo& outputInfo = GetTensorInfo(outputs[0]); + + std::unique_ptr> params_decoderPtr = MakeDecoder(inputInfo0, inputs[0]->Map()); + + const int32_t* indicesDataPtr = reinterpret_cast(inputs[1]->Map()); + std::vector indices(indicesDataPtr, indicesDataPtr + inputInfo1.GetNumElements()); + + std::unique_ptr> output_encoderPtr = MakeEncoder(outputInfo, outputs[0]->Map()); + + std::map keyIndices = CalculateGatherNdKeyIndices(inputInfo0, inputInfo1); + + /// Calculate flattened indices: flattenedIndices = indices * flattenedCoefficients + // Calculate the flattened coefficients to use in the multiplication + // to calculate the flattened indices needed by gather + TensorShape paramsShape = inputInfo0.GetShape(); + std::vector flattenedCoeff(keyIndices["ND"], 1); + for (unsigned int i = 1; i < keyIndices["ND"]; ++i) + { + flattenedCoeff[i-1] = paramsShape[i]; + } + for (unsigned int i = keyIndices["ND"]-1; i > 0; --i) + { + flattenedCoeff[i-1] *= flattenedCoeff[i]; + } + + // Prepare the vector to store the output of the matrix multiplication, + // which will represent the flattened indices needed by gather + armnn::TensorInfo flattenedIndices_Info = inputInfo1; + flattenedIndices_Info.SetShape({ keyIndices["W"] }); + std::vector flattenedIndices(flattenedIndices_Info.GetNumElements(), 0); + + // Multiplication to calculate the flattened indices, which are the indices needed by gather. + for (unsigned int i = 0; i < keyIndices["W"]; ++i) + { + for (unsigned int j = 0; j < keyIndices["ND"]; ++j) + { + flattenedIndices[i] += indices[i * keyIndices["ND"] + j] * static_cast(flattenedCoeff[j]); + } + } + + /// Call Gather with adequate shapes + // Reshape params into {K, C} + armnn::TensorInfo params_K_C_Info = inputInfo0; + params_K_C_Info.SetShape({ keyIndices["K"], keyIndices["C"] }); + + // Reshape indices into {N, W} + armnn::TensorInfo indices_N_W_Info = inputInfo1; + indices_N_W_Info.SetShape({ keyIndices["N"], keyIndices["W"] }); + + // Reshape output to have the shape given by gather {N, W, C} + // (the original outputInfo has the shape given by gatherNd) + armnn::TensorInfo outputGather_Info = outputInfo; + outputGather_Info.SetShape({ keyIndices["N"], keyIndices["W"], keyIndices["C"] }); + + // output_gather = gather(params_K_C, indices_N_W) + Gather(params_K_C_Info, indices_N_W_Info, outputGather_Info, + *params_decoderPtr, flattenedIndices.data(), *output_encoderPtr, 0); +} + +} //namespace armnn diff --git a/src/backends/reference/workloads/RefGatherNdWorkload.hpp b/src/backends/reference/workloads/RefGatherNdWorkload.hpp new file mode 100644 index 0000000000..a0d91586cc --- /dev/null +++ b/src/backends/reference/workloads/RefGatherNdWorkload.hpp @@ -0,0 +1,24 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "RefBaseWorkload.hpp" + +namespace armnn +{ + +class RefGatherNdWorkload : public RefBaseWorkload +{ +public: + using RefBaseWorkload::RefBaseWorkload; + void Execute() const override; + void ExecuteAsync(WorkingMemDescriptor& workingMemDescriptor) override; +private: + void Execute(std::vector inputs, std::vector outputs) const; + +}; + +} // namespace armnn diff --git a/src/backends/reference/workloads/RefGatherWorkload.cpp b/src/backends/reference/workloads/RefGatherWorkload.cpp index be3274f00a..8ad36e43b4 100644 --- a/src/backends/reference/workloads/RefGatherWorkload.cpp +++ b/src/backends/reference/workloads/RefGatherWorkload.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp index 700a1d6184..3e83304616 100644 --- a/src/backends/reference/workloads/RefWorkloads.hpp +++ b/src/backends/reference/workloads/RefWorkloads.hpp @@ -42,6 +42,7 @@ #include "RefFillWorkload.hpp" #include "RefFloorWorkload.hpp" #include "RefFullyConnectedWorkload.hpp" +#include "RefGatherNdWorkload.hpp" #include "RefGatherWorkload.hpp" #include "RefInstanceNormalizationWorkload.hpp" #include "RefL2NormalizationWorkload.hpp" -- cgit v1.2.1