From 1e4c31dafb1c8984a126fa1d211ed8f9eedaf7cc Mon Sep 17 00:00:00 2001 From: narpra01 Date: Fri, 28 Sep 2018 11:07:51 +0100 Subject: IVGCVSW-1812 Adding Ref implementation and tests of MeanWorkloads Change-Id: I6fb15c407024e3b91d5abf4513f8090be5821760 --- src/armnn/layers/MeanLayer.cpp | 2 +- src/armnn/test/NetworkTests.cpp | 33 ++++ src/backends/reference/RefLayerSupport.cpp | 7 +- src/backends/reference/RefWorkloadFactory.cpp | 2 +- src/backends/reference/backend.mk | 3 + src/backends/reference/workloads/CMakeLists.txt | 6 + src/backends/reference/workloads/Mean.cpp | 136 +++++++++++++++ src/backends/reference/workloads/Mean.hpp | 21 +++ .../reference/workloads/RefMeanFloat32Workload.cpp | 35 ++++ .../reference/workloads/RefMeanFloat32Workload.hpp | 22 +++ .../reference/workloads/RefMeanUint8Workload.cpp | 39 +++++ .../reference/workloads/RefMeanUint8Workload.hpp | 21 +++ src/backends/reference/workloads/RefWorkloads.hpp | 2 + src/backends/test/LayerTests.cpp | 183 ++++++++++++++++++++- src/backends/test/LayerTests.hpp | 13 ++ src/backends/test/Reference.cpp | 14 ++ 16 files changed, 535 insertions(+), 4 deletions(-) create mode 100644 src/backends/reference/workloads/Mean.cpp create mode 100644 src/backends/reference/workloads/Mean.hpp create mode 100644 src/backends/reference/workloads/RefMeanFloat32Workload.cpp create mode 100644 src/backends/reference/workloads/RefMeanFloat32Workload.hpp create mode 100644 src/backends/reference/workloads/RefMeanUint8Workload.cpp create mode 100644 src/backends/reference/workloads/RefMeanUint8Workload.hpp diff --git a/src/armnn/layers/MeanLayer.cpp b/src/armnn/layers/MeanLayer.cpp index 6bbb0943b0..01f1133c5c 100644 --- a/src/armnn/layers/MeanLayer.cpp +++ b/src/armnn/layers/MeanLayer.cpp @@ -60,7 +60,7 @@ void MeanLayer::ValidateTensorShapesFromInputs() { outputRank = 1; } - else if (m_Param.m_Axis.size() <= input.GetNumDimensions()) + else if (m_Param.m_Axis.size() >= input.GetNumDimensions()) { throw LayerValidationException("MeanLayer: Dimensions to reduce can not be bigger than input dimensions"); } diff --git a/src/armnn/test/NetworkTests.cpp b/src/armnn/test/NetworkTests.cpp index 11c26da8b4..2f36f4da09 100644 --- a/src/armnn/test/NetworkTests.cpp +++ b/src/armnn/test/NetworkTests.cpp @@ -845,6 +845,39 @@ BOOST_AUTO_TEST_CASE(OptimizeValidateWorkloadsCpuRefPermuteLayer) } } +BOOST_AUTO_TEST_CASE(OptimizeValidateWorkloadsCpuRefMeanLayer) +{ + // Create runtime in which test will run + armnn::IRuntime::CreationOptions options; + armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options)); + + std::vector backends = {armnn::Compute::CpuRef}; + + // build up the structure of the network + armnn::INetworkPtr net(armnn::INetwork::Create()); + + armnn::IConnectableLayer* input = net->AddInputLayer(0); + + armnn::MeanDescriptor descriptor({ 0, 1 }, false); + armnn::IConnectableLayer* meanLayer = net->AddMeanLayer(descriptor); + + armnn::IConnectableLayer* output = net->AddOutputLayer(0); + + input->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0)); + meanLayer->GetOutputSlot(0).Connect(output->GetInputSlot(0)); + + input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 4, 3, 2 }, armnn::DataType::Float32)); + meanLayer->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 2 }, armnn::DataType::Float32)); + + // optimize the network + armnn::IOptimizedNetworkPtr optNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec()); + + for (auto&& layer : static_cast(optNet.get())->GetGraph()) + { + BOOST_CHECK_EQUAL(armnn::Compute::CpuRef, layer->GetComputeDevice()); + } +} + BOOST_AUTO_TEST_CASE(FP16TurboModeTestOnCpuRef) { // Test to check when FP16 Turbo mode set diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp index d56cdebeda..12a2817774 100644 --- a/src/backends/reference/RefLayerSupport.cpp +++ b/src/backends/reference/RefLayerSupport.cpp @@ -392,7 +392,12 @@ bool IsMeanSupportedRef(const TensorInfo& input, const MeanDescriptor& descriptor, std::string* reasonIfUnsupported) { - return false; + ignore_unused(output); + ignore_unused(descriptor); + return IsSupportedForDataTypeRef(reasonIfUnsupported, + input.GetDataType(), + &TrueFunc<>, + &TrueFunc<>); } } diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp index 5cefd1b6e1..582c691a18 100644 --- a/src/backends/reference/RefWorkloadFactory.cpp +++ b/src/backends/reference/RefWorkloadFactory.cpp @@ -242,7 +242,7 @@ std::unique_ptr RefWorkloadFactory::CreateSubtraction( std::unique_ptr RefWorkloadFactory::CreateMean( const MeanQueueDescriptor& descriptor, const WorkloadInfo& info) const { - return MakeWorkload(descriptor, info); + return MakeWorkload(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreatePad(const PadQueueDescriptor& descriptor, diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk index 23dab119d0..e5345c07d5 100644 --- a/src/backends/reference/backend.mk +++ b/src/backends/reference/backend.mk @@ -15,6 +15,7 @@ BACKEND_SOURCES := \ workloads/Broadcast.cpp \ workloads/ConvImpl.cpp \ workloads/FullyConnected.cpp \ + workloads/Mean.cpp \ workloads/Pooling2d.cpp \ workloads/RefActivationFloat32Workload.cpp \ workloads/RefActivationUint8Workload.cpp \ @@ -36,6 +37,8 @@ BACKEND_SOURCES := \ workloads/RefFullyConnectedUint8Workload.cpp \ workloads/RefL2NormalizationFloat32Workload.cpp \ workloads/RefLstmFloat32Workload.cpp \ + workloads/RefMeanFloat32Workload.cpp \ + workloads/RefMeanUint8Workload.cpp \ workloads/RefMergerFloat32Workload.cpp \ workloads/RefMergerUint8Workload.cpp \ workloads/RefNormalizationFloat32Workload.cpp \ diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt index 7343b70daf..5a756e4596 100644 --- a/src/backends/reference/workloads/CMakeLists.txt +++ b/src/backends/reference/workloads/CMakeLists.txt @@ -94,6 +94,12 @@ list(APPEND armnnRefBackendWorkloads_sources Softmax.hpp Splitter.hpp TensorBufferArrayView.hpp + Mean.cpp + Mean.hpp + RefMeanFloat32Workload.cpp + RefMeanFloat32Workload.hpp + RefMeanUint8Workload.cpp + RefMeanUint8Workload.hpp ) add_library(armnnRefBackendWorkloads STATIC ${armnnRefBackendWorkloads_sources}) diff --git a/src/backends/reference/workloads/Mean.cpp b/src/backends/reference/workloads/Mean.cpp new file mode 100644 index 0000000000..0db67a0eed --- /dev/null +++ b/src/backends/reference/workloads/Mean.cpp @@ -0,0 +1,136 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "Mean.hpp" +#include "backends/WorkloadData.hpp" + +#include + +#include +#include +#include +#include + +namespace armnn +{ +bool NextIndex(const unsigned int numDims, const armnn::TensorShape& dims, std::vector& current) +{ + unsigned int carry = 1; + + for (unsigned int idx = numDims; idx-- > 0; ) + { + unsigned int current_val = current[idx] + carry; + if (dims[idx] == current_val) + { + current[idx] = 0; + } + else + { + current[idx] = current_val; + carry = 0; + break; + } + } + 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; + for (unsigned int idx = 0; idx < numDims; ++idx) + { + bool isAxis = false; + if (!axis.empty()) + { + for (unsigned int axisIdx = 0; axisIdx < numAxis; ++axisIdx) + { + if (idx == axis[axisIdx]) + { + isAxis = true; + break; + } + } + } + if (!isAxis) + { + offset = offset * boost::numeric_cast(dims[idx]) + boost::numeric_cast(index[idx]); + } + } + return offset; +} +} // namespace + +namespace armnn +{ +void Mean(const armnn::TensorInfo& inputInfo, + const armnn::TensorInfo& outputInfo, + const std::vector& axis, + const float* inputData, + float* outputData) { + + unsigned int inputNumDims = inputInfo.GetNumDimensions(); + unsigned int outputNumDims = outputInfo.GetNumDimensions(); + + armnn::TensorShape outputDims = outputInfo.GetShape(); + armnn::TensorShape inputDims = inputInfo.GetShape(); + + // Initialise output data. + size_t numOutputs = 1; + for (unsigned int idx = 0; idx < outputNumDims; ++idx) + { + numOutputs *= boost::numeric_cast(outputDims[idx]); + } + + std::vector tempSum(numOutputs); + for (size_t idx = 0; idx < numOutputs; ++idx) + { + outputData[idx] = 0.0f; + tempSum[idx] = 0.0f; + } + + // Initialise temp index. + std::vector tempIndex(inputNumDims); + for (unsigned int idx = 0; idx < inputNumDims; ++idx) + { + tempIndex[idx] = 0; + } + + std::vector resolvedAxis = axis; + if (resolvedAxis.empty()) + { + for (unsigned int idx = 0; idx < inputNumDims; ++idx) + { + resolvedAxis.push_back(idx); + } + } + unsigned int 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]; + } + + // 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]]); + 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) + { + outputData[idx] = tempSum[idx] / boost::numeric_cast(numElementsInAxis); + } + } +} +} //namespace armnn diff --git a/src/backends/reference/workloads/Mean.hpp b/src/backends/reference/workloads/Mean.hpp new file mode 100644 index 0000000000..38c2e39653 --- /dev/null +++ b/src/backends/reference/workloads/Mean.hpp @@ -0,0 +1,21 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "armnn/DescriptorsFwd.hpp" +#include "armnn/Tensor.hpp" + +#include + +namespace armnn +{ +void Mean(const TensorInfo& inputInfo, + const TensorInfo& outputInfo, + const std::vector& axis, + const float* inputData, + float* outputData); +} //namespace armnn + diff --git a/src/backends/reference/workloads/RefMeanFloat32Workload.cpp b/src/backends/reference/workloads/RefMeanFloat32Workload.cpp new file mode 100644 index 0000000000..a23906b8aa --- /dev/null +++ b/src/backends/reference/workloads/RefMeanFloat32Workload.cpp @@ -0,0 +1,35 @@ +// +// 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 new file mode 100644 index 0000000000..a4c559f0c6 --- /dev/null +++ b/src/backends/reference/workloads/RefMeanFloat32Workload.hpp @@ -0,0 +1,22 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "backends/Workload.hpp" +#include "backends/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 new file mode 100644 index 0000000000..4ebffcfd70 --- /dev/null +++ b/src/backends/reference/workloads/RefMeanUint8Workload.cpp @@ -0,0 +1,39 @@ +// +// 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 new file mode 100644 index 0000000000..21cf72b38f --- /dev/null +++ b/src/backends/reference/workloads/RefMeanUint8Workload.hpp @@ -0,0 +1,21 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "backends/Workload.hpp" +#include "backends/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/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp index e5c6e1e9d5..7e89cabd66 100644 --- a/src/backends/reference/workloads/RefWorkloads.hpp +++ b/src/backends/reference/workloads/RefWorkloads.hpp @@ -51,3 +51,5 @@ #include "RefLstmFloat32Workload.hpp" #include "RefConvertFp16ToFp32Workload.hpp" #include "RefConvertFp32ToFp16Workload.hpp" +#include "RefMeanUint8Workload.hpp" +#include "RefMeanFloat32Workload.hpp" \ No newline at end of file diff --git a/src/backends/test/LayerTests.cpp b/src/backends/test/LayerTests.cpp index 8f06690018..4f6cb93670 100644 --- a/src/backends/test/LayerTests.cpp +++ b/src/backends/test/LayerTests.cpp @@ -4747,4 +4747,185 @@ LayerTestResult PermuteFloat32ValueSet2Test(armnn::IWorkloadFactory& w LayerTestResult PermuteFloat32ValueSet3Test(armnn::IWorkloadFactory& workloadFactory) { return PermuteFloat32ValueSet3TestCommon(workloadFactory); -}; \ No newline at end of file +}; + +namespace +{ +template +LayerTestResult MeanTestHelper(armnn::IWorkloadFactory& workloadFactory, + 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()); + + workloadFactory.Finalize(); + workload->Execute(); + + CopyDataFromITensorHandle(result.output.origin(), outputHandle.get()); + + return result; +} +} // anonymous namespace + +LayerTestResult MeanUint8SimpleTest(armnn::IWorkloadFactory& workloadFactory) +{ + 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, inputShape, input, {}, false, outputShape, output); +} + +LayerTestResult MeanUint8SimpleAxisTest(armnn::IWorkloadFactory& workloadFactory) +{ + 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, inputShape, input, {2}, false, outputShape, output); +} + +LayerTestResult MeanUint8KeepDimsTest(armnn::IWorkloadFactory& workloadFactory) +{ + 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, inputShape, input, {2}, true, outputShape, output); +} + +LayerTestResult MeanUint8MultipleDimsTest(armnn::IWorkloadFactory& workloadFactory) +{ + 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, inputShape, input, {0, 3}, true, outputShape, output); +} + +LayerTestResult MeanVtsUint8Test(armnn::IWorkloadFactory& workloadFactory) +{ + 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, inputShape, input, {0, 1}, false, outputShape, + output, 0.8f, 5); +} + +LayerTestResult MeanFloatSimpleTest(armnn::IWorkloadFactory& workloadFactory) +{ + 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, inputShape, input, {}, false, outputShape, output); +} + +LayerTestResult MeanFloatSimpleAxisTest(armnn::IWorkloadFactory& workloadFactory) +{ + const unsigned int inputShape[] = { 2, 3, 1, 2 }; + const unsigned int outputShape[] = { 3, 1, 2 }; + + std::vector input({ 1., 2., 3., 4., 5., 6., 1., 2., 3., 4., 5., 6.}); + std::vector output({ 1., 2., 3., 4., 5., 6. }); + + return MeanTestHelper(workloadFactory, inputShape, input, {0}, false, outputShape, output); +} + +LayerTestResult MeanFloatKeepDimsTest(armnn::IWorkloadFactory& workloadFactory) +{ + 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, inputShape, input, {2}, true, outputShape, output); +} + +LayerTestResult MeanFloatMultipleDimsTest(armnn::IWorkloadFactory& workloadFactory) +{ + 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.5, 3.5, 5.5 }); + + return MeanTestHelper(workloadFactory, inputShape, input, {0, 3}, true, outputShape, output); +} + +LayerTestResult MeanVtsFloat1Test(armnn::IWorkloadFactory& workloadFactory) +{ + 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, inputShape, input, {0, 1}, false, outputShape, output); +} + +LayerTestResult MeanVtsFloat2Test(armnn::IWorkloadFactory& workloadFactory) +{ + 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, inputShape, input, {0, 2}, true, outputShape, output); +} diff --git a/src/backends/test/LayerTests.hpp b/src/backends/test/LayerTests.hpp index 365a1f53d4..9dc3afa150 100644 --- a/src/backends/test/LayerTests.hpp +++ b/src/backends/test/LayerTests.hpp @@ -343,3 +343,16 @@ LstmLayerFloat32NoCifgWithPeepholeWithProjectionTest(armnn::IWorkloadFactory& wo LayerTestResult SimpleConvertFp16ToFp32Test(armnn::IWorkloadFactory& workloadFactory); LayerTestResult SimpleConvertFp32ToFp16Test(armnn::IWorkloadFactory& workloadFactory); + + +LayerTestResult MeanUint8SimpleTest(armnn::IWorkloadFactory& workloadFactory); +LayerTestResult MeanUint8SimpleAxisTest(armnn::IWorkloadFactory& workloadFactory); +LayerTestResult MeanUint8KeepDimsTest(armnn::IWorkloadFactory& workloadFactory); +LayerTestResult MeanUint8MultipleDimsTest(armnn::IWorkloadFactory& workloadFactory); +LayerTestResult MeanVtsUint8Test(armnn::IWorkloadFactory& workloadFactory); +LayerTestResult MeanFloatSimpleTest(armnn::IWorkloadFactory& workloadFactory); +LayerTestResult MeanFloatSimpleAxisTest(armnn::IWorkloadFactory& workloadFactory); +LayerTestResult MeanFloatKeepDimsTest(armnn::IWorkloadFactory& workloadFactory); +LayerTestResult MeanFloatMultipleDimsTest(armnn::IWorkloadFactory& workloadFactory); +LayerTestResult MeanVtsFloat1Test(armnn::IWorkloadFactory& workloadFactory); +LayerTestResult MeanVtsFloat2Test(armnn::IWorkloadFactory& workloadFactory); diff --git a/src/backends/test/Reference.cpp b/src/backends/test/Reference.cpp index 97a209d757..30a8f8e1a5 100644 --- a/src/backends/test/Reference.cpp +++ b/src/backends/test/Reference.cpp @@ -250,4 +250,18 @@ ARMNN_AUTO_TEST_CASE(SimpleConvertFp16ToFp32, SimpleConvertFp16ToFp32Test) // Convert from Float32 to Float16 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) + BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.1