From 2b4d88e34ac1f965417fd236fd4786f26bae2042 Mon Sep 17 00:00:00 2001 From: kevmay01 Date: Thu, 24 Jan 2019 14:05:09 +0000 Subject: IVGCVSW-2503 Refactor RefElementwiseWorkload around Equal and Greater * Remove Equal and Greater from RefElementwiseWorkload * Create RefComparisonWorkload and add Equal and Greater * Update ElementwiseFunction for different input/output types * Update TfParser to create Equal/Greater with Boolean output * Update relevant tests to check for Boolean comparison Change-Id: I299b7f2121769c960ac0c6139764a5f3c89c9c32 --- src/armnn/LayerSupportCommon.hpp | 6 +- src/armnn/test/TensorHelpers.hpp | 21 ++- src/armnn/test/UnitTests.hpp | 2 +- src/armnnTfParser/TfParser.cpp | 31 +++- src/armnnTfParser/TfParser.hpp | 6 + src/armnnTfParser/test/Equal.cpp | 32 ++-- src/armnnTfParser/test/Greater.cpp | 32 ++-- src/armnnUtils/ParserPrototxtFixture.hpp | 38 +++- src/backends/backendsCommon/MakeWorkloadHelper.hpp | 20 ++- src/backends/backendsCommon/Workload.hpp | 13 ++ src/backends/backendsCommon/WorkloadData.cpp | 10 ++ .../backendsCommon/test/ArithmeticTestImpl.hpp | 50 +++--- .../backendsCommon/test/EndToEndTestImpl.hpp | 12 +- src/backends/backendsCommon/test/LayerTests.cpp | 194 +++++++++++++-------- src/backends/backendsCommon/test/LayerTests.hpp | 14 +- .../backendsCommon/test/MergerTestImpl.hpp | 2 +- src/backends/cl/ClLayerSupport.cpp | 16 +- src/backends/cl/ClWorkloadFactory.cpp | 3 +- src/backends/neon/NeonLayerSupport.cpp | 16 +- src/backends/neon/NeonTensorHandle.hpp | 4 + src/backends/neon/NeonWorkloadFactory.cpp | 3 +- src/backends/reference/RefLayerSupport.cpp | 38 ++-- src/backends/reference/RefWorkloadFactory.cpp | 10 +- src/backends/reference/backend.mk | 1 + src/backends/reference/test/RefEndToEndTests.cpp | 48 +++-- src/backends/reference/workloads/CMakeLists.txt | 2 + .../reference/workloads/ElementwiseFunction.cpp | 32 ++-- .../reference/workloads/ElementwiseFunction.hpp | 8 +- .../reference/workloads/RefComparisonWorkload.cpp | 65 +++++++ .../reference/workloads/RefComparisonWorkload.hpp | 92 ++++++++++ .../reference/workloads/RefElementwiseWorkload.cpp | 20 +-- .../reference/workloads/RefElementwiseWorkload.hpp | 24 --- src/backends/reference/workloads/RefWorkloads.hpp | 1 + 33 files changed, 601 insertions(+), 265 deletions(-) create mode 100644 src/backends/reference/workloads/RefComparisonWorkload.cpp create mode 100644 src/backends/reference/workloads/RefComparisonWorkload.hpp diff --git a/src/armnn/LayerSupportCommon.hpp b/src/armnn/LayerSupportCommon.hpp index 109728cd81..70b5f182f4 100644 --- a/src/armnn/LayerSupportCommon.hpp +++ b/src/armnn/LayerSupportCommon.hpp @@ -12,13 +12,15 @@ namespace armnn { -template +template bool IsSupportedForDataTypeGeneric(Optional reasonIfUnsupported, DataType dataType, Float16Func float16FuncPtr, Float32Func float32FuncPtr, Uint8Func uint8FuncPtr, Int32Func int32FuncPtr, + BooleanFunc booleanFuncPtr, Params&&... params) { switch(dataType) @@ -31,6 +33,8 @@ bool IsSupportedForDataTypeGeneric(Optional reasonIfUnsupported, return uint8FuncPtr(reasonIfUnsupported, std::forward(params)...); case DataType::Signed32: return int32FuncPtr(reasonIfUnsupported, std::forward(params)...); + case DataType::Boolean: + return booleanFuncPtr(reasonIfUnsupported, std::forward(params)...); default: return false; } diff --git a/src/armnn/test/TensorHelpers.hpp b/src/armnn/test/TensorHelpers.hpp index 06818d3918..fcaa0772a0 100644 --- a/src/armnn/test/TensorHelpers.hpp +++ b/src/armnn/test/TensorHelpers.hpp @@ -67,11 +67,16 @@ bool SelectiveCompare(T a, T b) return SelectiveComparer()>::Compare(a, b); }; - +template +bool SelectiveCompareBoolean(T a, T b) +{ + return (((a == 0) && (b == 0)) || ((a != 0) && (b != 0))); +}; template boost::test_tools::predicate_result CompareTensors(const boost::multi_array& a, - const boost::multi_array& b) + const boost::multi_array& b, + bool compareBoolean = false) { // Checks they are same shape. for (unsigned int i=0; i TfParser::ProcessElementwise return {input0Slot, input1Slot}; } +ParsedTfOperationPtr TfParser::ProcessComparisonLayer( + IOutputSlot* input0Slot, + IOutputSlot* input1Slot, + IConnectableLayer* const layer, + const tensorflow::NodeDef& nodeDef) +{ + input0Slot->Connect(layer->GetInputSlot(0)); + input1Slot->Connect(layer->GetInputSlot(1)); + + TensorInfo outputInfo = input0Slot->GetTensorInfo(); + outputInfo.SetDataType(DataType::Boolean); + std::vector outputShape; + + const TensorShape& input0Shape = input0Slot->GetTensorInfo().GetShape(); + const TensorShape& input1Shape = input1Slot->GetTensorInfo().GetShape(); + + for (unsigned int i = 0; i < input0Shape.GetNumDimensions(); i++) + { + outputShape.push_back(std::max(input0Shape[i], input1Shape[i])); + } + + outputInfo.SetShape(TensorShape(input0Shape.GetNumDimensions(), outputShape.data())); + layer->GetOutputSlot(0).SetTensorInfo(outputInfo); + + return std::make_unique(this, nodeDef, layer); +} + ParsedTfOperationPtr TfParser::ProcessElementwiseLayer( IOutputSlot* input0Slot, IOutputSlot* input1Slot, @@ -1812,7 +1839,7 @@ ParsedTfOperationPtr TfParser::ParseGreater(const tensorflow::NodeDef& nodeDef, IConnectableLayer* const layer = m_Network->AddGreaterLayer(nodeDef.name().c_str()); - return ProcessElementwiseLayer(input0Slot, input1Slot, layer, nodeDef); + return ProcessComparisonLayer(input0Slot, input1Slot, layer, nodeDef); } ParsedTfOperationPtr TfParser::ParseEqual(const tensorflow::NodeDef& nodeDef, @@ -1824,7 +1851,7 @@ ParsedTfOperationPtr TfParser::ParseEqual(const tensorflow::NodeDef& nodeDef, IConnectableLayer* const layer = m_Network->AddEqualLayer(nodeDef.name().c_str()); - return ProcessElementwiseLayer(input0Slot, input1Slot, layer, nodeDef); + return ProcessComparisonLayer(input0Slot, input1Slot, layer, nodeDef); } ParsedTfOperationPtr TfParser::ParseMinimum(const tensorflow::NodeDef& nodeDef, diff --git a/src/armnnTfParser/TfParser.hpp b/src/armnnTfParser/TfParser.hpp index 9a7d7827c3..2b809419de 100644 --- a/src/armnnTfParser/TfParser.hpp +++ b/src/armnnTfParser/TfParser.hpp @@ -187,6 +187,12 @@ private: std::pair ProcessElementwiseInputSlots( const tensorflow::NodeDef& nodeDef, const std::string& layerName); + ParsedTfOperationPtr ProcessComparisonLayer( + armnn::IOutputSlot* input0Slot, + armnn::IOutputSlot* input1Slot, + armnn::IConnectableLayer* const layer, + const tensorflow::NodeDef& nodeDef); + ParsedTfOperationPtr ProcessElementwiseLayer( armnn::IOutputSlot* input0Slot, armnn::IOutputSlot* input1Slot, diff --git a/src/armnnTfParser/test/Equal.cpp b/src/armnnTfParser/test/Equal.cpp index 43a1c6abb5..2dce822b0f 100644 --- a/src/armnnTfParser/test/Equal.cpp +++ b/src/armnnTfParser/test/Equal.cpp @@ -91,9 +91,9 @@ struct EqualTwoByTwo : public EqualFixtureAutoSetup BOOST_FIXTURE_TEST_CASE(ParseEqualTwoByTwo, EqualTwoByTwo) { - RunTest<2>({ { "input0", { 1.0f, 2.0f, 3.0f, 2.0f } }, - { "input1", { 1.0f, 5.0f, 2.0f, 2.0f } } }, - { { "output", { 1.0f, 0.0f, 0.0f, 1.0f } } }); + RunComparisonTest<2>({ { "input0", { 1.0f, 2.0f, 3.0f, 2.0f } }, + { "input1", { 1.0f, 5.0f, 2.0f, 2.0f } } }, + { { "output", { 1, 0, 0, 1 } } }); } struct EqualBroadcast1DAnd4D : public EqualFixtureAutoSetup @@ -103,9 +103,9 @@ struct EqualBroadcast1DAnd4D : public EqualFixtureAutoSetup BOOST_FIXTURE_TEST_CASE(ParseEqualBroadcast1DToTwoByTwo, EqualBroadcast1DAnd4D) { - RunTest<4>({ { "input0", { 2.0f } }, - { "input1", { 1.0f, 2.0f, 3.0f, 2.0f } } }, - { { "output", { 0.0f, 1.0f, 0.0f, 1.0f } } }); + RunComparisonTest<4>({ { "input0", { 2.0f } }, + { "input1", { 1.0f, 2.0f, 3.0f, 2.0f } } }, + { { "output", { 0, 1, 0, 1 } } }); } struct EqualBroadcast4DAnd1D : public EqualFixtureAutoSetup @@ -115,9 +115,9 @@ struct EqualBroadcast4DAnd1D : public EqualFixtureAutoSetup BOOST_FIXTURE_TEST_CASE(ParseEqualBroadcast4DAnd1D, EqualBroadcast4DAnd1D) { - RunTest<4>({ { "input0", { 1.0f, 2.0f, 3.0f, 2.0f } }, - { "input1", { 3.0f } } }, - { { "output", { 0.0f, 0.0f, 1.0f, 0.0f } } }); + RunComparisonTest<4>({ { "input0", { 1.0f, 2.0f, 3.0f, 2.0f } }, + { "input1", { 3.0f } } }, + { { "output", { 0, 0, 1, 0 } } }); } struct EqualMultiDimBroadcast : public EqualFixtureAutoSetup @@ -127,13 +127,13 @@ struct EqualMultiDimBroadcast : public EqualFixtureAutoSetup BOOST_FIXTURE_TEST_CASE(ParseEqualMultiDimBroadcast, EqualMultiDimBroadcast) { - RunTest<4>({ { "input0", { 1.0f, 2.0f } }, - { "input1", { 1.0f, 2.0f, 3.0f, - 3.0f, 2.0f, 2.0f } } }, - { { "output", { 1.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 1.0f } } }); + RunComparisonTest<4>({ { "input0", { 1.0f, 2.0f } }, + { "input1", { 1.0f, 2.0f, 3.0f, + 3.0f, 2.0f, 2.0f } } }, + { { "output", { 1, 0, 0, + 0, 1, 0, + 0, 0, 0, + 0, 1, 1 } } }); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/armnnTfParser/test/Greater.cpp b/src/armnnTfParser/test/Greater.cpp index f11c199599..d1e793987b 100644 --- a/src/armnnTfParser/test/Greater.cpp +++ b/src/armnnTfParser/test/Greater.cpp @@ -91,9 +91,9 @@ struct GreaterFixtureTwoByTwo : public GreaterFixtureAutoSetup BOOST_FIXTURE_TEST_CASE(ParseGreaterTwoByTwo, GreaterFixtureTwoByTwo) { - RunTest<2>({ { "input0", { 1.0f, 2.0f, 3.0f, 4.0f} }, - { "input1", { 1.0f, 5.0f, 2.0f, 2.0f} } }, - { { "output", { 0.0f, 0.0f, 1.0f, 1.0f} } }); + RunComparisonTest<2>({ { "input0", { 1.0f, 2.0f, 3.0f, 4.0f} }, + { "input1", { 1.0f, 5.0f, 2.0f, 2.0f} } }, + { { "output", { 0, 0, 1, 1} } }); } struct GreaterBroadcast1DAnd4D : public GreaterFixtureAutoSetup @@ -103,9 +103,9 @@ struct GreaterBroadcast1DAnd4D : public GreaterFixtureAutoSetup BOOST_FIXTURE_TEST_CASE(ParseGreaterBroadcast1DToTwoByTwo, GreaterBroadcast1DAnd4D) { - RunTest<4>({ { "input0", { 2.0f } }, - { "input1", { 1.0f, 2.0f, 3.0f, 2.0f } } }, - { { "output", { 1.0f, 0.0f, 0.0f, 0.0f } } }); + RunComparisonTest<4>({ { "input0", { 2.0f } }, + { "input1", { 1.0f, 2.0f, 3.0f, 2.0f } } }, + { { "output", { 1, 0, 0, 0 } } }); } struct GreaterBroadcast4DAnd1D : public GreaterFixtureAutoSetup @@ -115,9 +115,9 @@ struct GreaterBroadcast4DAnd1D : public GreaterFixtureAutoSetup BOOST_FIXTURE_TEST_CASE(ParseGreaterBroadcast4DAnd1D, GreaterBroadcast4DAnd1D) { - RunTest<4>({ { "input0", { 1.0f, 2.0f, 3.0f, 2.0f } }, - { "input1", { 3.0f } } }, - { { "output", { 0.0f, 0.0f, 0.0f, 0.0f } } }); + RunComparisonTest<4>({ { "input0", { 1.0f, 2.0f, 3.0f, 2.0f } }, + { "input1", { 3.0f } } }, + { { "output", { 0, 0, 0, 0 } } }); } struct GreaterMultiDimBroadcast : public GreaterFixtureAutoSetup @@ -127,13 +127,13 @@ struct GreaterMultiDimBroadcast : public GreaterFixtureAutoSetup BOOST_FIXTURE_TEST_CASE(ParseGreaterMultiDimBroadcast, GreaterMultiDimBroadcast) { - RunTest<4>({ { "input0", { 1.0f, 2.0f } }, - { "input1", { 1.0f, 2.0f, 3.0f, - 3.0f, 2.0f, 2.0f } } }, - { { "output", { 0.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f } } }); + RunComparisonTest<4>({ { "input0", { 1.0f, 2.0f } }, + { "input1", { 1.0f, 2.0f, 3.0f, + 3.0f, 2.0f, 2.0f } } }, + { { "output", { 0, 0, 0, + 1, 0, 0, + 0, 0, 0, + 0, 0, 0 } } }); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/armnnUtils/ParserPrototxtFixture.hpp b/src/armnnUtils/ParserPrototxtFixture.hpp index be35e460cf..7ae0742b8e 100644 --- a/src/armnnUtils/ParserPrototxtFixture.hpp +++ b/src/armnnUtils/ParserPrototxtFixture.hpp @@ -53,11 +53,17 @@ struct ParserPrototxtFixture template void RunTest(const std::vector& inputData, const std::vector& expectedOutputData); + /// Executes the network with the given input tensor and checks the result against the given output tensor. + /// Calls RunTest with output type of uint8_t for checking comparison operators. + template + void RunComparisonTest(const std::map>& inputData, + const std::map>& expectedOutputData); + /// Executes the network with the given input tensors and checks the results against the given output tensors. /// This overload supports multiple inputs and multiple outputs, identified by name. - template + template void RunTest(const std::map>& inputData, - const std::map>& expectedOutputData); + const std::map>& expectedOutputData); std::string m_Prototext; std::unique_ptr m_Parser; @@ -162,15 +168,24 @@ armnn::IOptimizedNetworkPtr ParserPrototxtFixture::SetupOptimizedNetwor template template void ParserPrototxtFixture::RunTest(const std::vector& inputData, - const std::vector& expectedOutputData) + const std::vector& expectedOutputData) { RunTest({ { m_SingleInputName, inputData } }, { { m_SingleOutputName, expectedOutputData } }); } template template +void ParserPrototxtFixture::RunComparisonTest(const std::map>& inputData, + const std::map>& + expectedOutputData) +{ + RunTest(inputData, expectedOutputData); +} + +template +template void ParserPrototxtFixture::RunTest(const std::map>& inputData, - const std::map>& expectedOutputData) + const std::map>& expectedOutputData) { using BindingPointInfo = std::pair; @@ -183,12 +198,12 @@ void ParserPrototxtFixture::RunTest(const std::map> outputStorage; + std::map> outputStorage; armnn::OutputTensors outputTensors; for (auto&& it : expectedOutputData) { BindingPointInfo bindingInfo = m_Parser->GetNetworkOutputBindingInfo(it.first); - outputStorage.emplace(it.first, MakeTensor(bindingInfo.second)); + outputStorage.emplace(it.first, MakeTensor(bindingInfo.second)); outputTensors.push_back( { bindingInfo.first, armnn::Tensor(bindingInfo.second, outputStorage.at(it.first).data()) }); } @@ -243,8 +258,15 @@ void ParserPrototxtFixture::RunTest(const std::map(bindingInfo.second, it.second); - BOOST_TEST(CompareTensors(outputExpected, outputStorage[it.first])); + auto outputExpected = MakeTensor(bindingInfo.second, it.second); + if (std::is_same::value) + { + BOOST_TEST(CompareTensors(outputExpected, outputStorage[it.first], true)); + } + else + { + BOOST_TEST(CompareTensors(outputExpected, outputStorage[it.first])); + } } } diff --git a/src/backends/backendsCommon/MakeWorkloadHelper.hpp b/src/backends/backendsCommon/MakeWorkloadHelper.hpp index 7784cc6d4d..2d54335355 100644 --- a/src/backends/backendsCommon/MakeWorkloadHelper.hpp +++ b/src/backends/backendsCommon/MakeWorkloadHelper.hpp @@ -38,7 +38,7 @@ struct MakeWorkloadForType // Makes a workload for one the specified types based on the data type requirements of the tensorinfo. // Specify type void as the WorkloadType for unsupported DataType/WorkloadType combos. template + typename BooleanWorkload, typename QueueDescriptorType, typename... Args> std::unique_ptr MakeWorkloadHelper(const QueueDescriptorType& descriptor, const WorkloadInfo& info, Args&&... args) @@ -47,8 +47,10 @@ std::unique_ptr MakeWorkloadHelper(const QueueDescriptorType& descrip info.m_InputTensorInfos[0].GetDataType() : info.m_OutputTensorInfos[0].GetDataType(); - BOOST_ASSERT(info.m_InputTensorInfos.empty() || info.m_OutputTensorInfos.empty() - || info.m_InputTensorInfos[0].GetDataType() == info.m_OutputTensorInfos[0].GetDataType()); + BOOST_ASSERT(info.m_InputTensorInfos.empty() || + info.m_OutputTensorInfos.empty() || + ((info.m_InputTensorInfos[0].GetDataType() == info.m_OutputTensorInfos[0].GetDataType()) || + info.m_OutputTensorInfos[0].GetDataType() == armnn::DataType::Boolean)); switch (dataType) { @@ -60,6 +62,8 @@ std::unique_ptr MakeWorkloadHelper(const QueueDescriptorType& descrip return MakeWorkloadForType::Func(descriptor, info, std::forward(args)...); case DataType::Signed32: return MakeWorkloadForType::Func(descriptor, info, std::forward(args)...); + case DataType::Boolean: + return MakeWorkloadForType::Func(descriptor, info, std::forward(args)...); default: BOOST_ASSERT_MSG(false, "Unknown DataType."); return nullptr; @@ -67,16 +71,18 @@ std::unique_ptr MakeWorkloadHelper(const QueueDescriptorType& descrip } // Makes a workload for one the specified types based on the data type requirements of the tensorinfo. -// Calling this method is the equivalent of calling the three typed MakeWorkload method with . +// Calling this method is the equivalent of calling the five typed MakeWorkload method with . // Specify type void as the WorkloadType for unsupported DataType/WorkloadType combos. template std::unique_ptr MakeWorkloadHelper(const QueueDescriptorType& descriptor, const WorkloadInfo& info, Args&&... args) { - return MakeWorkloadHelper(descriptor, info, - std::forward(args)...); + return MakeWorkloadHelper( + descriptor, + info, + std::forward(args)...); } } //namespace diff --git a/src/backends/backendsCommon/Workload.hpp b/src/backends/backendsCommon/Workload.hpp index 34d13635ba..4d14adbf54 100644 --- a/src/backends/backendsCommon/Workload.hpp +++ b/src/backends/backendsCommon/Workload.hpp @@ -164,6 +164,19 @@ using Uint8Workload = TypedWorkload using Int32Workload = TypedWorkload; +template +using BooleanWorkload = TypedWorkload; + +template +using BaseFloat32ComparisonWorkload = MultiTypedWorkload; + +template +using BaseUint8ComparisonWorkload = MultiTypedWorkload; + template using Float16ToFloat32Workload = MultiTypedWorkload +template INetworkPtr CreateArithmeticNetwork(const std::vector& inputShapes, const TensorShape& outputShape, const LayerType type, @@ -39,22 +39,25 @@ INetworkPtr CreateArithmeticNetwork(const std::vector& inputShapes, for (unsigned int i = 0; i < inputShapes.size(); ++i) { - TensorInfo inputTensorInfo(inputShapes[i], DataType, qScale, qOffset); + TensorInfo inputTensorInfo(inputShapes[i], ArmnnTypeInput, qScale, qOffset); IConnectableLayer* input = net->AddInputLayer(boost::numeric_cast(i)); Connect(input, arithmeticLayer, inputTensorInfo, 0, i); } - TensorInfo outputTensorInfo(outputShape, DataType, qScale, qOffset); + TensorInfo outputTensorInfo(outputShape, ArmnnTypeOutput, qScale, qOffset); IConnectableLayer* output = net->AddOutputLayer(0, "output"); Connect(arithmeticLayer, output, outputTensorInfo, 0, 0); return net; } -template> +template, + typename TOutput = armnn::ResolveType> void ArithmeticSimpleEndToEnd(const std::vector& backends, const LayerType type, - const std::vector expectedOutput) + const std::vector expectedOutput) { using namespace armnn; @@ -62,26 +65,29 @@ void ArithmeticSimpleEndToEnd(const std::vector& backends, const TensorShape& outputShape = { 2, 2, 2, 2 }; // Builds up the structure of the network - INetworkPtr net = CreateArithmeticNetwork(inputShapes, outputShape, type); + INetworkPtr net = CreateArithmeticNetwork(inputShapes, outputShape, type); BOOST_TEST_CHECKPOINT("create a network"); - const std::vector input0({ 1, 1, 1, 1, 5, 5, 5, 5, - 3, 3, 3, 3, 4, 4, 4, 4 }); + const std::vector input0({ 1, 1, 1, 1, 5, 5, 5, 5, + 3, 3, 3, 3, 4, 4, 4, 4 }); - const std::vector input1({ 1, 1, 1, 1, 3, 3, 3, 3, - 5, 5, 5, 5, 4, 4, 4, 4 }); + const std::vector input1({ 1, 1, 1, 1, 3, 3, 3, 3, + 5, 5, 5, 5, 4, 4, 4, 4 }); - std::map> inputTensorData = {{ 0, input0 }, { 1, input1 }}; - std::map> expectedOutputData = {{ 0, expectedOutput }}; + std::map> inputTensorData = {{ 0, input0 }, { 1, input1 }}; + std::map> expectedOutputData = {{ 0, expectedOutput }}; - EndToEndLayerTestImpl(move(net), inputTensorData, expectedOutputData, backends); + EndToEndLayerTestImpl(move(net), inputTensorData, expectedOutputData, backends); } -template> +template, + typename TOutput = armnn::ResolveType> void ArithmeticBroadcastEndToEnd(const std::vector& backends, const LayerType type, - const std::vector expectedOutput) + const std::vector expectedOutput) { using namespace armnn; @@ -89,19 +95,19 @@ void ArithmeticBroadcastEndToEnd(const std::vector& backends, const TensorShape& outputShape = { 1, 2, 2, 3 }; // Builds up the structure of the network - INetworkPtr net = CreateArithmeticNetwork(inputShapes, outputShape, type); + INetworkPtr net = CreateArithmeticNetwork(inputShapes, outputShape, type); BOOST_TEST_CHECKPOINT("create a network"); - const std::vector input0({ 1, 2, 3, 1, 0, 6, - 7, 8, 9, 10, 11, 12 }); + const std::vector input0({ 1, 2, 3, 1, 0, 6, + 7, 8, 9, 10, 11, 12 }); - const std::vector input1({ 1, 1, 3 }); + const std::vector input1({ 1, 1, 3 }); - std::map> inputTensorData = {{ 0, input0 }, { 1, input1 }}; - std::map> expectedOutputData = {{ 0, expectedOutput }}; + std::map> inputTensorData = {{ 0, input0 }, { 1, input1 }}; + std::map> expectedOutputData = {{ 0, expectedOutput }}; - EndToEndLayerTestImpl(move(net), inputTensorData, expectedOutputData, backends); + EndToEndLayerTestImpl(move(net), inputTensorData, expectedOutputData, backends); } } // anonymous namespace diff --git a/src/backends/backendsCommon/test/EndToEndTestImpl.hpp b/src/backends/backendsCommon/test/EndToEndTestImpl.hpp index 15a3937aca..7d2b091e42 100644 --- a/src/backends/backendsCommon/test/EndToEndTestImpl.hpp +++ b/src/backends/backendsCommon/test/EndToEndTestImpl.hpp @@ -102,10 +102,10 @@ inline bool ConstantUsageUint8Test(const std::vector& backends) ); } -template +template void EndToEndLayerTestImpl(INetworkPtr network, - const std::map>& inputTensorData, - const std::map>& expectedOutputData, + const std::map>& inputTensorData, + const std::map>& expectedOutputData, std::vector backends) { // Create runtime in which test will run @@ -128,10 +128,10 @@ void EndToEndLayerTestImpl(INetworkPtr network, } OutputTensors outputTensors; outputTensors.reserve(expectedOutputData.size()); - std::map> outputStorage; + std::map> outputStorage; for (auto&& it : expectedOutputData) { - std::vector out(it.second.size()); + std::vector out(it.second.size()); outputStorage.emplace(it.first, out); outputTensors.push_back({it.first, Tensor(runtime->GetOutputTensorInfo(netId, it.first), @@ -144,7 +144,7 @@ void EndToEndLayerTestImpl(INetworkPtr network, // Checks the results. for (auto&& it : expectedOutputData) { - std::vector out = outputStorage.at(it.first); + std::vector out = outputStorage.at(it.first); BOOST_TEST(it.second == out); } } diff --git a/src/backends/backendsCommon/test/LayerTests.cpp b/src/backends/backendsCommon/test/LayerTests.cpp index 95fa50b89c..6060b30928 100644 --- a/src/backends/backendsCommon/test/LayerTests.cpp +++ b/src/backends/backendsCommon/test/LayerTests.cpp @@ -1783,66 +1783,98 @@ std::unique_ptr CreateWorkload( } namespace { - template > - LayerTestResult ElementwiseTestHelper - (armnn::IWorkloadFactory & workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager, - const unsigned int shape0[4], std::vector values0, - const unsigned int shape1[4], std::vector values1, - const unsigned int outShape[4], std::vector outValues, - float qScale = 0.0f, int qOffset = 0) - { - const size_t dimensionCount = 4; - armnn::TensorInfo inputTensorInfo0{dimensionCount, shape0, ArmnnType}; - armnn::TensorInfo inputTensorInfo1{dimensionCount, shape1, ArmnnType}; - armnn::TensorInfo outputTensorInfo{dimensionCount, outShape, ArmnnType}; - auto input0 = MakeTensor(inputTensorInfo0, values0); - auto input1 = MakeTensor(inputTensorInfo1, values1); +template , + typename TOutput = armnn::ResolveType> +LayerTestResult ElementwiseTestHelper( + armnn::IWorkloadFactory & workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager, + const unsigned int shape0[4], std::vector values0, + const unsigned int shape1[4], std::vector values1, + const unsigned int outShape[4], std::vector outValues, + float qScale = 0.0f, int qOffset = 0) +{ + const size_t dimensionCount = 4; + armnn::TensorInfo inputTensorInfo0{dimensionCount, shape0, ArmnnTypeInput}; + armnn::TensorInfo inputTensorInfo1{dimensionCount, shape1, ArmnnTypeInput}; + armnn::TensorInfo outputTensorInfo{dimensionCount, outShape, ArmnnTypeOutput}; - if (armnn::IsQuantizedType()) - { - inputTensorInfo0.SetQuantizationScale(qScale); - inputTensorInfo0.SetQuantizationOffset(qOffset); + auto input0 = MakeTensor(inputTensorInfo0, values0); + auto input1 = MakeTensor(inputTensorInfo1, values1); - inputTensorInfo1.SetQuantizationScale(qScale); - inputTensorInfo1.SetQuantizationOffset(qOffset); + if (armnn::IsQuantizedType()) + { + inputTensorInfo0.SetQuantizationScale(qScale); + inputTensorInfo0.SetQuantizationOffset(qOffset); - outputTensorInfo.SetQuantizationScale(qScale); - outputTensorInfo.SetQuantizationOffset(qOffset); - } + inputTensorInfo1.SetQuantizationScale(qScale); + inputTensorInfo1.SetQuantizationOffset(qOffset); - LayerTestResult ret(outputTensorInfo); + outputTensorInfo.SetQuantizationScale(qScale); + outputTensorInfo.SetQuantizationOffset(qOffset); + } - std::unique_ptr inputHandle0 = workloadFactory.CreateTensorHandle(inputTensorInfo0); - std::unique_ptr inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1); - std::unique_ptr outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo); + LayerTestResult ret(outputTensorInfo); - Descriptor data; - armnn::WorkloadInfo info; - AddInputToWorkload(data, info, inputTensorInfo0, inputHandle0.get()); - AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get()); - AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); - auto workload = CreateWorkload(workloadFactory, info, data); + if(ArmnnTypeOutput == armnn::DataType::Boolean) + { + ret.compareBoolean = true; + } - inputHandle0->Allocate(); - inputHandle1->Allocate(); - outputHandle->Allocate(); + std::unique_ptr inputHandle0 = workloadFactory.CreateTensorHandle(inputTensorInfo0); + std::unique_ptr inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1); + std::unique_ptr outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo); - CopyDataToITensorHandle(inputHandle0.get(), &input0[0][0][0][0]); - CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]); + Descriptor data; + armnn::WorkloadInfo info; + AddInputToWorkload(data, info, inputTensorInfo0, inputHandle0.get()); + AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get()); + AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); + auto workload = CreateWorkload(workloadFactory, info, data); + + inputHandle0->Allocate(); + inputHandle1->Allocate(); + outputHandle->Allocate(); - ExecuteWorkload(*workload, memoryManager); + CopyDataToITensorHandle(inputHandle0.get(), &input0[0][0][0][0]); + CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]); - CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get()); + ExecuteWorkload(*workload, memoryManager); - ret.outputExpected = MakeTensor(outputTensorInfo, outValues); - return ret; - } + CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get()); + + ret.outputExpected = MakeTensor(outputTensorInfo, outValues); + return ret; } -LayerTestResult EqualSimpleTest(armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +template > +LayerTestResult ElementwiseTestHelper( + armnn::IWorkloadFactory & workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager, + const unsigned int shape0[4], std::vector values0, + const unsigned int shape1[4], std::vector values1, + const unsigned int outShape[4], std::vector outValues, + float qScale = 0.0f, int qOffset = 0) +{ + return ElementwiseTestHelper + (workloadFactory, + memoryManager, + shape0, + values0, + shape1, + values1, + outShape, + outValues, + qScale, + qOffset); +} +} + +LayerTestResult EqualSimpleTest(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) { const unsigned int width = 2; const unsigned int height = 2; @@ -1857,10 +1889,10 @@ LayerTestResult EqualSimpleTest(armnn::IWorkloadFactory& workloadFacto std::vector input1({ 1, 1, 1, 1, 3, 3, 3, 3, 5, 5, 5, 5, 4, 4, 4, 4 }); - std::vector output({ 1, 1, 1, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 1 }); + std::vector output({ 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1 }); - return ElementwiseTestHelper( + return ElementwiseTestHelper( workloadFactory, memoryManager, shape, @@ -1871,7 +1903,7 @@ LayerTestResult EqualSimpleTest(armnn::IWorkloadFactory& workloadFacto output); } -LayerTestResult EqualBroadcast1ElementTest( +LayerTestResult EqualBroadcast1ElementTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) { @@ -1881,9 +1913,9 @@ LayerTestResult EqualBroadcast1ElementTest( unsigned int shape1[] = { 1, 1, 1, 1 }; std::vector input1({ 1 }); - std::vector output({ 1, 0, 0, 0, 0, 0, 0, 0}); + std::vector output({ 1, 0, 0, 0, 0, 0, 0, 0}); - return ElementwiseTestHelper( + return ElementwiseTestHelper( workloadFactory, memoryManager, shape0, @@ -1894,7 +1926,7 @@ LayerTestResult EqualBroadcast1ElementTest( output); } -LayerTestResult EqualBroadcast1DVectorTest( +LayerTestResult EqualBroadcast1DVectorTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) { @@ -1906,10 +1938,10 @@ LayerTestResult EqualBroadcast1DVectorTest( std::vector input1({ 1, 2, 3}); - std::vector output({ 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0 }); + std::vector output({ 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0 }); - return ElementwiseTestHelper( + return ElementwiseTestHelper( workloadFactory, memoryManager, shape0, @@ -1928,7 +1960,7 @@ LayerTestResult EqualUint8Test( // See dequantized values to the right. std::vector input0({ 1, 1, 1, 1, 6, 6, 6, 6, - 3, 3, 3, 3, 5, 5, 5, 5 }); + 3, 3, 3, 3, 7, 7, 7, 7 }); std::vector input1({ 2, 2, 2, 2, 6, 6, 6, 6, 3, 3, 3, 3, 5, 5, 5, 5 }); @@ -1936,7 +1968,9 @@ LayerTestResult EqualUint8Test( std::vector output({ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }); - return ElementwiseTestHelper( + return ElementwiseTestHelper( workloadFactory, memoryManager, shape, @@ -1964,7 +1998,9 @@ LayerTestResult EqualBroadcast1ElementUint8Test( std::vector output({ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }); - return ElementwiseTestHelper( + return ElementwiseTestHelper( workloadFactory, memoryManager, shape0, @@ -1992,7 +2028,9 @@ LayerTestResult EqualBroadcast1DVectorUint8Test( std::vector output({ 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }); - return ElementwiseTestHelper( + return ElementwiseTestHelper( workloadFactory, memoryManager, shape0, @@ -2005,7 +2043,7 @@ LayerTestResult EqualBroadcast1DVectorUint8Test( 0); } -LayerTestResult GreaterSimpleTest(armnn::IWorkloadFactory& workloadFactory, +LayerTestResult GreaterSimpleTest(armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) { const unsigned int width = 2; @@ -2021,10 +2059,10 @@ LayerTestResult GreaterSimpleTest(armnn::IWorkloadFactory& workloadFac std::vector input1({ 1, 1, 1, 1, 3, 3, 3, 3, 5, 5, 5, 5, 4, 4, 4, 4 }); - std::vector output({ 0, 0, 0, 0, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0 }); + std::vector output({ 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0 }); - return ElementwiseTestHelper( + return ElementwiseTestHelper( workloadFactory, memoryManager, shape, @@ -2035,7 +2073,7 @@ LayerTestResult GreaterSimpleTest(armnn::IWorkloadFactory& workloadFac output); } -LayerTestResult GreaterBroadcast1ElementTest( +LayerTestResult GreaterBroadcast1ElementTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) { @@ -2045,9 +2083,9 @@ LayerTestResult GreaterBroadcast1ElementTest( unsigned int shape1[] = { 1, 1, 1, 1 }; std::vector input1({ 1 }); - std::vector output({ 0, 1, 1, 1, 1, 1, 1, 1}); + std::vector output({ 0, 1, 1, 1, 1, 1, 1, 1}); - return ElementwiseTestHelper( + return ElementwiseTestHelper( workloadFactory, memoryManager, shape0, @@ -2058,7 +2096,7 @@ LayerTestResult GreaterBroadcast1ElementTest( output); } -LayerTestResult GreaterBroadcast1DVectorTest( +LayerTestResult GreaterBroadcast1DVectorTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) { @@ -2070,10 +2108,10 @@ LayerTestResult GreaterBroadcast1DVectorTest( std::vector input1({ 1, 3, 2}); - std::vector output({ 0, 0, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1 }); + std::vector output({ 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1 }); - return ElementwiseTestHelper( + return ElementwiseTestHelper( workloadFactory, memoryManager, shape0, @@ -2100,7 +2138,9 @@ LayerTestResult GreaterUint8Test( std::vector output({ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0 }); - return ElementwiseTestHelper( + return ElementwiseTestHelper( workloadFactory, memoryManager, shape, @@ -2128,7 +2168,9 @@ LayerTestResult GreaterBroadcast1ElementUint8Test( std::vector output({ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }); - return ElementwiseTestHelper( + return ElementwiseTestHelper( workloadFactory, memoryManager, shape0, @@ -2156,7 +2198,9 @@ LayerTestResult GreaterBroadcast1DVectorUint8Test( std::vector output({ 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }); - return ElementwiseTestHelper( + return ElementwiseTestHelper( workloadFactory, memoryManager, shape0, @@ -2235,7 +2279,7 @@ LayerTestResult MaximumBroadcast1DVectorTest( std::vector input1({ 1, 2, 3}); std::vector output({ 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12 }); + 7, 8, 9, 10, 11, 12 }); return ElementwiseTestHelper( workloadFactory, diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp index 16fe43212b..05d510e78e 100644 --- a/src/backends/backendsCommon/test/LayerTests.hpp +++ b/src/backends/backendsCommon/test/LayerTests.hpp @@ -47,11 +47,13 @@ struct LayerTestResult output.resize(shape); outputExpected.resize(shape); supported = true; + compareBoolean = false; } boost::multi_array output; boost::multi_array outputExpected; bool supported; + bool compareBoolean; }; LayerTestResult SimpleConvolution2d3x5Test( @@ -909,15 +911,15 @@ LayerTestResult Concatenation3dDim2DiffInputDimsUint8Test( const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, bool useSubtensor); -LayerTestResult EqualSimpleTest( +LayerTestResult EqualSimpleTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); -LayerTestResult EqualBroadcast1ElementTest( +LayerTestResult EqualBroadcast1ElementTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); -LayerTestResult EqualBroadcast1DVectorTest( +LayerTestResult EqualBroadcast1DVectorTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); @@ -933,15 +935,15 @@ LayerTestResult EqualBroadcast1DVectorUint8Test( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); -LayerTestResult GreaterSimpleTest( +LayerTestResult GreaterSimpleTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); -LayerTestResult GreaterBroadcast1ElementTest( +LayerTestResult GreaterBroadcast1ElementTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); -LayerTestResult GreaterBroadcast1DVectorTest( +LayerTestResult GreaterBroadcast1DVectorTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); diff --git a/src/backends/backendsCommon/test/MergerTestImpl.hpp b/src/backends/backendsCommon/test/MergerTestImpl.hpp index 2bdfe286c9..ec42b09ada 100644 --- a/src/backends/backendsCommon/test/MergerTestImpl.hpp +++ b/src/backends/backendsCommon/test/MergerTestImpl.hpp @@ -110,7 +110,7 @@ void MergerDim0EndToEnd(const std::vector& backends) std::map> inputTensorData = {{ 0,inputData }, { 1,inputData }}; std::map> expectedOutputData = {{ 0,expectedOutput }}; - EndToEndLayerTestImpl(move(net), inputTensorData, expectedOutputData, backends); + EndToEndLayerTestImpl(move(net), inputTensorData, expectedOutputData, backends); } template diff --git a/src/backends/cl/ClLayerSupport.cpp b/src/backends/cl/ClLayerSupport.cpp index 3e35f9d52d..410cb04288 100644 --- a/src/backends/cl/ClLayerSupport.cpp +++ b/src/backends/cl/ClLayerSupport.cpp @@ -122,6 +122,7 @@ bool IsSupportedForDataTypeCl(Optional reasonIfUnsupported, floatFuncPtr, uint8FuncPtr, &FalseFunc<>, + &FalseFunc<>, std::forward(params)...); } @@ -267,7 +268,8 @@ bool ClLayerSupport::IsFloorSupported(const TensorInfo& input, &FalseFuncF16<>, &TrueFunc<>, &FalseFuncU8<>, - &FalseFuncI32<>); + &FalseFuncI32<>, + &FalseFuncU8<>); } bool ClLayerSupport::IsFullyConnectedSupported(const TensorInfo& input, @@ -453,10 +455,14 @@ bool ClLayerSupport::IsNormalizationSupported(const TensorInfo& input, bool ClLayerSupport::IsOutputSupported(const TensorInfo& output, Optional reasonIfUnsupported) const { - return IsSupportedForDataTypeCl(reasonIfUnsupported, - output.GetDataType(), - &TrueFunc<>, - &TrueFunc<>); + return IsClBackendSupported(reasonIfUnsupported) && + IsSupportedForDataTypeGeneric(reasonIfUnsupported, + output.GetDataType(), + &TrueFunc<>, + &TrueFunc<>, + &TrueFunc<>, + &FalseFuncI32<>, + &TrueFunc<>); } bool ClLayerSupport::IsPadSupported(const TensorInfo& input, diff --git a/src/backends/cl/ClWorkloadFactory.cpp b/src/backends/cl/ClWorkloadFactory.cpp index 71c1b89c09..7a53257af1 100644 --- a/src/backends/cl/ClWorkloadFactory.cpp +++ b/src/backends/cl/ClWorkloadFactory.cpp @@ -126,7 +126,8 @@ std::unique_ptr ClWorkloadFactory::CreateInput(const InputQueueDescri std::unique_ptr ClWorkloadFactory::CreateOutput(const OutputQueueDescriptor& descriptor, const WorkloadInfo& info) const { - return MakeWorkload(descriptor, info); + return MakeWorkloadHelper(descriptor, info); } std::unique_ptr ClWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor, diff --git a/src/backends/neon/NeonLayerSupport.cpp b/src/backends/neon/NeonLayerSupport.cpp index 2f83c8f82a..9db7354e9e 100644 --- a/src/backends/neon/NeonLayerSupport.cpp +++ b/src/backends/neon/NeonLayerSupport.cpp @@ -72,6 +72,7 @@ bool IsSupportedForDataTypeNeon(Optional reasonIfUnsupported, floatFuncPtr, uint8FuncPtr, &FalseFunc<>, + &FalseFunc<>, std::forward(params)...); } @@ -214,7 +215,8 @@ bool NeonLayerSupport::IsFloorSupported(const TensorInfo& input, &FalseFuncF16<>, &TrueFunc<>, &FalseFuncU8<>, - &FalseFuncI32<>); + &FalseFuncI32<>, + &FalseFuncU8<>); } bool NeonLayerSupport::IsFullyConnectedSupported(const TensorInfo& input, @@ -344,10 +346,14 @@ bool NeonLayerSupport::IsNormalizationSupported(const TensorInfo& input, bool NeonLayerSupport::IsOutputSupported(const TensorInfo& output, Optional reasonIfUnsupported) const { - return IsSupportedForDataTypeNeon(reasonIfUnsupported, - output.GetDataType(), - &TrueFunc<>, - &TrueFunc<>); + return IsNeonBackendSupported(reasonIfUnsupported) && + IsSupportedForDataTypeGeneric(reasonIfUnsupported, + output.GetDataType(), + &TrueFunc<>, + &TrueFunc<>, + &TrueFunc<>, + &FalseFuncI32<>, + &TrueFunc<>); } bool NeonLayerSupport::IsPermuteSupported(const TensorInfo& input, diff --git a/src/backends/neon/NeonTensorHandle.hpp b/src/backends/neon/NeonTensorHandle.hpp index 7206b6fc5a..b972043827 100644 --- a/src/backends/neon/NeonTensorHandle.hpp +++ b/src/backends/neon/NeonTensorHandle.hpp @@ -94,6 +94,7 @@ private: armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(), static_cast(memory)); break; + case arm_compute::DataType::U8: case arm_compute::DataType::QASYMM8: armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(), static_cast(memory)); @@ -114,6 +115,7 @@ private: armcomputetensorutils::CopyArmComputeITensorData(static_cast(memory), this->GetTensor()); break; + case arm_compute::DataType::U8: case arm_compute::DataType::QASYMM8: armcomputetensorutils::CopyArmComputeITensorData(static_cast(memory), this->GetTensor()); @@ -181,6 +183,7 @@ private: armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(), static_cast(memory)); break; + case arm_compute::DataType::U8: case arm_compute::DataType::QASYMM8: armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(), static_cast(memory)); @@ -201,6 +204,7 @@ private: armcomputetensorutils::CopyArmComputeITensorData(static_cast(memory), this->GetTensor()); break; + case arm_compute::DataType::U8: case arm_compute::DataType::QASYMM8: armcomputetensorutils::CopyArmComputeITensorData(static_cast(memory), this->GetTensor()); diff --git a/src/backends/neon/NeonWorkloadFactory.cpp b/src/backends/neon/NeonWorkloadFactory.cpp index e7fac97c2c..e8a00d6b14 100644 --- a/src/backends/neon/NeonWorkloadFactory.cpp +++ b/src/backends/neon/NeonWorkloadFactory.cpp @@ -91,7 +91,8 @@ std::unique_ptr NeonWorkloadFactory::CreateInput(const InputQueueDesc std::unique_ptr NeonWorkloadFactory::CreateOutput(const OutputQueueDescriptor& descriptor, const WorkloadInfo& info) const { - return MakeWorkloadHelper(descriptor, info); + return MakeWorkloadHelper(descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor, diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp index 45f108c2f8..78e44bd6a3 100644 --- a/src/backends/reference/RefLayerSupport.cpp +++ b/src/backends/reference/RefLayerSupport.cpp @@ -35,6 +35,7 @@ bool IsSupportedForDataTypeRef(Optional reasonIfUnsupported, floatFuncPtr, uint8FuncPtr, &FalseFunc, + &FalseFunc, std::forward(params)...); } @@ -111,7 +112,8 @@ bool RefLayerSupport::IsConstantSupported(const TensorInfo& output, &FalseFunc<>, &TrueFunc<>, &TrueFunc<>, - &TrueFunc<>); + &TrueFunc<>, + &FalseFunc<>); } bool RefLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input, @@ -123,13 +125,15 @@ bool RefLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input, &TrueFunc<>, &FalseInputFuncF32<>, &FalseFuncU8<>, - &FalseFuncI32<>) && + &FalseFuncI32<>, + &FalseFuncU8<>) && IsSupportedForDataTypeGeneric(reasonIfUnsupported, output.GetDataType(), &FalseOutputFuncF16<>, &TrueFunc<>, &FalseFuncU8<>, - &FalseFuncI32<>)); + &FalseFuncI32<>, + &FalseFuncU8<>)); } bool RefLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input, @@ -141,13 +145,15 @@ bool RefLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input, &FalseInputFuncF16<>, &TrueFunc<>, &FalseFuncU8<>, - &FalseFuncI32<>) && + &FalseFuncI32<>, + &FalseFuncU8<>) && IsSupportedForDataTypeGeneric(reasonIfUnsupported, output.GetDataType(), &TrueFunc<>, &FalseOutputFuncF32<>, &FalseFuncU8<>, - &FalseFuncI32<>)); + &FalseFuncI32<>, + &FalseFuncU8<>)); } bool RefLayerSupport::IsConvolution2dSupported(const TensorInfo& input, @@ -415,10 +421,13 @@ bool RefLayerSupport::IsMemCopySupported(const TensorInfo &input, Optional reasonIfUnsupported) const { ignore_unused(output); - return IsSupportedForDataTypeRef(reasonIfUnsupported, - input.GetDataType(), - &TrueFunc<>, - &TrueFunc<>); + return IsSupportedForDataTypeGeneric(reasonIfUnsupported, + input.GetDataType(), + &TrueFunc<>, + &TrueFunc<>, + &TrueFunc<>, + &FalseFuncI32<>, + &TrueFunc<>); } bool RefLayerSupport::IsMinimumSupported(const TensorInfo& input0, @@ -463,10 +472,13 @@ bool RefLayerSupport::IsNormalizationSupported(const TensorInfo& input, bool RefLayerSupport::IsOutputSupported(const TensorInfo& output, Optional reasonIfUnsupported) const { - return IsSupportedForDataTypeRef(reasonIfUnsupported, - output.GetDataType(), - &TrueFunc<>, - &TrueFunc<>); + return IsSupportedForDataTypeGeneric(reasonIfUnsupported, + output.GetDataType(), + &TrueFunc<>, + &TrueFunc<>, + &TrueFunc<>, + &FalseFuncI32<>, + &TrueFunc<>); } bool RefLayerSupport::IsPadSupported(const TensorInfo& input, diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp index b112e9dd6a..75a9efd70f 100644 --- a/src/backends/reference/RefWorkloadFactory.cpp +++ b/src/backends/reference/RefWorkloadFactory.cpp @@ -24,7 +24,8 @@ template RefWorkloadFactory::MakeWorkload(const QueueDescriptorType& descriptor, const WorkloadInfo& info) const { - return armnn::MakeWorkloadHelper(descriptor, info); + return armnn::MakeWorkloadHelper(descriptor, + info); } RefWorkloadFactory::RefWorkloadFactory() @@ -90,7 +91,8 @@ std::unique_ptr RefWorkloadFactory::CreateOutput(const OutputQueueDes throw InvalidArgumentException("RefWorkloadFactory::CreateOutput: data input and output differ in byte count."); } - return MakeWorkload(descriptor, info); + return MakeWorkloadHelper(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor, @@ -127,7 +129,7 @@ std::unique_ptr RefWorkloadFactory::CreatePermute(const Permut const WorkloadInfo& info) const { return MakeWorkloadHelper(descriptor, info); + NullWorkload, NullWorkload>(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreatePooling2d(const Pooling2dQueueDescriptor& descriptor, @@ -206,7 +208,7 @@ std::unique_ptr RefWorkloadFactory::CreateConstant(const ConstantQueu const WorkloadInfo& info) const { return MakeWorkloadHelper(descriptor, info); + RefConstantInt32Workload, NullWorkload>(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateReshape(const ReshapeQueueDescriptor& descriptor, diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk index 763f26e18c..3ee07913dc 100644 --- a/src/backends/reference/backend.mk +++ b/src/backends/reference/backend.mk @@ -28,6 +28,7 @@ BACKEND_SOURCES := \ workloads/RefBatchNormalizationUint8Workload.cpp \ workloads/RefBatchToSpaceNdFloat32Workload.cpp \ workloads/RefBatchToSpaceNdUint8Workload.cpp \ + workloads/RefComparisonWorkload.cpp \ workloads/RefConstantWorkload.cpp \ workloads/RefConvertFp16ToFp32Workload.cpp \ workloads/RefConvertFp32ToFp16Workload.cpp \ diff --git a/src/backends/reference/test/RefEndToEndTests.cpp b/src/backends/reference/test/RefEndToEndTests.cpp index 330f406265..802167a3a0 100644 --- a/src/backends/reference/test/RefEndToEndTests.cpp +++ b/src/backends/reference/test/RefEndToEndTests.cpp @@ -315,18 +315,22 @@ BOOST_AUTO_TEST_CASE(TrivialMin) BOOST_AUTO_TEST_CASE(RefEqualSimpleEndToEndTest) { - const std::vector expectedOutput({ 1, 1, 1, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 1 }); + const std::vector expectedOutput({ 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1 }); - ArithmeticSimpleEndToEnd(defaultBackends, LayerType::Equal, expectedOutput); + ArithmeticSimpleEndToEnd(defaultBackends, + LayerType::Equal, + expectedOutput); } BOOST_AUTO_TEST_CASE(RefGreaterSimpleEndToEndTest) { - const std::vector expectedOutput({ 0, 0, 0, 0, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0 }); + const std::vector expectedOutput({ 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0 }); - ArithmeticSimpleEndToEnd(defaultBackends, LayerType::Greater, expectedOutput); + ArithmeticSimpleEndToEnd(defaultBackends, + LayerType::Greater, + expectedOutput); } BOOST_AUTO_TEST_CASE(RefEqualSimpleEndToEndUint8Test) @@ -334,7 +338,9 @@ BOOST_AUTO_TEST_CASE(RefEqualSimpleEndToEndUint8Test) const std::vector expectedOutput({ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 }); - ArithmeticSimpleEndToEnd(defaultBackends, LayerType::Equal, expectedOutput); + ArithmeticSimpleEndToEnd(defaultBackends, + LayerType::Equal, + expectedOutput); } BOOST_AUTO_TEST_CASE(RefGreaterSimpleEndToEndUint8Test) @@ -342,23 +348,29 @@ BOOST_AUTO_TEST_CASE(RefGreaterSimpleEndToEndUint8Test) const std::vector expectedOutput({ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }); - ArithmeticSimpleEndToEnd(defaultBackends, LayerType::Greater, expectedOutput); + ArithmeticSimpleEndToEnd(defaultBackends, + LayerType::Greater, + expectedOutput); } BOOST_AUTO_TEST_CASE(RefEqualBroadcastEndToEndTest) { - const std::vector expectedOutput({ 1, 0, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0 }); + const std::vector expectedOutput({ 1, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0 }); - ArithmeticBroadcastEndToEnd(defaultBackends, LayerType::Equal, expectedOutput); + ArithmeticBroadcastEndToEnd(defaultBackends, + LayerType::Equal, + expectedOutput); } BOOST_AUTO_TEST_CASE(RefGreaterBroadcastEndToEndTest) { - const std::vector expectedOutput({ 0, 1, 0, 0, 0, 1, - 1, 1, 1, 1, 1, 1 }); + const std::vector expectedOutput({ 0, 1, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1 }); - ArithmeticBroadcastEndToEnd(defaultBackends, LayerType::Greater, expectedOutput); + ArithmeticBroadcastEndToEnd(defaultBackends, + LayerType::Greater, + expectedOutput); } BOOST_AUTO_TEST_CASE(RefEqualBroadcastEndToEndUint8Test) @@ -366,7 +378,9 @@ BOOST_AUTO_TEST_CASE(RefEqualBroadcastEndToEndUint8Test) const std::vector expectedOutput({ 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }); - ArithmeticBroadcastEndToEnd(defaultBackends, LayerType::Equal, expectedOutput); + ArithmeticBroadcastEndToEnd(defaultBackends, + LayerType::Equal, + expectedOutput); } BOOST_AUTO_TEST_CASE(RefGreaterBroadcastEndToEndUint8Test) @@ -374,7 +388,9 @@ BOOST_AUTO_TEST_CASE(RefGreaterBroadcastEndToEndUint8Test) const std::vector expectedOutput({ 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 }); - ArithmeticBroadcastEndToEnd(defaultBackends, LayerType::Greater, expectedOutput); + ArithmeticBroadcastEndToEnd(defaultBackends, + LayerType::Greater, + expectedOutput); } BOOST_AUTO_TEST_CASE(RefMergerEndToEndDim0Test) diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt index f95fda08d1..57e89fa456 100644 --- a/src/backends/reference/workloads/CMakeLists.txt +++ b/src/backends/reference/workloads/CMakeLists.txt @@ -40,6 +40,8 @@ list(APPEND armnnRefBackendWorkloads_sources RefBatchToSpaceNdFloat32Workload.hpp RefBatchToSpaceNdUint8Workload.cpp RefBatchToSpaceNdUint8Workload.hpp + RefComparisonWorkload.cpp + RefComparisonWorkload.hpp RefConstantWorkload.cpp RefConstantWorkload.hpp RefConvertFp16ToFp32Workload.cpp diff --git a/src/backends/reference/workloads/ElementwiseFunction.cpp b/src/backends/reference/workloads/ElementwiseFunction.cpp index cb8aa7089c..c8c25ef9e9 100644 --- a/src/backends/reference/workloads/ElementwiseFunction.cpp +++ b/src/backends/reference/workloads/ElementwiseFunction.cpp @@ -13,24 +13,26 @@ namespace armnn { -template -ElementwiseFunction::ElementwiseFunction(const TensorShape& inShape0, - const TensorShape& inShape1, - const TensorShape& outShape, - const float* inData0, - const float* inData1, - float* outData) +template +ElementwiseFunction::ElementwiseFunction(const TensorShape& inShape0, + const TensorShape& inShape1, + const TensorShape& outShape, + const dataTypeInput* inData0, + const dataTypeInput* inData1, + dataTypeOutput* outData) { BroadcastLoop(inShape0, inShape1, outShape).Unroll(Functor(), 0, inData0, inData1, outData); } } //namespace armnn -template struct armnn::ElementwiseFunction>; -template struct armnn::ElementwiseFunction>; -template struct armnn::ElementwiseFunction>; -template struct armnn::ElementwiseFunction>; -template struct armnn::ElementwiseFunction>; -template struct armnn::ElementwiseFunction>; -template struct armnn::ElementwiseFunction>; -template struct armnn::ElementwiseFunction>; +template struct armnn::ElementwiseFunction, float, float>; +template struct armnn::ElementwiseFunction, float, float>; +template struct armnn::ElementwiseFunction, float, float>; +template struct armnn::ElementwiseFunction, float, float>; +template struct armnn::ElementwiseFunction, float, float>; +template struct armnn::ElementwiseFunction, float, float>; +template struct armnn::ElementwiseFunction, float ,uint8_t>; +template struct armnn::ElementwiseFunction, uint8_t, uint8_t>; +template struct armnn::ElementwiseFunction, float, uint8_t>; +template struct armnn::ElementwiseFunction, uint8_t, uint8_t>; diff --git a/src/backends/reference/workloads/ElementwiseFunction.hpp b/src/backends/reference/workloads/ElementwiseFunction.hpp index 0ac136466c..8099f3279a 100644 --- a/src/backends/reference/workloads/ElementwiseFunction.hpp +++ b/src/backends/reference/workloads/ElementwiseFunction.hpp @@ -10,15 +10,15 @@ namespace armnn { -template +template struct ElementwiseFunction { ElementwiseFunction(const TensorShape& inShape0, const TensorShape& inShape1, const TensorShape& outShape, - const float* inData0, - const float* inData1, - float* outData); + const dataTypeInput* inData0, + const dataTypeInput* inData1, + dataTypeOutput* outData); }; } //namespace armnn diff --git a/src/backends/reference/workloads/RefComparisonWorkload.cpp b/src/backends/reference/workloads/RefComparisonWorkload.cpp new file mode 100644 index 0000000000..fe517ff51a --- /dev/null +++ b/src/backends/reference/workloads/RefComparisonWorkload.cpp @@ -0,0 +1,65 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "RefComparisonWorkload.hpp" +#include "ElementwiseFunction.hpp" +#include "RefWorkloadUtils.hpp" +#include "Profiling.hpp" +#include + +namespace armnn { + +template +void RefFloat32ComparisonWorkload::ExecuteImpl(const char* debugString) const +{ + ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, debugString); + + auto data = BaseFloat32ComparisonWorkload::GetData(); + const TensorShape& inShape0 = GetTensorInfo(data.m_Inputs[0]).GetShape(); + const TensorShape& inShape1 = GetTensorInfo(data.m_Inputs[1]).GetShape(); + const TensorShape& outputShape = GetTensorInfo(data.m_Outputs[0]).GetShape(); + + const float* inData0 = GetInputTensorDataFloat(0, data); + const float* inData1 = GetInputTensorDataFloat(1, data); + uint8_t* outData = GetOutputTensorData(0, data); + + ElementwiseFunction(inShape0, + inShape1, + outputShape, + inData0, + inData1, + outData); + +} + +template +void RefUint8ComparisonWorkload::ExecuteImpl(const char* debugString) const +{ + ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, debugString); + + auto data = BaseUint8ComparisonWorkload::GetData(); + const TensorShape& inputInfo0 = GetTensorInfo(data.m_Inputs[0]).GetShape(); + const TensorShape& inputInfo1 = GetTensorInfo(data.m_Inputs[1]).GetShape(); + const TensorShape& outputShape = GetTensorInfo(data.m_Outputs[0]).GetShape(); + + const uint8_t* inData0 = GetInputTensorData(0, data); + const uint8_t* inData1 = GetInputTensorData(1, data); + uint8_t* outData = GetOutputTensorData(0, data); + + ElementwiseFunction(inputInfo0, + inputInfo1, + outputShape, + inData0, + inData1, + outData); +} + +} + +template class armnn::RefFloat32ComparisonWorkload>; +template class armnn::RefUint8ComparisonWorkload>; + +template class armnn::RefFloat32ComparisonWorkload>; +template class armnn::RefUint8ComparisonWorkload>; diff --git a/src/backends/reference/workloads/RefComparisonWorkload.hpp b/src/backends/reference/workloads/RefComparisonWorkload.hpp new file mode 100644 index 0000000000..524d20625a --- /dev/null +++ b/src/backends/reference/workloads/RefComparisonWorkload.hpp @@ -0,0 +1,92 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include +#include +#include +#include "StringMapping.hpp" + +namespace armnn +{ + +template +class RefComparisonWorkload +{ + // Needs specialization. The default is empty on purpose. +}; + +template +class RefFloat32ComparisonWorkload : public BaseFloat32ComparisonWorkload +{ +public: + using BaseFloat32ComparisonWorkload::BaseFloat32ComparisonWorkload; + void ExecuteImpl(const char * debugString) const; +}; + +template +class RefComparisonWorkload + : public RefFloat32ComparisonWorkload +{ +public: + using RefFloat32ComparisonWorkload::RefFloat32ComparisonWorkload; + + virtual void Execute() const override + { + using Parent = RefFloat32ComparisonWorkload; + Parent::ExecuteImpl(StringMapping::Instance().Get(DebugString)); + } +}; + +template +class RefUint8ComparisonWorkload : public BaseUint8ComparisonWorkload +{ +public: + using BaseUint8ComparisonWorkload::BaseUint8ComparisonWorkload; + void ExecuteImpl(const char * debugString) const; +}; + +template +class RefComparisonWorkload + : public RefUint8ComparisonWorkload +{ +public: + using RefUint8ComparisonWorkload::RefUint8ComparisonWorkload; + + virtual void Execute() const override + { + using Parent = RefUint8ComparisonWorkload; + Parent::ExecuteImpl(StringMapping::Instance().Get(DebugString)); + } +}; + +using RefEqualFloat32Workload = + RefComparisonWorkload, + DataType::Float32, + EqualQueueDescriptor, + StringMapping::RefEqualWorkload_Execute>; + +using RefEqualUint8Workload = + RefComparisonWorkload, + DataType::QuantisedAsymm8, + EqualQueueDescriptor, + StringMapping::RefEqualWorkload_Execute>; + +using RefGreaterFloat32Workload = + RefComparisonWorkload, + DataType::Float32, + GreaterQueueDescriptor, + StringMapping::RefGreaterWorkload_Execute>; + +using RefGreaterUint8Workload = + RefComparisonWorkload, + DataType::QuantisedAsymm8, + GreaterQueueDescriptor, + StringMapping::RefGreaterWorkload_Execute>; +} // armnn diff --git a/src/backends/reference/workloads/RefElementwiseWorkload.cpp b/src/backends/reference/workloads/RefElementwiseWorkload.cpp index 13d6e70a96..c9b93c8524 100644 --- a/src/backends/reference/workloads/RefElementwiseWorkload.cpp +++ b/src/backends/reference/workloads/RefElementwiseWorkload.cpp @@ -26,7 +26,7 @@ void BaseFloat32ElementwiseWorkload::ExecuteImpl(cons const float* inData1 = GetInputTensorDataFloat(1, data); float* outData = GetOutputTensorDataFloat(0, data); - ElementwiseFunction(inShape0, inShape1, outShape, inData0, inData1, outData); + ElementwiseFunction(inShape0, inShape1, outShape, inData0, inData1, outData); } template @@ -44,12 +44,12 @@ void BaseUint8ElementwiseWorkload::ExecuteImpl(const std::vector results(outputInfo.GetNumElements()); - ElementwiseFunction(inputInfo0.GetShape(), - inputInfo1.GetShape(), - outputInfo.GetShape(), - dequant0.data(), - dequant1.data(), - results.data()); + ElementwiseFunction(inputInfo0.GetShape(), + inputInfo1.GetShape(), + outputInfo.GetShape(), + dequant0.data(), + dequant1.data(), + results.data()); Quantize(GetOutputTensorDataU8(0, data), results.data(), outputInfo); } @@ -73,9 +73,3 @@ template class armnn::BaseUint8ElementwiseWorkload>; template class armnn::BaseUint8ElementwiseWorkload>; - -template class armnn::BaseFloat32ElementwiseWorkload>; -template class armnn::BaseUint8ElementwiseWorkload>; - -template class armnn::BaseFloat32ElementwiseWorkload>; -template class armnn::BaseUint8ElementwiseWorkload>; diff --git a/src/backends/reference/workloads/RefElementwiseWorkload.hpp b/src/backends/reference/workloads/RefElementwiseWorkload.hpp index 6dd6865f53..a5ff376673 100644 --- a/src/backends/reference/workloads/RefElementwiseWorkload.hpp +++ b/src/backends/reference/workloads/RefElementwiseWorkload.hpp @@ -144,28 +144,4 @@ using RefMinimumUint8Workload = DataType::QuantisedAsymm8, MinimumQueueDescriptor, StringMapping::RefMinimumWorkload_Execute>; - -using RefEqualFloat32Workload = - RefElementwiseWorkload, - DataType::Float32, - EqualQueueDescriptor, - StringMapping::RefEqualWorkload_Execute>; - -using RefEqualUint8Workload = - RefElementwiseWorkload, - DataType::QuantisedAsymm8, - EqualQueueDescriptor, - StringMapping::RefEqualWorkload_Execute>; - -using RefGreaterFloat32Workload = - RefElementwiseWorkload, - DataType::Float32, - GreaterQueueDescriptor, - StringMapping::RefGreaterWorkload_Execute>; - -using RefGreaterUint8Workload = - RefElementwiseWorkload, - DataType::QuantisedAsymm8, - GreaterQueueDescriptor, - StringMapping::RefGreaterWorkload_Execute>; } // armnn diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp index 1cbceb366b..d9f4dbb342 100644 --- a/src/backends/reference/workloads/RefWorkloads.hpp +++ b/src/backends/reference/workloads/RefWorkloads.hpp @@ -60,3 +60,4 @@ #include "RefBatchToSpaceNdFloat32Workload.hpp" #include "RefDebugWorkload.hpp" #include "RefRsqrtFloat32Workload.hpp" +#include "RefComparisonWorkload.hpp" -- cgit v1.2.1