From 4d1ff588288b1a7a98dd2fd7f2ba5717b8ecf102 Mon Sep 17 00:00:00 2001 From: James Conroy Date: Mon, 10 Jun 2019 17:06:39 +0100 Subject: IVGCVSW-3221 Refactor Mean ref workload and tests * Renamed RefMeanFloat32Workload and RefMeanUint8Workload to RefMeanWorkload, updated references to reflect this change. * Refactored RefFloorWorkload to use Decoders/Encoders, to support the use of multiple data types. * Deleted reference Unit8 Mean tests as they were duplicates of the Float32 tests. Refactored these tests to support multiple data types and updated references. * Adjusted the values used in the tests' input tensors so that they are more like floating point numbers e.g. change 1.0f to 1.5f. * Replace size_t with unsigned int in Mean ref workload, for better compatibility with the Encoder/Decoder, removed some unnecessary casts after this. * Added ValidateTensorDataTypesMatch() function to WorkloadData.cpp, added CreateIncorrectDimensionsErrorMsg function to RefLayerSupport.cpp. * Added passing and failing tests for ref IsMeanSupported. Signed-off-by: James Conroy Change-Id: Id3d44463d1385255c727a497d4026d21a49e7eb2 --- src/backends/backendsCommon/WorkloadData.cpp | 39 +++- .../test/IsLayerSupportedTestImpl.hpp | 29 +++ src/backends/backendsCommon/test/LayerTests.cpp | 231 --------------------- src/backends/backendsCommon/test/LayerTests.hpp | 203 +++++++++++++++--- src/backends/cl/test/ClLayerTests.cpp | 28 +-- src/backends/neon/test/NeonLayerTests.cpp | 28 +-- src/backends/reference/RefLayerSupport.cpp | 82 +++++++- src/backends/reference/RefWorkloadFactory.cpp | 6 +- src/backends/reference/backend.mk | 3 +- .../reference/test/RefLayerSupportTests.cpp | 25 +++ src/backends/reference/test/RefLayerTests.cpp | 28 +-- src/backends/reference/workloads/CMakeLists.txt | 6 +- src/backends/reference/workloads/Mean.cpp | 45 ++-- src/backends/reference/workloads/Mean.hpp | 5 +- .../reference/workloads/RefMeanFloat32Workload.cpp | 35 ---- .../reference/workloads/RefMeanFloat32Workload.hpp | 22 -- .../reference/workloads/RefMeanUint8Workload.cpp | 39 ---- .../reference/workloads/RefMeanUint8Workload.hpp | 21 -- .../reference/workloads/RefMeanWorkload.cpp | 34 +++ .../reference/workloads/RefMeanWorkload.hpp | 24 +++ src/backends/reference/workloads/RefWorkloads.hpp | 3 +- 21 files changed, 480 insertions(+), 456 deletions(-) delete mode 100644 src/backends/reference/workloads/RefMeanFloat32Workload.cpp delete mode 100644 src/backends/reference/workloads/RefMeanFloat32Workload.hpp delete mode 100644 src/backends/reference/workloads/RefMeanUint8Workload.cpp delete mode 100644 src/backends/reference/workloads/RefMeanUint8Workload.hpp create mode 100644 src/backends/reference/workloads/RefMeanWorkload.cpp create mode 100644 src/backends/reference/workloads/RefMeanWorkload.hpp diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp index a1d00c6945..1505078b77 100644 --- a/src/backends/backendsCommon/WorkloadData.cpp +++ b/src/backends/backendsCommon/WorkloadData.cpp @@ -271,6 +271,20 @@ void ValidateDataTypes(const TensorInfo& info, } } +//--------------------------------------------------------------- +void ValidateTensorDataTypesMatch(const TensorInfo& first, + const TensorInfo& second, + std::string const& descName, + std::string const& firstName, + std::string const& secondName) +{ + if (first.GetDataType() != second.GetDataType()) + { + throw InvalidArgumentException(descName + ": " + firstName + " & " + secondName + + " must have identical data types."); + } +} + } //namespace void QueueDescriptor::ValidateInputsOutputs(const std::string& descName, @@ -1275,25 +1289,40 @@ void MaximumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const void MeanQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const { - ValidateNumInputs(workloadInfo, "MeanQueueDescriptor", 1); - ValidateNumOutputs(workloadInfo, "MeanQueueDescriptor", 1); + const std::string meanQueueDescString = "MeanQueueDescriptor"; + + ValidateNumInputs(workloadInfo, meanQueueDescString, 1); + ValidateNumOutputs(workloadInfo, meanQueueDescString, 1); + + std::vector supportedTypes = + { + DataType::Float32, + DataType::Float16, + DataType::QuantisedAsymm8, + DataType::QuantisedSymm16 + }; const TensorInfo& input = workloadInfo.m_InputTensorInfos[0]; const TensorInfo& output = workloadInfo.m_OutputTensorInfos[0]; + // First check if input tensor data type is supported, then + // check if this data type matches the output tensor data type + ValidateDataTypes(input, supportedTypes, meanQueueDescString); + ValidateTensorDataTypesMatch(input, output, meanQueueDescString, "input", "output"); + if (m_Parameters.m_KeepDims) { - ValidateTensorNumDimensions(output, "MeanQueueDescriptor", input.GetNumDimensions(), "output"); + ValidateTensorNumDimensions(output, meanQueueDescString, input.GetNumDimensions(), "output"); } else if (m_Parameters.m_Axis.empty()) { - ValidateTensorNumDimensions(output, "MeanQueueDescriptor", 1, "output"); + ValidateTensorNumDimensions(output, meanQueueDescString, 1, "output"); } else { auto outputDim = input.GetNumDimensions() - boost::numeric_cast(m_Parameters.m_Axis.size()); ValidateTensorNumDimensions(output, - "MeanQueueDescriptor", + meanQueueDescString, outputDim > 0 ? outputDim : 1, "output"); } diff --git a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp index fa6ec1000b..ff632fc701 100644 --- a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp +++ b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp @@ -633,5 +633,34 @@ bool IsMeanLayerSupportedTests(std::string& reasonIfUnsupported) return result; } +// Tests that IsMeanSupported fails when input tensor dimensions +// do not match output tensor dimensions when keepDims == true +template +bool IsMeanLayerNotSupportedTests(std::string& reasonIfUnsupported) +{ + armnn::Graph graph; + static const std::vector axes = {}; + // Set keepDims == true + armnn::MeanDescriptor desc(axes, true); + + armnn::Layer* const layer = graph.AddLayer(desc, "LayerName"); + + armnn::Layer* const input = graph.AddLayer(0, "input"); + armnn::Layer* const output = graph.AddLayer(0, "output"); + + // Mismatching number of tensor dimensions + armnn::TensorInfo inputTensorInfo({1, 1, 1, 1}, InputDataType); + armnn::TensorInfo outputTensorInfo({1, 1}, OutputDataType); + + input->GetOutputSlot(0).Connect(layer->GetInputSlot(0)); + input->GetOutputHandler(0).SetTensorInfo(inputTensorInfo); + layer->GetOutputSlot(0).Connect(output->GetInputSlot(0)); + layer->GetOutputHandler(0).SetTensorInfo(outputTensorInfo); + + bool result = FactoryType::IsLayerSupported(*layer, InputDataType, reasonIfUnsupported); + + return result; +} + } //namespace diff --git a/src/backends/backendsCommon/test/LayerTests.cpp b/src/backends/backendsCommon/test/LayerTests.cpp index 9d40197776..55e799e1be 100644 --- a/src/backends/backendsCommon/test/LayerTests.cpp +++ b/src/backends/backendsCommon/test/LayerTests.cpp @@ -8368,237 +8368,6 @@ LayerTestResult PermuteFloat32ValueSet3Test( return PermuteFloat32ValueSet3TestCommon(workloadFactory, memoryManager); }; -namespace -{ - -template -LayerTestResult MeanTestHelper( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, - const unsigned int* inputShape, - const std::vector& inputData, - const std::vector& axis, - bool keepDims, - const unsigned int* outputShape, - const std::vector& outputData, - float scale = 1.0f, - int32_t offset = 0) -{ - auto dataType = (std::is_same::value ? armnn::DataType::QuantisedAsymm8 : armnn::DataType::Float32); - - armnn::TensorInfo inputTensorInfo(InputDim, inputShape, dataType); - armnn::TensorInfo outputTensorInfo(OutputDim, outputShape, dataType); - - inputTensorInfo.SetQuantizationScale(scale); - inputTensorInfo.SetQuantizationOffset(offset); - - outputTensorInfo.SetQuantizationScale(scale); - outputTensorInfo.SetQuantizationOffset(offset); - - auto input = MakeTensor(inputTensorInfo, inputData); - - LayerTestResult result(outputTensorInfo); - result.outputExpected = MakeTensor(outputTensorInfo, outputData); - - std::unique_ptr inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo); - std::unique_ptr outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo); - - armnn::MeanQueueDescriptor data; - data.m_Parameters.m_Axis = axis; - data.m_Parameters.m_KeepDims = keepDims; - armnn::WorkloadInfo info; - AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); - AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); - - std::unique_ptr workload = workloadFactory.CreateMean(data, info); - - inputHandle->Allocate(); - outputHandle->Allocate(); - - CopyDataToITensorHandle(inputHandle.get(), input.origin()); - - workload->PostAllocationConfigure(); - workload->Execute(); - - CopyDataFromITensorHandle(result.output.origin(), outputHandle.get()); - - return result; -} - -} // anonymous namespace - -LayerTestResult MeanUint8SimpleTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) -{ - const unsigned int inputShape[] = { 3, 2 }; - const unsigned int outputShape[] = { 1 }; - - std::vector input({ 1, 1, 2, 2, 3, 3 }); - std::vector output({ 2 }); - - return MeanTestHelper( - workloadFactory, memoryManager, inputShape, input, {}, false, outputShape, output); -} - -LayerTestResult MeanUint8SimpleAxisTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) -{ - const unsigned int inputShape[] = { 1, 1, 3, 2 }; - const unsigned int outputShape[] = { 1, 1, 2 }; - - std::vector input({ 1, 1, 2, 2, 3, 3 }); - std::vector output({ 2, 2 }); - - return MeanTestHelper( - workloadFactory, memoryManager, inputShape, input, { 2 }, false, outputShape, output); -} - -LayerTestResult MeanUint8KeepDimsTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) -{ - const unsigned int inputShape[] = { 1, 1, 3, 2 }; - const unsigned int outputShape[] = { 1, 1, 1, 2 }; - - std::vector input({ 1, 1, 2, 2, 3, 3 }); - std::vector output({ 2, 2 }); - - return MeanTestHelper( - workloadFactory, memoryManager, inputShape, input, { 2 }, true, outputShape, output); -} - -LayerTestResult MeanUint8MultipleDimsTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) -{ - const unsigned int inputShape[] = { 2, 3, 1, 2 }; - const unsigned int outputShape[] = { 1, 3, 1, 1 }; - - std::vector input({ 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6 }); - std::vector output({ 1, 3, 5 }); - - return MeanTestHelper( - workloadFactory, memoryManager, inputShape, input, { 0, 3 }, true, outputShape, output); -} - -LayerTestResult MeanVtsUint8Test( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) -{ - const unsigned int inputShape[] = { 4, 3, 2 }; - const unsigned int outputShape[] = { 2 }; - - std::vector input({ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24 }); - std::vector output({ 12, 13 }); - - return MeanTestHelper(workloadFactory, memoryManager, - inputShape, input, { 0, 1 }, false, outputShape, - output, 0.8f, 5); -} - -LayerTestResult MeanFloatSimpleTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) -{ - const unsigned int inputShape[] = { 3, 2 }; - const unsigned int outputShape[] = { 1 }; - - std::vector input({ 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f }); - std::vector output({ 2.0f }); - - return MeanTestHelper( - workloadFactory, memoryManager, inputShape, input, {}, false, outputShape, output); -} - -LayerTestResult MeanFloatSimpleAxisTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) -{ - const unsigned int inputShape[] = { 2, 3, 1, 2 }; - const unsigned int outputShape[] = { 3, 1, 2 }; - - std::vector input({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f }); - std::vector output({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f }); - - return MeanTestHelper( - workloadFactory, memoryManager, inputShape, input, { 0 }, false, outputShape, output); -} - -LayerTestResult MeanFloatKeepDimsTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) -{ - const unsigned int inputShape[] = { 1, 1, 3, 2 }; - const unsigned int outputShape[] = { 1, 1, 1, 2 }; - - std::vector input({ 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f }); - std::vector output({ 2.0f, 2.0f }); - - return MeanTestHelper( - workloadFactory, memoryManager, inputShape, input, { 2 }, true, outputShape, output); -} - -LayerTestResult MeanFloatMultipleDimsTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) -{ - const unsigned int inputShape[] = { 2, 3, 1, 2 }; - const unsigned int outputShape[] = { 1, 3, 1, 1 }; - - std::vector input({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f }); - std::vector output({ 1.5f, 3.5f, 5.5f }); - - return MeanTestHelper( - workloadFactory, memoryManager, inputShape, input, { 0, 3 }, true, outputShape, output); -} - -LayerTestResult MeanVtsFloat1Test( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) -{ - const unsigned int inputShape[] = { 4, 3, 2 }; - const unsigned int outputShape[] = { 2 }; - - std::vector input({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, - 15.0f, 16.0f, 17.0f, 18.0f, 19.0f, 20.0f, 21.0f, 22.0f, 23.0f, 24.0f }); - std::vector output({ 12.0f, 13.0f }); - - return MeanTestHelper( - workloadFactory, memoryManager, inputShape, input, { 0, 1 }, false, outputShape, output); -} - -LayerTestResult MeanVtsFloat2Test( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) -{ - const unsigned int inputShape[] = { 4, 3, 2 }; - const unsigned int outputShape[] = { 1, 3, 1 }; - - std::vector input({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, - 15.0f, 16.0f, 17.0f, 18.0f, 19.0f, 20.0f, 21.0f, 22.0f, 23.0f, 24.0f }); - std::vector output({ 10.5f, 12.5f, 14.5f }); - - return MeanTestHelper( - workloadFactory, memoryManager, inputShape, input, { 0, 2 }, true, outputShape, output); -} - -LayerTestResult MeanVtsFloat3Test( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) -{ - const unsigned int inputShape[] = { 1, 2, 2, 1 }; - const unsigned int outputShape[] = { 1, 2, 1 }; - - std::vector input({ 1.0f, 2.0f, 3.0f, 4.0f }); - std::vector output({ 1.5f, 3.5f }); - - return MeanTestHelper( - workloadFactory, memoryManager, inputShape, input, { 2 }, false, outputShape, output); -} - LayerTestResult AdditionAfterMaxPoolTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp index 3eed189c1b..fab1ad83c1 100644 --- a/src/backends/backendsCommon/test/LayerTests.hpp +++ b/src/backends/backendsCommon/test/LayerTests.hpp @@ -1448,51 +1448,38 @@ LayerTestResult MaximumBroadcast1DVectorInt16Test( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); -LayerTestResult MeanUint8SimpleTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); - -LayerTestResult MeanUint8SimpleAxisTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); - -LayerTestResult MeanUint8KeepDimsTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); - -LayerTestResult MeanUint8MultipleDimsTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); - -LayerTestResult MeanVtsUint8Test( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); - -LayerTestResult MeanFloatSimpleTest( +template> +LayerTestResult MeanSimpleTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); -LayerTestResult MeanFloatSimpleAxisTest( +template> +LayerTestResult MeanSimpleAxisTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); -LayerTestResult MeanFloatKeepDimsTest( +template> +LayerTestResult MeanKeepDimsTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); -LayerTestResult MeanFloatMultipleDimsTest( +template> +LayerTestResult MeanMultipleDimsTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); -LayerTestResult MeanVtsFloat1Test( +template> +LayerTestResult MeanVts1Test( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); -LayerTestResult MeanVtsFloat2Test( +template> +LayerTestResult MeanVts2Test( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); -LayerTestResult MeanVtsFloat3Test( +template> +LayerTestResult MeanVts3Test( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); @@ -2912,4 +2899,164 @@ template LayerTestResult( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, - const armnn::DataLayout dataLayout); \ No newline at end of file + const armnn::DataLayout dataLayout); + +template +LayerTestResult MeanTestHelper( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const unsigned int* inputShape, + const std::vector& inputData, + const std::vector& axis, + bool keepDims, + const unsigned int* outputShape, + const std::vector& outputData, + float scale = 1.0f, + int32_t offset = 0) +{ + armnn::TensorInfo inputTensorInfo(InputDim, inputShape, ArmnnType); + armnn::TensorInfo outputTensorInfo(OutputDim, outputShape, ArmnnType); + + inputTensorInfo.SetQuantizationScale(scale); + inputTensorInfo.SetQuantizationOffset(offset); + + outputTensorInfo.SetQuantizationScale(scale); + outputTensorInfo.SetQuantizationOffset(offset); + + auto input = MakeTensor(inputTensorInfo, ConvertToDataType(inputData, inputTensorInfo)); + + LayerTestResult result(outputTensorInfo); + result.outputExpected = MakeTensor( + outputTensorInfo, ConvertToDataType(outputData, outputTensorInfo)); + + std::unique_ptr inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo); + std::unique_ptr outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo); + + armnn::MeanQueueDescriptor data; + data.m_Parameters.m_Axis = axis; + data.m_Parameters.m_KeepDims = keepDims; + armnn::WorkloadInfo info; + AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); + AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); + + std::unique_ptr workload = workloadFactory.CreateMean(data, info); + + inputHandle->Allocate(); + outputHandle->Allocate(); + + CopyDataToITensorHandle(inputHandle.get(), input.origin()); + + workload->PostAllocationConfigure(); + workload->Execute(); + + CopyDataFromITensorHandle(result.output.origin(), outputHandle.get()); + + return result; +} + +template +LayerTestResult MeanSimpleTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + const unsigned int inputShape[] = { 3, 2 }; + const unsigned int outputShape[] = { 1 }; + + std::vector input({ 1.5f, 1.5f, 2.5f, 2.5f, 3.5f, 3.5f }); + std::vector output({ 2.5f }); + + return MeanTestHelper( + workloadFactory, memoryManager, inputShape, input, {}, false, outputShape, output); +} + +template +LayerTestResult MeanSimpleAxisTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + const unsigned int inputShape[] = { 2, 3, 1, 2 }; + const unsigned int outputShape[] = { 3, 1, 2 }; + + std::vector input({ 1.5f, 2.5f, 3.5f, 4.5f, 5.5f, 6.5f, 1.5f, 2.5f, 3.5f, 4.5f, 5.5f, 6.5f }); + std::vector output({ 1.5f, 2.5f, 3.5f, 4.5f, 5.5f, 6.5f }); + + return MeanTestHelper( + workloadFactory, memoryManager, inputShape, input, { 0 }, false, outputShape, output); +} + +template +LayerTestResult MeanKeepDimsTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + const unsigned int inputShape[] = { 1, 1, 3, 2 }; + const unsigned int outputShape[] = { 1, 1, 1, 2 }; + + std::vector input({ 1.5f, 1.5f, 2.5f, 2.5f, 3.5f, 3.5f }); + std::vector output({ 2.5f, 2.5f }); + + return MeanTestHelper( + workloadFactory, memoryManager, inputShape, input, { 2 }, true, outputShape, output); +} + +template +LayerTestResult MeanMultipleDimsTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + const unsigned int inputShape[] = { 2, 3, 1, 2 }; + const unsigned int outputShape[] = { 1, 3, 1, 1 }; + + std::vector input({ 1.5f, 2.5f, 3.5f, 4.5f, 5.5f, 6.5f, 1.5f, 2.5f, 3.5f, 4.5f, 5.5f, 6.5 }); + std::vector output({ 2.0f, 4.0f, 6.0f }); + + return MeanTestHelper( + workloadFactory, memoryManager, inputShape, input, { 0, 3 }, true, outputShape, output); +} + +template +LayerTestResult MeanVts1Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + const unsigned int inputShape[] = { 4, 3, 2 }; + const unsigned int outputShape[] = { 2 }; + + std::vector input({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, + 15.0f, 16.0f, 17.0f, 18.0f, 19.0f, 20.0f, 21.0f, 22.0f, 23.0f, 24.0f }); + std::vector output({ 12.0f, 13.0f }); + + return MeanTestHelper( + workloadFactory, memoryManager, inputShape, input, { 0, 1 }, false, outputShape, output); +} + +template +LayerTestResult MeanVts2Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + const unsigned int inputShape[] = { 4, 3, 2 }; + const unsigned int outputShape[] = { 1, 3, 1 }; + + std::vector input({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, + 15.0f, 16.0f, 17.0f, 18.0f, 19.0f, 20.0f, 21.0f, 22.0f, 23.0f, 24.0f }); + std::vector output({ 10.5f, 12.5f, 14.5f }); + + return MeanTestHelper( + workloadFactory, memoryManager, inputShape, input, { 0, 2 }, true, outputShape, output); +} + +template +LayerTestResult MeanVts3Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + const unsigned int inputShape[] = { 1, 2, 2, 1 }; + const unsigned int outputShape[] = { 1, 2, 1 }; + + std::vector input({ 1.0f, 2.0f, 3.0f, 4.0f }); + std::vector output({ 1.5f, 3.5f }); + + return MeanTestHelper( + workloadFactory, memoryManager, inputShape, input, { 2 }, false, outputShape, output); +} diff --git a/src/backends/cl/test/ClLayerTests.cpp b/src/backends/cl/test/ClLayerTests.cpp index fee980c8a0..164a42a2b6 100644 --- a/src/backends/cl/test/ClLayerTests.cpp +++ b/src/backends/cl/test/ClLayerTests.cpp @@ -357,19 +357,21 @@ ARMNN_AUTO_TEST_CASE(MaximumBroadcast1ElementUint8, MaximumBroadcast1ElementUint ARMNN_AUTO_TEST_CASE(MaximumBroadcast1DVectorUint8, MaximumBroadcast1DVectorUint8Test) // Mean -ARMNN_AUTO_TEST_CASE(MeanUint8Simple, MeanUint8SimpleTest) -ARMNN_AUTO_TEST_CASE(MeanUint8SimpleAxis, MeanUint8SimpleAxisTest) -ARMNN_AUTO_TEST_CASE(MeanUint8KeepDims, MeanUint8KeepDimsTest) -ARMNN_AUTO_TEST_CASE(MeanUint8MultipleDims, MeanUint8MultipleDimsTest) -ARMNN_AUTO_TEST_CASE(MeanVtsUint8, MeanVtsUint8Test) - -ARMNN_AUTO_TEST_CASE(MeanFloatSimple, MeanFloatSimpleTest) -ARMNN_AUTO_TEST_CASE(MeanFloatSimpleAxis, MeanFloatSimpleAxisTest) -ARMNN_AUTO_TEST_CASE(MeanFloatKeepDims, MeanFloatKeepDimsTest) -ARMNN_AUTO_TEST_CASE(MeanFloatMultipleDims, MeanFloatMultipleDimsTest) -ARMNN_AUTO_TEST_CASE(MeanVtsFloat1, MeanVtsFloat1Test) -ARMNN_AUTO_TEST_CASE(MeanVtsFloat2, MeanVtsFloat2Test) -ARMNN_AUTO_TEST_CASE(MeanVtsFloat3, MeanVtsFloat3Test) +ARMNN_AUTO_TEST_CASE(MeanSimpleFloat32, MeanSimpleTest) +ARMNN_AUTO_TEST_CASE(MeanSimpleAxisFloat32, MeanSimpleAxisTest) +ARMNN_AUTO_TEST_CASE(MeanKeepDimsFloat32, MeanKeepDimsTest) +ARMNN_AUTO_TEST_CASE(MeanMultipleDimsFloat32, MeanMultipleDimsTest) +ARMNN_AUTO_TEST_CASE(MeanVts1Float32, MeanVts1Test) +ARMNN_AUTO_TEST_CASE(MeanVts2Float32, MeanVts2Test) +ARMNN_AUTO_TEST_CASE(MeanVts3Float32, MeanVts3Test) + +ARMNN_AUTO_TEST_CASE(MeanSimpleQuantisedAsymm8, MeanSimpleTest) +ARMNN_AUTO_TEST_CASE(MeanSimpleAxisQuantisedAsymm8, MeanSimpleAxisTest) +ARMNN_AUTO_TEST_CASE(MeanKeepDimsQuantisedAsymm8, MeanKeepDimsTest) +ARMNN_AUTO_TEST_CASE(MeanMultipleDimsQuantisedAsymm8, MeanMultipleDimsTest) +ARMNN_AUTO_TEST_CASE(MeanVts1QuantisedAsymm8, MeanVts1Test) +ARMNN_AUTO_TEST_CASE(MeanVts2QuantisedAsymm8, MeanVts2Test) +ARMNN_AUTO_TEST_CASE(MeanVts3QuantisedAsymm8, MeanVts3Test) // Minimum ARMNN_AUTO_TEST_CASE(MinimumBroadcast1Element1, MinimumBroadcast1ElementTest1) diff --git a/src/backends/neon/test/NeonLayerTests.cpp b/src/backends/neon/test/NeonLayerTests.cpp index 4e719d2df8..af9db52bb1 100644 --- a/src/backends/neon/test/NeonLayerTests.cpp +++ b/src/backends/neon/test/NeonLayerTests.cpp @@ -438,19 +438,21 @@ ARMNN_AUTO_TEST_CASE(LstmLayerFloat32NoCifgWithPeepholeWithProjection, LstmLayerFloat32NoCifgWithPeepholeWithProjectionTest) // Mean -ARMNN_AUTO_TEST_CASE(MeanUint8Simple, MeanUint8SimpleTest) -ARMNN_AUTO_TEST_CASE(MeanUint8SimpleAxis, MeanUint8SimpleAxisTest) -ARMNN_AUTO_TEST_CASE(MeanUint8KeepDims, MeanUint8KeepDimsTest) -ARMNN_AUTO_TEST_CASE(MeanUint8MultipleDims, MeanUint8MultipleDimsTest) -ARMNN_AUTO_TEST_CASE(MeanVtsUint8, MeanVtsUint8Test) - -ARMNN_AUTO_TEST_CASE(MeanFloatSimple, MeanFloatSimpleTest) -ARMNN_AUTO_TEST_CASE(MeanFloatSimpleAxis, MeanFloatSimpleAxisTest) -ARMNN_AUTO_TEST_CASE(MeanFloatKeepDims, MeanFloatKeepDimsTest) -ARMNN_AUTO_TEST_CASE(MeanFloatMultipleDims, MeanFloatMultipleDimsTest) -ARMNN_AUTO_TEST_CASE(MeanVtsFloat1, MeanVtsFloat1Test) -ARMNN_AUTO_TEST_CASE(MeanVtsFloat2, MeanVtsFloat2Test) -ARMNN_AUTO_TEST_CASE(MeanVtsFloat3, MeanVtsFloat3Test) +ARMNN_AUTO_TEST_CASE(MeanSimpleFloat32, MeanSimpleTest) +ARMNN_AUTO_TEST_CASE(MeanSimpleAxisFloat32, MeanSimpleAxisTest) +ARMNN_AUTO_TEST_CASE(MeanKeepDimsFloat32, MeanKeepDimsTest) +ARMNN_AUTO_TEST_CASE(MeanMultipleDimsFloat32, MeanMultipleDimsTest) +ARMNN_AUTO_TEST_CASE(MeanVts1Float32, MeanVts1Test) +ARMNN_AUTO_TEST_CASE(MeanVts2Float32, MeanVts2Test) +ARMNN_AUTO_TEST_CASE(MeanVts3Float32, MeanVts3Test) + +ARMNN_AUTO_TEST_CASE(MeanSimpleQuantisedAsymm8, MeanSimpleTest) +ARMNN_AUTO_TEST_CASE(MeanSimpleAxisQuantisedAsymm8, MeanSimpleAxisTest) +ARMNN_AUTO_TEST_CASE(MeanKeepDimsQuantisedAsymm8, MeanKeepDimsTest) +ARMNN_AUTO_TEST_CASE(MeanMultipleDimsQuantisedAsymm8, MeanMultipleDimsTest) +ARMNN_AUTO_TEST_CASE(MeanVts1QuantisedAsymm8, MeanVts1Test) +ARMNN_AUTO_TEST_CASE(MeanVts2QuantisedAsymm8, MeanVts2Test) +ARMNN_AUTO_TEST_CASE(MeanVts3QuantisedAsymm8, MeanVts3Test) // Max ARMNN_AUTO_TEST_CASE(SimpleMaximum, MaximumSimpleTest) diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp index cf1814e06a..402bd66f02 100644 --- a/src/backends/reference/RefLayerSupport.cpp +++ b/src/backends/reference/RefLayerSupport.cpp @@ -47,6 +47,21 @@ bool IsSupportedForDataTypeRef(Optional reasonIfUnsupported, } // anonymous namespace +namespace +{ + +std::string CreateIncorrectDimensionsErrorMsg(unsigned int expected, + unsigned int actual, + std::string& layerStr, + std::string& tensorName) +{ + std::string errorMsg = "Reference " + layerStr + ": Expected " + std::to_string(expected) + " dimensions but got" + + " " + std::to_string(actual) + " dimensions instead, for the '" + tensorName + "' tensor."; + + return errorMsg; +} + +} // anonymous namespace namespace { @@ -177,6 +192,15 @@ struct ShapesAreBroadcastCompatible : public Rule } } }; + +struct TensorNumDimensionsAreCorrect : public Rule +{ + TensorNumDimensionsAreCorrect(const TensorInfo& info, unsigned int expectedNumDimensions) + { + m_Res = info.GetNumDimensions() == expectedNumDimensions; + } +}; + } // namespace @@ -874,12 +898,58 @@ bool RefLayerSupport::IsMeanSupported(const TensorInfo& input, const MeanDescriptor& descriptor, Optional reasonIfUnsupported) const { - ignore_unused(output); - ignore_unused(descriptor); - return IsSupportedForDataTypeRef(reasonIfUnsupported, - input.GetDataType(), - &TrueFunc<>, - &TrueFunc<>); + bool supported = true; + std::string meanLayerStr = "Mean"; + std::string outputTensorStr = "output"; + + std::array supportedTypes = + { + DataType::Float32, + DataType::QuantisedAsymm8 + }; + + supported &= CheckSupportRule(TypeAnyOf(input, supportedTypes), reasonIfUnsupported, + "Reference Mean: input type not supported."); + + supported &= CheckSupportRule(TypesAreEqual(input, output), reasonIfUnsupported, + "Reference Mean: input and output types are mismatched"); + + if (descriptor.m_KeepDims) + { + supported &= CheckSupportRule(TensorNumDimensionsAreCorrect(output, input.GetNumDimensions()), + reasonIfUnsupported, + CreateIncorrectDimensionsErrorMsg(input.GetNumDimensions(), + output.GetNumDimensions(), + meanLayerStr, outputTensorStr).data()); + } + else if (descriptor.m_Axis.empty()) + { + supported &= CheckSupportRule(TensorNumDimensionsAreCorrect(output, 1), + reasonIfUnsupported, + CreateIncorrectDimensionsErrorMsg(1, output.GetNumDimensions(), + meanLayerStr, outputTensorStr).data()); + } + else + { + auto outputDim = input.GetNumDimensions() - boost::numeric_cast(descriptor.m_Axis.size()); + + if (outputDim > 0) + { + supported &= CheckSupportRule(TensorNumDimensionsAreCorrect(output, outputDim), + reasonIfUnsupported, + CreateIncorrectDimensionsErrorMsg(outputDim, output.GetNumDimensions(), + meanLayerStr, outputTensorStr).data()); + } + else + { + supported &= CheckSupportRule(TensorNumDimensionsAreCorrect(output, 1), + reasonIfUnsupported, + CreateIncorrectDimensionsErrorMsg(1, output.GetNumDimensions(), + meanLayerStr, outputTensorStr).data()); + } + } + + return supported; } bool RefLayerSupport::IsMergerSupported(const std::vector inputs, diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp index 728e60520a..4467bd4ad6 100644 --- a/src/backends/reference/RefWorkloadFactory.cpp +++ b/src/backends/reference/RefWorkloadFactory.cpp @@ -353,7 +353,11 @@ std::unique_ptr RefWorkloadFactory::CreateMaximum( std::unique_ptr RefWorkloadFactory::CreateMean( const MeanQueueDescriptor& 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::CreateMinimum( diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk index c4a0c76bdc..ecd281208a 100644 --- a/src/backends/reference/backend.mk +++ b/src/backends/reference/backend.mk @@ -45,8 +45,7 @@ BACKEND_SOURCES := \ workloads/RefGatherWorkload.cpp \ workloads/RefL2NormalizationWorkload.cpp \ workloads/RefLstmWorkload.cpp \ - workloads/RefMeanFloat32Workload.cpp \ - workloads/RefMeanUint8Workload.cpp \ + workloads/RefMeanWorkload.cpp \ workloads/RefNormalizationWorkload.cpp \ workloads/RefPadWorkload.cpp \ workloads/RefPermuteWorkload.cpp \ diff --git a/src/backends/reference/test/RefLayerSupportTests.cpp b/src/backends/reference/test/RefLayerSupportTests.cpp index 2c7e17da43..0d99b3e66f 100644 --- a/src/backends/reference/test/RefLayerSupportTests.cpp +++ b/src/backends/reference/test/RefLayerSupportTests.cpp @@ -14,6 +14,7 @@ #include #include +#include #include @@ -130,4 +131,28 @@ BOOST_AUTO_TEST_CASE(IsConvertFp32ToFp16SupportedFp32OutputReference) BOOST_CHECK_EQUAL(reasonIfUnsupported, "Layer is not supported with float32 data type output"); } +BOOST_AUTO_TEST_CASE(IsLayerSupportedMeanDimensionsReference) +{ + std::string reasonIfUnsupported; + + bool result = IsMeanLayerSupportedTests(reasonIfUnsupported); + + BOOST_CHECK(result); +} + +BOOST_AUTO_TEST_CASE(IsLayerNotSupportedMeanDimensionsReference) +{ + std::string reasonIfUnsupported; + + bool result = IsMeanLayerNotSupportedTests(reasonIfUnsupported); + + BOOST_CHECK(!result); + + boost::algorithm::trim(reasonIfUnsupported); + BOOST_CHECK_EQUAL(reasonIfUnsupported, + "Reference Mean: Expected 4 dimensions but got 2 dimensions instead, for the 'output' tensor."); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp index 7ff6d1b269..c2cda8ec6b 100644 --- a/src/backends/reference/test/RefLayerTests.cpp +++ b/src/backends/reference/test/RefLayerTests.cpp @@ -607,19 +607,21 @@ ARMNN_AUTO_TEST_CASE(SimpleConvertFp16ToFp32, SimpleConvertFp16ToFp32Test) ARMNN_AUTO_TEST_CASE(SimpleConvertFp32ToFp16, SimpleConvertFp32ToFp16Test) // Mean -ARMNN_AUTO_TEST_CASE(MeanUint8Simple, MeanUint8SimpleTest) -ARMNN_AUTO_TEST_CASE(MeanUint8SimpleAxis, MeanUint8SimpleAxisTest) -ARMNN_AUTO_TEST_CASE(MeanUint8KeepDims, MeanUint8KeepDimsTest) -ARMNN_AUTO_TEST_CASE(MeanUint8MultipleDims, MeanUint8MultipleDimsTest) -ARMNN_AUTO_TEST_CASE(MeanVtsUint8, MeanVtsUint8Test) - -ARMNN_AUTO_TEST_CASE(MeanFloatSimple, MeanFloatSimpleTest) -ARMNN_AUTO_TEST_CASE(MeanFloatSimpleAxis, MeanFloatSimpleAxisTest) -ARMNN_AUTO_TEST_CASE(MeanFloatKeepDims, MeanFloatKeepDimsTest) -ARMNN_AUTO_TEST_CASE(MeanFloatMultipleDims, MeanFloatMultipleDimsTest) -ARMNN_AUTO_TEST_CASE(MeanVtsFloat1, MeanVtsFloat1Test) -ARMNN_AUTO_TEST_CASE(MeanVtsFloat2, MeanVtsFloat2Test) -ARMNN_AUTO_TEST_CASE(MeanVtsFloat3, MeanVtsFloat3Test) +ARMNN_AUTO_TEST_CASE(MeanSimpleFloat32, MeanSimpleTest) +ARMNN_AUTO_TEST_CASE(MeanSimpleAxisFloat32, MeanSimpleAxisTest) +ARMNN_AUTO_TEST_CASE(MeanKeepDimsFloat32, MeanKeepDimsTest) +ARMNN_AUTO_TEST_CASE(MeanMultipleDimsFloat32, MeanMultipleDimsTest) +ARMNN_AUTO_TEST_CASE(MeanVts1Float32, MeanVts1Test) +ARMNN_AUTO_TEST_CASE(MeanVts2Float32, MeanVts2Test) +ARMNN_AUTO_TEST_CASE(MeanVts3Float32, MeanVts3Test) + +ARMNN_AUTO_TEST_CASE(MeanSimpleQuantisedAsymm8, MeanSimpleTest) +ARMNN_AUTO_TEST_CASE(MeanSimpleAxisQuantisedAsymm8, MeanSimpleAxisTest) +ARMNN_AUTO_TEST_CASE(MeanKeepDimsQuantisedAsymm8, MeanKeepDimsTest) +ARMNN_AUTO_TEST_CASE(MeanMultipleDimsQuantisedAsymm8, MeanMultipleDimsTest) +ARMNN_AUTO_TEST_CASE(MeanVts1QuantisedAsymm8, MeanVts1Test) +ARMNN_AUTO_TEST_CASE(MeanVts2QuantisedAsymm8, MeanVts2Test) +ARMNN_AUTO_TEST_CASE(MeanVts3QuantisedAsymm8, MeanVts3Test) ARMNN_AUTO_TEST_CASE(AdditionAfterMaxPool, AdditionAfterMaxPoolTest) diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt index ebd33901d3..1ab38ccbcb 100644 --- a/src/backends/reference/workloads/CMakeLists.txt +++ b/src/backends/reference/workloads/CMakeLists.txt @@ -119,10 +119,8 @@ list(APPEND armnnRefBackendWorkloads_sources TensorBufferArrayView.hpp Mean.cpp Mean.hpp - RefMeanFloat32Workload.cpp - RefMeanFloat32Workload.hpp - RefMeanUint8Workload.cpp - RefMeanUint8Workload.hpp + RefMeanWorkload.cpp + RefMeanWorkload.hpp ) add_library(armnnRefBackendWorkloads OBJECT ${armnnRefBackendWorkloads_sources}) diff --git a/src/backends/reference/workloads/Mean.cpp b/src/backends/reference/workloads/Mean.cpp index 530aade611..3ac3af96a4 100644 --- a/src/backends/reference/workloads/Mean.cpp +++ b/src/backends/reference/workloads/Mean.cpp @@ -36,10 +36,13 @@ bool NextIndex(const unsigned int numDims, const armnn::TensorShape& dims, std:: return (carry == 0); } -std::size_t ReducedOutputOffset(const unsigned int numDims, const armnn::TensorShape& dims, - std::vector& index, const unsigned int numAxis, - const std::vector& axis) { - std::size_t offset = 0; +unsigned int ReducedOutputOffset(const unsigned int numDims, + const armnn::TensorShape& dims, + std::vector& index, + const unsigned int numAxis, + const std::vector& axis) +{ + unsigned int offset = 0; for (unsigned int idx = 0; idx < numDims; ++idx) { bool isAxis = false; @@ -56,7 +59,7 @@ std::size_t ReducedOutputOffset(const unsigned int numDims, const armnn::TensorS } if (!isAxis) { - offset = offset * boost::numeric_cast(dims[idx]) + boost::numeric_cast(index[idx]); + offset = offset * dims[idx] + index[idx]; } } return offset; @@ -68,8 +71,9 @@ namespace armnn void Mean(const armnn::TensorInfo& inputInfo, const armnn::TensorInfo& outputInfo, const std::vector& axis, - const float* inputData, - float* outputData) { + Decoder& input, + Encoder& output) +{ unsigned int inputNumDims = inputInfo.GetNumDimensions(); unsigned int outputNumDims = outputInfo.GetNumDimensions(); @@ -78,16 +82,17 @@ void Mean(const armnn::TensorInfo& inputInfo, armnn::TensorShape inputDims = inputInfo.GetShape(); // Initialise output data. - size_t numOutputs = 1; + unsigned int numOutputs = 1; for (unsigned int idx = 0; idx < outputNumDims; ++idx) { - numOutputs *= boost::numeric_cast(outputDims[idx]); + numOutputs *= outputDims[idx]; } std::vector tempSum(numOutputs); - for (size_t idx = 0; idx < numOutputs; ++idx) + for (unsigned int idx = 0; idx < numOutputs; ++idx) { - outputData[idx] = 0.0f; + output[idx]; + output.Set(0.0f); tempSum[idx] = 0.0f; } @@ -106,30 +111,32 @@ void Mean(const armnn::TensorInfo& inputInfo, resolvedAxis.push_back(idx); } } - unsigned int numResolvedAxis = boost::numeric_cast(resolvedAxis.size()); + auto numResolvedAxis = boost::numeric_cast(resolvedAxis.size()); // Iterates through input_data and sum up the reduced axis. for (bool hasNext = true; hasNext; hasNext = NextIndex(inputNumDims, inputDims, tempIndex)) { - size_t inputOffset = ReducedOutputOffset(inputNumDims, inputDims, tempIndex, 0, {}); - size_t outputOffset = ReducedOutputOffset(inputNumDims, inputDims, tempIndex, - numResolvedAxis, resolvedAxis); - tempSum[outputOffset] += inputData[inputOffset]; + unsigned int inputOffset = ReducedOutputOffset(inputNumDims, inputDims, tempIndex, 0, {}); + unsigned int outputOffset = ReducedOutputOffset(inputNumDims, inputDims, tempIndex, + numResolvedAxis, resolvedAxis); + input[inputOffset]; + tempSum[outputOffset] += input.Get(); } // Takes average by num of elements added to get mean. size_t numElementsInAxis = 1; for (unsigned int idx = 0; idx < numResolvedAxis; ++idx) { - size_t current = boost::numeric_cast(inputDims[resolvedAxis[idx]]); + unsigned int current = inputDims[resolvedAxis[idx]]; BOOST_ASSERT(boost::numeric_cast(current) < (std::numeric_limits::max() / boost::numeric_cast(numElementsInAxis))); numElementsInAxis *= current; } if (numElementsInAxis > 0) { - for (size_t idx = 0; idx < numOutputs; ++idx) + for (unsigned int idx = 0; idx < numOutputs; ++idx) { - outputData[idx] = tempSum[idx] / boost::numeric_cast(numElementsInAxis); + output[idx]; + output.Set(tempSum[idx] / boost::numeric_cast(numElementsInAxis)); } } } diff --git a/src/backends/reference/workloads/Mean.hpp b/src/backends/reference/workloads/Mean.hpp index 38c2e39653..dfb0302bf9 100644 --- a/src/backends/reference/workloads/Mean.hpp +++ b/src/backends/reference/workloads/Mean.hpp @@ -7,6 +7,7 @@ #include "armnn/DescriptorsFwd.hpp" #include "armnn/Tensor.hpp" +#include "BaseIterator.hpp" #include @@ -15,7 +16,7 @@ namespace armnn void Mean(const TensorInfo& inputInfo, const TensorInfo& outputInfo, const std::vector& axis, - const float* inputData, - float* outputData); + Decoder& input, + Encoder& output); } //namespace armnn diff --git a/src/backends/reference/workloads/RefMeanFloat32Workload.cpp b/src/backends/reference/workloads/RefMeanFloat32Workload.cpp deleted file mode 100644 index a23906b8aa..0000000000 --- a/src/backends/reference/workloads/RefMeanFloat32Workload.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#include "RefMeanFloat32Workload.hpp" - -#include "Mean.hpp" -#include "RefWorkloadUtils.hpp" - -#include "Profiling.hpp" -#include "vector" - -namespace armnn -{ - -RefMeanFloat32Workload::RefMeanFloat32Workload(const MeanQueueDescriptor& descriptor, const WorkloadInfo& info) - :Float32Workload(descriptor, info) {} - - -void RefMeanFloat32Workload::Execute() const -{ - ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefMeanFloat32Workload_Execute"); - - const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]); - const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]); - const float* inputData = GetInputTensorDataFloat(0, m_Data); - float* outputData = GetOutputTensorDataFloat(0, m_Data); - - Mean(inputInfo, outputInfo, m_Data.m_Parameters.m_Axis, inputData, outputData); -} - -} //namespace armnn - - diff --git a/src/backends/reference/workloads/RefMeanFloat32Workload.hpp b/src/backends/reference/workloads/RefMeanFloat32Workload.hpp deleted file mode 100644 index 153ebe161a..0000000000 --- a/src/backends/reference/workloads/RefMeanFloat32Workload.hpp +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#pragma once - -#include "backendsCommon/Workload.hpp" -#include "backendsCommon/WorkloadData.hpp" - -namespace armnn -{ - - -class RefMeanFloat32Workload : public Float32Workload -{ -public: - explicit RefMeanFloat32Workload (const MeanQueueDescriptor& descriptor, const WorkloadInfo& info); - virtual void Execute() const override; -}; - -}//namespace armnn diff --git a/src/backends/reference/workloads/RefMeanUint8Workload.cpp b/src/backends/reference/workloads/RefMeanUint8Workload.cpp deleted file mode 100644 index 4ebffcfd70..0000000000 --- a/src/backends/reference/workloads/RefMeanUint8Workload.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#include "RefMeanUint8Workload.hpp" - -#include "Mean.hpp" -#include "RefWorkloadUtils.hpp" - -#include "Profiling.hpp" - -#include - -namespace armnn -{ - -RefMeanUint8Workload::RefMeanUint8Workload(const MeanQueueDescriptor& descriptor, const WorkloadInfo& info) - :Uint8Workload(descriptor, info) {} - - -void RefMeanUint8Workload::Execute() const -{ - ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefMeanUint8Workload_Execute"); - - const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]); - const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]); - - auto dequant = Dequantize(GetInputTensorDataU8(0, m_Data), inputInfo); - - std::vector results(outputInfo.GetNumElements()); - - Mean(inputInfo, outputInfo, m_Data.m_Parameters.m_Axis, dequant.data(), results.data()); - - Quantize(GetOutputTensorDataU8(0, m_Data), results.data(), outputInfo); -} - -} //namespace armnn - diff --git a/src/backends/reference/workloads/RefMeanUint8Workload.hpp b/src/backends/reference/workloads/RefMeanUint8Workload.hpp deleted file mode 100644 index f53b8a434a..0000000000 --- a/src/backends/reference/workloads/RefMeanUint8Workload.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#pragma once - -#include "backendsCommon/Workload.hpp" -#include "backendsCommon/WorkloadData.hpp" - -namespace armnn -{ - -class RefMeanUint8Workload : public Uint8Workload -{ -public: - explicit RefMeanUint8Workload (const MeanQueueDescriptor& descriptor, const WorkloadInfo& info); - virtual void Execute() const override; -}; - -} //namespace armnn diff --git a/src/backends/reference/workloads/RefMeanWorkload.cpp b/src/backends/reference/workloads/RefMeanWorkload.cpp new file mode 100644 index 0000000000..375ab395be --- /dev/null +++ b/src/backends/reference/workloads/RefMeanWorkload.cpp @@ -0,0 +1,34 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "RefMeanWorkload.hpp" + +#include "Mean.hpp" +#include "RefWorkloadUtils.hpp" + +#include "Profiling.hpp" + +#include + +namespace armnn +{ + +RefMeanWorkload::RefMeanWorkload(const MeanQueueDescriptor& descriptor, const WorkloadInfo& info) + :BaseWorkload(descriptor, info) {} + +void RefMeanWorkload::Execute() const +{ + ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefMeanWorkload_Execute"); + + const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]); + const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]); + + auto inputDecoder = MakeDecoder(inputInfo, m_Data.m_Inputs[0]->Map()); + auto outputEncoder = MakeEncoder(outputInfo, m_Data.m_Outputs[0]->Map()); + + Mean(inputInfo, outputInfo, m_Data.m_Parameters.m_Axis, *inputDecoder, *outputEncoder); +} + +} //namespace armnn diff --git a/src/backends/reference/workloads/RefMeanWorkload.hpp b/src/backends/reference/workloads/RefMeanWorkload.hpp new file mode 100644 index 0000000000..eb4b407dbd --- /dev/null +++ b/src/backends/reference/workloads/RefMeanWorkload.hpp @@ -0,0 +1,24 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "backendsCommon/Workload.hpp" +#include "backendsCommon/WorkloadData.hpp" + +#include "Decoders.hpp" +#include "Encoders.hpp" + +namespace armnn +{ + +class RefMeanWorkload : public BaseWorkload +{ +public: + explicit RefMeanWorkload (const MeanQueueDescriptor& descriptor, const WorkloadInfo& info); + virtual void Execute() const override; +}; + +} //namespace armnn diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp index 7cfced484e..b14129146a 100644 --- a/src/backends/reference/workloads/RefWorkloads.hpp +++ b/src/backends/reference/workloads/RefWorkloads.hpp @@ -42,8 +42,7 @@ #include "RefLstmWorkload.hpp" #include "RefConvertFp16ToFp32Workload.hpp" #include "RefConvertFp32ToFp16Workload.hpp" -#include "RefMeanUint8Workload.hpp" -#include "RefMeanFloat32Workload.hpp" +#include "RefMeanWorkload.hpp" #include "RefPadWorkload.hpp" #include "RefBatchToSpaceNdUint8Workload.hpp" #include "RefBatchToSpaceNdFloat32Workload.hpp" -- cgit v1.2.1