diff options
Diffstat (limited to 'src/backends/reference/workloads')
-rw-r--r-- | src/backends/reference/workloads/BaseIterator.hpp | 20 | ||||
-rw-r--r-- | src/backends/reference/workloads/Broadcast.cpp | 24 | ||||
-rw-r--r-- | src/backends/reference/workloads/Decoders.hpp | 3 | ||||
-rw-r--r-- | src/backends/reference/workloads/ElementwiseFunction.cpp | 4 | ||||
-rw-r--r-- | src/backends/reference/workloads/Encoders.hpp | 8 | ||||
-rw-r--r-- | src/backends/reference/workloads/Maximum.hpp | 22 | ||||
-rw-r--r-- | src/backends/reference/workloads/Pad.cpp | 82 | ||||
-rw-r--r-- | src/backends/reference/workloads/RefCastWorkload.cpp | 67 | ||||
-rw-r--r-- | src/backends/reference/workloads/RefElementwiseBinaryWorkload.cpp | 20 | ||||
-rw-r--r-- | src/backends/reference/workloads/Slice.cpp | 26 | ||||
-rw-r--r-- | src/backends/reference/workloads/StridedSlice.cpp | 103 |
11 files changed, 300 insertions, 79 deletions
diff --git a/src/backends/reference/workloads/BaseIterator.hpp b/src/backends/reference/workloads/BaseIterator.hpp index 5c5fff39d6..1cec5f3477 100644 --- a/src/backends/reference/workloads/BaseIterator.hpp +++ b/src/backends/reference/workloads/BaseIterator.hpp @@ -764,7 +764,7 @@ public: { ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(m_Iterator, "PerAxisIterator: m_Iterator is null!"); m_Iterator = m_Start + index; - if (index < m_AxisFactor) + if (index < m_AxisFactor || m_AxisDimensionality < 1) { m_AxisIndex = 0; } @@ -796,12 +796,12 @@ class QSymm8PerAxisDecoder : public PerAxisIterator<const int8_t, Decoder<float> public: QSymm8PerAxisDecoder(const int8_t* data, const armnn::TensorInfo& tensorInfo) : PerAxisIterator(data, tensorInfo.GetShape(), tensorInfo.GetQuantizationDim().value()), - m_Scales(tensorInfo.GetQuantizationScales()) + m_Scales(tensorInfo.GetQuantizationScales()), m_Offset(tensorInfo.GetQuantizationOffset()) {} float Get() const override { - return armnn::Dequantize(*m_Iterator, GetScale(), 0); + return armnn::Dequantize(*m_Iterator, GetScale(), m_Offset); } // Get scale of the current value @@ -819,29 +819,32 @@ public: for (uint32_t i = 0; i < size; ++i) { SetIndexOnMem(i); - decodedTensor.emplace_back(armnn::Dequantize(*m_Iterator, GetScale(), 0)); + decodedTensor.emplace_back(armnn::Dequantize(*m_Iterator, GetScale(), m_Offset)); } return decodedTensor; } private: std::vector<float> m_Scales; + const int32_t m_Offset; }; class QSymm8PerAxisEncoder : public PerAxisIterator<int8_t, Encoder<float>> { public: - QSymm8PerAxisEncoder(int8_t* data, const std::vector<float>& scale, unsigned int axisFactor) - : PerAxisIterator(data, axisFactor), m_Scale(scale) {} + QSymm8PerAxisEncoder(int8_t* data, const armnn::TensorInfo& tensorInfo) + : PerAxisIterator(data, tensorInfo.GetShape(), tensorInfo.GetQuantizationDim().value()), + m_Scale(tensorInfo.GetQuantizationScales()), m_Offset(tensorInfo.GetQuantizationOffset()) + {} void Set(float right) { - *m_Iterator = armnn::Quantize<int8_t>(right, m_Scale[m_AxisIndex], 0); + *m_Iterator = armnn::Quantize<int8_t>(right, m_Scale[m_AxisIndex], m_Offset); } float Get() const { - return armnn::Dequantize(*m_Iterator, m_Scale[m_AxisIndex], 0); + return armnn::Dequantize(*m_Iterator, m_Scale[m_AxisIndex], m_Offset); } // Get scale of the current value @@ -852,6 +855,7 @@ public: private: std::vector<float> m_Scale; + const int32_t m_Offset; }; class ScaledInt32PerAxisDecoder : public PerAxisIterator<const int32_t, Decoder<float>> diff --git a/src/backends/reference/workloads/Broadcast.cpp b/src/backends/reference/workloads/Broadcast.cpp index 24af0fc4b1..f17ec6b311 100644 --- a/src/backends/reference/workloads/Broadcast.cpp +++ b/src/backends/reference/workloads/Broadcast.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2019 Arm Ltd. All rights reserved. +// Copyright © 2019,2024 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // @@ -38,13 +38,31 @@ BroadcastLoop::BroadcastLoop(const TensorShape& inShape, const TensorShape& outS unsigned int sIn = 1; unsigned int sOut = 1; + // Get the difference between the output dimension and input dimension + const unsigned int dimDifference = numDims - inShape.GetNumDimensions(); + for (unsigned int j = numDims - 1, k = 0; k < numDims ; k++, j--) { + m_DimData[j].m_DimSize = outShape[j]; - m_DimData[j].m_Stride1 = (inShape[j] > 1) ? sIn : 0; + // Pretend there are extra 1-dimensional tensors prepended + if (dimDifference > 0 && j < dimDifference) + { + m_DimData[j].m_Stride1 = 0; + sIn *= 1; + } + else if (dimDifference > 0) + { + m_DimData[j].m_Stride1 = (inShape[j - dimDifference] > 1) ? sIn : 0; + sIn *= inShape[j - dimDifference]; + } + else + { + m_DimData[j].m_Stride1 = (inShape[j] > 1) ? sIn : 0; + sIn *= inShape[j]; + } m_DimData[j].m_StrideOut = sOut; - sIn *= inShape[j]; sOut *= outShape[j]; } } diff --git a/src/backends/reference/workloads/Decoders.hpp b/src/backends/reference/workloads/Decoders.hpp index 3bf3db7967..160244d3ca 100644 --- a/src/backends/reference/workloads/Decoders.hpp +++ b/src/backends/reference/workloads/Decoders.hpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd. All rights reserved. +// Copyright © 2017, 2024 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // @@ -102,7 +102,6 @@ inline std::unique_ptr<Decoder<float>> MakeDecoder(const TensorInfo& info, const { if (info.HasPerAxisQuantization()) { - std::pair<unsigned int, std::vector<float>> params = armnnUtils::GetPerAxisParams(info); return std::make_unique<QSymm8PerAxisDecoder>(static_cast<const int8_t*>(data), info); } else diff --git a/src/backends/reference/workloads/ElementwiseFunction.cpp b/src/backends/reference/workloads/ElementwiseFunction.cpp index 4044f06ac4..1d1ca5a856 100644 --- a/src/backends/reference/workloads/ElementwiseFunction.cpp +++ b/src/backends/reference/workloads/ElementwiseFunction.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2017-2021,2023 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2017-2021,2023-2024 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -67,6 +67,7 @@ template struct armnn::ElementwiseBinaryFunction<std::plus<float>>; template struct armnn::ElementwiseBinaryFunction<std::minus<float>>; template struct armnn::ElementwiseBinaryFunction<std::multiplies<float>>; template struct armnn::ElementwiseBinaryFunction<std::divides<float>>; +template struct armnn::ElementwiseBinaryFunction<armnn::floorDiv<float>>; template struct armnn::ElementwiseBinaryFunction<armnn::maximum<float>>; template struct armnn::ElementwiseBinaryFunction<armnn::minimum<float>>; template struct armnn::ElementwiseBinaryFunction<armnn::power<float>>; @@ -76,6 +77,7 @@ template struct armnn::ElementwiseBinaryFunction<std::plus<int32_t>>; template struct armnn::ElementwiseBinaryFunction<std::minus<int32_t>>; template struct armnn::ElementwiseBinaryFunction<std::multiplies<int32_t>>; template struct armnn::ElementwiseBinaryFunction<std::divides<int32_t>>; +template struct armnn::ElementwiseBinaryFunction<armnn::floorDiv<int32_t>>; template struct armnn::ElementwiseBinaryFunction<armnn::maximum<int32_t>>; template struct armnn::ElementwiseBinaryFunction<armnn::minimum<int32_t>>; template struct armnn::ElementwiseBinaryFunction<armnn::power<int32_t>>; diff --git a/src/backends/reference/workloads/Encoders.hpp b/src/backends/reference/workloads/Encoders.hpp index 5de361590a..aa0c834d2b 100644 --- a/src/backends/reference/workloads/Encoders.hpp +++ b/src/backends/reference/workloads/Encoders.hpp @@ -1,5 +1,5 @@ // -// Copyright © 2017-2023 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2017-2024 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -38,11 +38,7 @@ inline std::unique_ptr<Encoder<float>> MakeEncoder(const TensorInfo& info, void* { if (info.HasPerAxisQuantization()) { - std::pair<unsigned int, std::vector<float>> params = armnnUtils::GetPerAxisParams(info); - return std::make_unique<QSymm8PerAxisEncoder>( - static_cast<int8_t*>(data), - params.second, - params.first); + return std::make_unique<QSymm8PerAxisEncoder>(static_cast<int8_t*>(data), info); } else { diff --git a/src/backends/reference/workloads/Maximum.hpp b/src/backends/reference/workloads/Maximum.hpp index ca4b480b51..1e1f02d68a 100644 --- a/src/backends/reference/workloads/Maximum.hpp +++ b/src/backends/reference/workloads/Maximum.hpp @@ -1,24 +1,36 @@ // -// Copyright © 2017 Arm Ltd. All rights reserved. +// Copyright © 2017, 2024 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once -#include <iostream> + namespace armnn { template<typename T> struct maximum +{ + typedef T result_type; + typedef T first_argument_type; + + T operator () (const T& inputData0, const T& inputData1) const + { + return std::max(inputData0, inputData1); + } +}; + +template<typename T> +struct floorDiv { typedef T result_type; typedef T first_argument_type; - T - operator () (const T& inputData0, const T& inputData1) const + T operator () (const T& inputData0, const T& inputData1) const { - return std::max(inputData0, inputData1); + double result = static_cast<double>(inputData0)/static_cast<double>(inputData1); + return static_cast<T>(std::floor(result)); } }; diff --git a/src/backends/reference/workloads/Pad.cpp b/src/backends/reference/workloads/Pad.cpp index f58dbaea61..8273d34365 100644 --- a/src/backends/reference/workloads/Pad.cpp +++ b/src/backends/reference/workloads/Pad.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd. All rights reserved. +// Copyright © 2017,2024 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // @@ -63,7 +63,9 @@ void Pad(const TensorInfo& inputInfo, unsigned int inputChannels = 0; unsigned int inputHeight = 0; unsigned int inputWidth = 0; + unsigned int inputDim5 = 0; + unsigned int outputBatches = 0; unsigned int outputChannels = 0; unsigned int outputHeight = 0; unsigned int outputWidth = 0; @@ -76,6 +78,7 @@ void Pad(const TensorInfo& inputInfo, { // For Quantized types Pad Value should not be quantized with scale and offset of the tensor info auto temporaryInfo = TensorInfo(outputInfo.GetShape(), outputInfo.GetDataType(), 1.0f, 0); + auto outputData = MakeEncoder<float>(temporaryInfo, outputHandle->Map()); FillOutputWithPadValue(*outputData, padValue, numOutputElements); } @@ -95,13 +98,13 @@ void Pad(const TensorInfo& inputInfo, { input[w]; auto inputValue = input.Get(); - auto outputIndex = w + std::get<0>(padList[0]); + auto outputIndex = w + padList[0].first; output[outputIndex]; output.Set(inputValue); } break; - case 2 : + case 2: inputHeight = inputShape[0]; inputWidth = inputShape[1]; outputWidth = outputShape[1]; @@ -112,14 +115,14 @@ void Pad(const TensorInfo& inputInfo, { input[h * inputWidth + w]; auto inputValue = input.Get(); - auto outputIndex = (h + std::get<0>(padList[0])) * outputWidth + (w + std::get<0>(padList[1])); + auto outputIndex = (h + padList[0].first) * outputWidth + (w + padList[1].first); output[outputIndex]; output.Set(inputValue); } } break; - case 3 : + case 3: inputChannels = inputShape[0]; inputHeight = inputShape[1]; inputWidth = inputShape[2]; @@ -134,9 +137,9 @@ void Pad(const TensorInfo& inputInfo, { input[c * inputHeight * inputWidth + h * inputWidth + w]; auto inputValue = input.Get(); - auto outputIndex = (c + std::get<0>(padList[0])) * outputHeight * outputWidth - + (h + std::get<0>(padList[1])) * outputWidth - + (w + std::get<0>(padList[2])); + auto outputIndex = (c + padList[0].first) * outputHeight * outputWidth + + (h + padList[1].first) * outputWidth + + (w + padList[2].first); output[outputIndex]; output.Set(inputValue); } @@ -144,7 +147,7 @@ void Pad(const TensorInfo& inputInfo, } break; - case 4 : + case 4: inputBatches = inputShape[0]; inputChannels = inputShape[1]; inputHeight = inputShape[2]; @@ -162,24 +165,69 @@ void Pad(const TensorInfo& inputInfo, for (unsigned int w = 0; w < inputWidth ; w++) { input[b * inputChannels * inputHeight * inputWidth - + c * inputHeight * inputWidth - + h * inputWidth - + w]; + + c * inputHeight * inputWidth + + h * inputWidth + + w]; auto inputValue = input.Get(); - auto outputIndex = (b + std::get<0>(padList[0])) + auto outputIndex = (b + padList[0].first) * outputChannels * outputHeight * outputWidth - + (c + std::get<0>(padList[1])) * outputHeight * outputWidth - + (h + std::get<0>(padList[2])) * outputWidth - + (w + std::get<0>(padList[3])); + + (c + padList[1].first) * outputHeight * outputWidth + + (h + padList[2].first) * outputWidth + + (w + padList[3].first); output[outputIndex]; output.Set(inputValue); } } } } + break; + case 5: + inputBatches = inputShape[0]; + inputChannels = inputShape[1]; + inputHeight = inputShape[2]; + inputWidth = inputShape[3]; + inputDim5 = inputShape[4]; + + outputBatches = outputShape[1]; + outputChannels = outputShape[2]; + outputHeight = outputShape[3]; + outputWidth = outputShape[4]; + + for (unsigned int b = 0; b < inputBatches; ++b) + { + for (unsigned int c = 0; c < inputChannels; ++c) + { + for (unsigned int h = 0; h < inputHeight; ++h) + { + for (unsigned int w = 0; w < inputWidth ; ++w) + { + for (unsigned int d = 0; d < inputDim5 ; ++d) + { + input[b * inputChannels * inputHeight * inputWidth * inputDim5 + + c * inputHeight * inputWidth * inputDim5 + + h * inputWidth * inputDim5 + + d]; + + auto inputValue = input.Get(); + + auto outputIndex = (b + padList[0].first) + * outputBatches * outputChannels * outputHeight * outputWidth + + (c + padList[1].first) * outputChannels * outputHeight*outputWidth + + (h + padList[2].first) * outputHeight * outputWidth + + (w + padList[3].first) * outputWidth + + (d + padList[4].first); + + output[outputIndex]; + output.Set(inputValue); + } + } + } + } + } break; - default : + + default: break; } } diff --git a/src/backends/reference/workloads/RefCastWorkload.cpp b/src/backends/reference/workloads/RefCastWorkload.cpp index 40fbce6f4e..c8484d9672 100644 --- a/src/backends/reference/workloads/RefCastWorkload.cpp +++ b/src/backends/reference/workloads/RefCastWorkload.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2021-2023 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2021-2024 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -12,17 +12,54 @@ namespace { - void Cast(armnn::Decoder<float>& in, armnn::Encoder<float>& out, const uint32_t numElements ) + void Cast(armnn::Decoder<float>& in, armnn::Encoder<float>& out, + const uint32_t numElements, const armnn::DataType OutputDataType) { - for (unsigned int i = 0; i < numElements; i++) + for (unsigned int i = 0; i < numElements; ++i) + { + switch (OutputDataType) + { + case armnn::DataType::Float32: + case armnn::DataType::Float16: + case armnn::DataType::BFloat16: + out.Set(in.Get()); + break; + default: + out.Set(std::floor(in.Get())); + break; + } + ++in; + ++out; + } + } + + + // Cast Float to Int64 + void Cast(armnn::Decoder<float>& in, armnn::Encoder<double_t>& out, + const uint32_t numElements, const armnn::DataType) + { + for (unsigned int i = 0; i < numElements; ++i) { out.Set(in.Get()); ++in; ++out; } } + + // Cast Int64 To Float + void Cast(armnn::Decoder<double_t>& in, armnn::Encoder<float>& out, + const uint32_t numElements, const armnn::DataType) + { + for (unsigned int i = 0; i < numElements; ++i) + { + out.Set(static_cast<float>(in.Get())); + ++in; + ++out; + } + } } + namespace armnn { @@ -56,9 +93,27 @@ void RefCastWorkload::Execute(std::vector<ITensorHandle*> inputs, std::vector<IT outputTensorInfo.SetQuantizationOffset(0); } - Cast(*MakeDecoder<float>(inputTensorInfo, inputs[0]->Map()), - *MakeEncoder<float>(outputTensorInfo, outputs[0]->Map()), - inputTensorInfo.GetNumElements()); + if(inputTensorInfo.GetDataType() == DataType::Signed64) + { + Cast(*MakeDecoder<double_t>(inputTensorInfo, inputs[0]->Map()), + *MakeEncoder<float>(outputTensorInfo, outputs[0]->Map()), + inputTensorInfo.GetNumElements(), + outputTensorInfo.GetDataType()); + } + else if(outputTensorInfo.GetDataType() == DataType::Signed64) + { + Cast(*MakeDecoder<float>(inputTensorInfo, inputs[0]->Map()), + *MakeEncoder<double_t>(outputTensorInfo, outputs[0]->Map()), + inputTensorInfo.GetNumElements(), + outputTensorInfo.GetDataType()); + } + else + { + Cast(*MakeDecoder<float>(inputTensorInfo, inputs[0]->Map()), + *MakeEncoder<float>(outputTensorInfo, outputs[0]->Map()), + inputTensorInfo.GetNumElements(), + outputTensorInfo.GetDataType()); + } } } //namespace armnn
\ No newline at end of file diff --git a/src/backends/reference/workloads/RefElementwiseBinaryWorkload.cpp b/src/backends/reference/workloads/RefElementwiseBinaryWorkload.cpp index 2f30dff211..0cefe0f20d 100644 --- a/src/backends/reference/workloads/RefElementwiseBinaryWorkload.cpp +++ b/src/backends/reference/workloads/RefElementwiseBinaryWorkload.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2023 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2023-2024 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -26,7 +26,8 @@ namespace armnn template<typename DataType> void ExecuteFunction(std::vector<ITensorHandle*> inputs, std::vector<ITensorHandle*> outputs, - BinaryOperation operation) + BinaryOperation operation, + const std::string& layerName = "") { const TensorInfo& inputInfo0 = GetTensorInfo(inputs[0]); const TensorInfo& inputInfo1 = GetTensorInfo(inputs[1]); @@ -42,6 +43,7 @@ void ExecuteFunction(std::vector<ITensorHandle*> inputs, using AddFunction = ElementwiseBinaryFunction<std::plus<DataType>>; using DivFunction = ElementwiseBinaryFunction<std::divides<DataType>>; + using FloorDivFunction = ElementwiseBinaryFunction<armnn::floorDiv<DataType>>; using MaximumFunction = ElementwiseBinaryFunction<armnn::maximum<DataType>>; using MinimumFunction = ElementwiseBinaryFunction<armnn::minimum<DataType>>; using MulFunction = ElementwiseBinaryFunction<std::multiplies<DataType>>; @@ -49,6 +51,7 @@ void ExecuteFunction(std::vector<ITensorHandle*> inputs, using SqDiffFunction = ElementwiseBinaryFunction<armnn::squaredDifference<DataType>>; using PowerFunction = ElementwiseBinaryFunction<armnn::power<DataType>>; + switch (operation) { case BinaryOperation::Add: @@ -58,7 +61,14 @@ void ExecuteFunction(std::vector<ITensorHandle*> inputs, } case BinaryOperation::Div: { - DivFunction(inShape0, inShape1, outShape, *input0, *input1, *output); + if(!layerName.empty() && layerName.find("FloorDiv") != std::string::npos) + { + FloorDivFunction(inShape0, inShape1, outShape, *input0, *input1, *output); + } + else + { + DivFunction(inShape0, inShape1, outShape, *input0, *input1, *output); + } break; } case BinaryOperation::Maximum: @@ -123,11 +133,11 @@ void RefElementwiseBinaryWorkload::Execute(std::vector<ITensorHandle*> inputs, if (GetTensorInfo(inputs[0]).GetDataType() == DataType::Signed32) { - ExecuteFunction<int32_t>(inputs, outputs, m_Data.m_Parameters.m_Operation); + ExecuteFunction<int32_t>(inputs, outputs, m_Data.m_Parameters.m_Operation, m_Name); } else { - ExecuteFunction<float>(inputs, outputs, m_Data.m_Parameters.m_Operation); + ExecuteFunction<float>(inputs, outputs, m_Data.m_Parameters.m_Operation, m_Name); } } diff --git a/src/backends/reference/workloads/Slice.cpp b/src/backends/reference/workloads/Slice.cpp index 534a063ed5..1232e9f373 100644 --- a/src/backends/reference/workloads/Slice.cpp +++ b/src/backends/reference/workloads/Slice.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2019 Arm Ltd. All rights reserved. +// Copyright © 2019,2024 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // @@ -20,7 +20,7 @@ void Slice(const TensorInfo& inputInfo, const TensorShape& inputShape = inputInfo.GetShape(); const unsigned int numDims = inputShape.GetNumDimensions(); - constexpr unsigned int maxNumDims = 4; + constexpr unsigned int maxNumDims = 5; if (descriptor.m_Begin.size() != numDims) { std::stringstream msg; @@ -43,9 +43,9 @@ void Slice(const TensorInfo& inputInfo, throw InvalidArgumentException(msg.str()); } - std::vector<unsigned int> paddedInput(4); - std::vector<unsigned int> paddedBegin(4); - std::vector<unsigned int> paddedSize (4); + std::vector<unsigned int> paddedInput(5); + std::vector<unsigned int> paddedBegin(5); + std::vector<unsigned int> paddedSize (5); const unsigned int numPaddingDims = maxNumDims - numDims; for (unsigned int i = 0u; i < maxNumDims; ++i) @@ -69,16 +69,19 @@ void Slice(const TensorInfo& inputInfo, unsigned int dim1 = paddedInput[1]; unsigned int dim2 = paddedInput[2]; unsigned int dim3 = paddedInput[3]; + unsigned int dim4 = paddedInput[4]; unsigned int begin0 = paddedBegin[0]; unsigned int begin1 = paddedBegin[1]; unsigned int begin2 = paddedBegin[2]; unsigned int begin3 = paddedBegin[3]; + unsigned int begin4 = paddedBegin[4]; unsigned int size0 = paddedSize[0]; unsigned int size1 = paddedSize[1]; unsigned int size2 = paddedSize[2]; unsigned int size3 = paddedSize[3]; + unsigned int size4 = paddedSize[4]; if (begin0 + size0 > dim0) { @@ -129,11 +132,14 @@ void Slice(const TensorInfo& inputInfo, { for (unsigned int idx3 = begin3; idx3 < begin3 + size3; ++idx3) { - const unsigned int inputOffset = - (((idx0 * dim1 + idx1) * dim2 + idx2) * dim3 + idx3) * dataTypeSize; - - ::memcpy(output, input + inputOffset, dataTypeSize); - output += dataTypeSize; + for (unsigned int idx4 = begin4; idx4 < begin4 + size4; ++idx4) + { + const unsigned int inputOffset = + ((((idx0 * dim1 + idx1) * dim2 + idx2) * dim3 + idx3) * dim4 + idx4) * dataTypeSize; + + ::memcpy(output, input + inputOffset, dataTypeSize); + output += dataTypeSize; + } } } } diff --git a/src/backends/reference/workloads/StridedSlice.cpp b/src/backends/reference/workloads/StridedSlice.cpp index fcd1c357f8..a8828fdfbe 100644 --- a/src/backends/reference/workloads/StridedSlice.cpp +++ b/src/backends/reference/workloads/StridedSlice.cpp @@ -108,34 +108,105 @@ void StridedSlice(const TensorInfo& inputInfo, // Pad parameters to 4 dimensions PadParams(paddedParams, 4); - const int start0 = paddedParams.GetStartForAxis(inputShape, 0); - const int stop0 = paddedParams.GetStopForAxis (inputShape, 0, start0); + // Arrays containing the start and stop index for each axis (adjusted by set params/flags) + int startArray [4] = {0}; + int stopArray [4] = {0}; - const int start1 = paddedParams.GetStartForAxis(inputShape, 1); - const int stop1 = paddedParams.GetStopForAxis (inputShape, 1, start1); + // Getting paddedParams stop and start values for each axis + for(unsigned int i = 0; i < 4; ++i) + { + startArray[i] = paddedParams.GetStartForAxis(inputShape, i); + stopArray[i] = paddedParams.GetStopForAxis(inputShape, i, startArray[i]); + } - const int start2 = paddedParams.GetStartForAxis(inputShape, 2); - const int stop2 = paddedParams.GetStopForAxis (inputShape, 2, start2); + // Adjusting the EllipsisMask based on the NewAxisMask + // (if NewAxisMask extends an axis, the ellipsis flag is extended as well) + if(paddedParams.m_NewAxisMask > 0 && paddedParams.m_EllipsisMask > 0) + { + // Iterate until the current EllipsisMask 1-bit found + for(unsigned int i = 0; i < 4; ++i) + { + // If EllipsisMask bit found, adjust based on NewAxisMask and exit loop + if(paddedParams.m_EllipsisMask & (1 << i) && !(paddedParams.m_NewAxisMask & (1 << i))) + { + // If the previous bit is the NewAxisMask, set the EllipsisMask there + // (this condition was determined based on the unit tests expected data) + if(paddedParams.m_NewAxisMask & (1 << (i-1))) + { + paddedParams.m_EllipsisMask |= (1 << (i-1)); + } + // Otherwise, extend the EllipsisMask by one bit + else + { + paddedParams.m_EllipsisMask |= (1 << (i+1)); + } + break; + } + } + } - const int start3 = paddedParams.GetStartForAxis(inputShape, 3); - const int stop3 = paddedParams.GetStopForAxis (inputShape, 3, start3); + // Processing start and stop values based on the EllipsisMask and NewAxisMask + for(unsigned int i = 0, dimIdx = 0; i < 4; ++i) + { + // If the EllipsisMask is set, extend the start/stop to the input dimension size + if(paddedParams.m_EllipsisMask & (1 << dimIdx)) + { + startArray[i] = 0; + stopArray[i] = armnn::numeric_cast<int>(inputShape[i]); + } + // Otherwise, if the NewAxisMask is set, shift all following start/stop values to the left + else if(paddedParams.m_NewAxisMask & (1 << dimIdx)) + { + // Increment dimIdx - skip the current dimension for which NewAxisMask is set + ++dimIdx; + } + + // If the index of the currently processed dimension is higher than + // the index of the current start/stop array position, shift start/stop values + if(dimIdx > i && !(paddedParams.m_EllipsisMask & (1 << dimIdx))) + { + if(dimIdx < 4) + { + startArray[i] = startArray[dimIdx]; + stopArray[i] = stopArray[dimIdx]; + } + else + { + // If dimIdx is greater than the amount of available dimensions, + // instead of shifting the next ones, create new start/stop values + if(paddedParams.m_EllipsisMask > 0) + { + // The new values are 0,1 if there is an EllipsisMask bit present + startArray[i] = 0; + stopArray[i] = 1; + } + else + { + // Otherwise, select the entire inputTensor dimension size + startArray[i] = 0; + stopArray[i] = armnn::numeric_cast<int>(inputShape[i]); + } + } + } + ++dimIdx; + } const int step = armnn::numeric_cast<int>(dataTypeSize); - for (int in0 = start0; - !LoopCondition(in0, stop0, paddedParams.m_Stride[0]); + for (int in0 = startArray[0]; + !LoopCondition(in0, stopArray[0], paddedParams.m_Stride[0]); in0 += paddedParams.m_Stride[0]) { - for (int in1 = start1; - !LoopCondition(in1, stop1, paddedParams.m_Stride[1]); + for (int in1 = startArray[1]; + !LoopCondition(in1, stopArray[1], paddedParams.m_Stride[1]); in1 += paddedParams.m_Stride[1]) { - for (int in2 = start2; - !LoopCondition(in2, stop2, paddedParams.m_Stride[2]); + for (int in2 = startArray[2]; + !LoopCondition(in2, stopArray[2], paddedParams.m_Stride[2]); in2 += paddedParams.m_Stride[2]) { - for (int in3 = start3; - !LoopCondition(in3, stop3, paddedParams.m_Stride[3]); + for (int in3 = startArray[3]; + !LoopCondition(in3, stopArray[3], paddedParams.m_Stride[3]); in3 += paddedParams.m_Stride[3]) { int dim1 = armnn::numeric_cast<int>(inputShape[1]); |