diff options
author | Jim Flynn <jim.flynn@arm.com> | 2019-05-22 14:24:13 +0100 |
---|---|---|
committer | Jim Flynn <jim.flynn@arm.com> | 2019-05-28 17:50:33 +0100 |
commit | e242f2dc646f41e9162aaaf74e057ce39fcb92df (patch) | |
tree | d6c49b559c34d1d306b1e901501dded1c18f71c5 /src/backends/reference/workloads/Concatenate.cpp | |
parent | 2f2778f36e59537bbd47fb8b21e73c6c5a949584 (diff) | |
download | armnn-e242f2dc646f41e9162aaaf74e057ce39fcb92df.tar.gz |
IVGCVSW-3119 Rename MergerLayer to ConcatLayer
!android-nn-driver:1210
Change-Id: I940b3b9e421c92bfd55ae996f7bc54ac077f2604
Signed-off-by: Jim Flynn <jim.flynn@arm.com>
Diffstat (limited to 'src/backends/reference/workloads/Concatenate.cpp')
-rw-r--r-- | src/backends/reference/workloads/Concatenate.cpp | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/backends/reference/workloads/Concatenate.cpp b/src/backends/reference/workloads/Concatenate.cpp new file mode 100644 index 0000000000..bb55424c0c --- /dev/null +++ b/src/backends/reference/workloads/Concatenate.cpp @@ -0,0 +1,83 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "Concatenate.hpp" +#include "RefWorkloadUtils.hpp" +#include "Decoders.hpp" +#include "Encoders.hpp" + +namespace armnn +{ + +void Concatenate(const ConcatQueueDescriptor &data) +{ + const TensorInfo& outputInfo0 = GetTensorInfo(data.m_Outputs[0]); + + std::unique_ptr<Encoder<float>> encoderPtr = MakeEncoder<float>(outputInfo0, data.m_Outputs[0]->Map()); + Encoder<float>& encoder = *encoderPtr; + + for (unsigned int index = 0 ; index < outputInfo0.GetNumElements(); ++index) + { + unsigned int indices[MaxNumOfTensorDimensions] = { 0 }; + + unsigned int indexRemainder = index; + unsigned int dimensionStride = outputInfo0.GetNumElements(); + + for (unsigned int i = 0; i < outputInfo0.GetNumDimensions(); i++) + { + dimensionStride /= outputInfo0.GetShape()[i]; + indices[i] = indexRemainder / dimensionStride; // Use integer division to round down. + indexRemainder -= indices[i] * dimensionStride; + } + + for (unsigned int viewIdx = 0; viewIdx < data.m_ViewOrigins.size(); ++viewIdx) + { + ConcatQueueDescriptor::ViewOrigin const& view = data.m_ViewOrigins[viewIdx]; + + //Split view extents are defined by the size of (the corresponding) input tensor. + const TensorInfo& inputInfo = GetTensorInfo(data.m_Inputs[viewIdx]); + BOOST_ASSERT(inputInfo.GetNumDimensions() == outputInfo0.GetNumDimensions()); + + // Check all dimensions to see if this element is inside the given input view. + bool insideView = true; + for (unsigned int i = 0; i < inputInfo.GetNumDimensions(); i++) + { + if (indices[i] < view.m_Origin[i]) + { + insideView = false; + } + if (indices[i] >= view.m_Origin[i] + inputInfo.GetShape()[i]) + { + insideView = false; + } + } + + if (insideView) + { + std::unique_ptr<Decoder<float>> decoderPtr = + MakeDecoder<float>(inputInfo, data.m_Inputs[viewIdx]->Map()); + Decoder<float>& decoder = *decoderPtr; + unsigned int inIndex = 0; + unsigned int dimensionStride = 1; + + for (unsigned int i = inputInfo.GetNumDimensions(); i-- > 0;) + { + inIndex += dimensionStride * (indices[i] - view.m_Origin[i]); + dimensionStride *= inputInfo.GetShape()[i]; + } + decoder += inIndex; + encoder.Set(decoder.Get()); + + //What should we do if input views overlap on the output tensor? + //We could error, take the average, or shm else... + //For now just stop after finding first view (input) that matches. + break; + } + } + ++encoder; + } +} + +} //namespace armnn |