diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | docs/05_01_parsers.dox | 1 | ||||
-rw-r--r-- | src/armnn/layers/BroadcastToLayer.cpp | 1 | ||||
-rw-r--r-- | src/armnn/optimizations/DeleteBroadcastTo.hpp | 3 | ||||
-rw-r--r-- | src/armnnTfLiteParser/TfLiteParser.cpp | 61 | ||||
-rw-r--r-- | src/armnnTfLiteParser/TfLiteParser.hpp | 1 | ||||
-rw-r--r-- | src/armnnTfLiteParser/test/BroadcastTo.cpp | 508 | ||||
-rw-r--r-- | src/backends/backendsCommon/test/BroadcastToEndToEndTestImpl.hpp | 39 | ||||
-rw-r--r-- | src/backends/reference/test/RefEndToEndTests.cpp | 23 |
9 files changed, 627 insertions, 11 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index bcfb8cf6d2..a89e3fd4f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -682,6 +682,7 @@ if(BUILD_UNIT_TESTS) src/armnnTfLiteParser/test/AvgPool2D.cpp src/armnnTfLiteParser/test/BatchMatMul.cpp src/armnnTfLiteParser/test/BatchToSpaceND.cpp + src/armnnTfLiteParser/test/BroadcastTo.cpp src/armnnTfLiteParser/test/Cast.cpp src/armnnTfLiteParser/test/Comparison.cpp src/armnnTfLiteParser/test/Concatenation.cpp diff --git a/docs/05_01_parsers.dox b/docs/05_01_parsers.dox index f92504b389..4454f44218 100644 --- a/docs/05_01_parsers.dox +++ b/docs/05_01_parsers.dox @@ -123,6 +123,7 @@ The Arm NN SDK TensorFlow Lite parser currently supports the following operators - ARG_MIN - AVERAGE_POOL_2D, Supported Fused Activation: RELU , RELU6 , TANH, NONE - BATCH_TO_SPACE +- BROADCAST_TO - CAST - CEIL - CONCATENATION, Supported Fused Activation: RELU , RELU6 , TANH, NONE diff --git a/src/armnn/layers/BroadcastToLayer.cpp b/src/armnn/layers/BroadcastToLayer.cpp index 252aa46de0..26a90eefed 100644 --- a/src/armnn/layers/BroadcastToLayer.cpp +++ b/src/armnn/layers/BroadcastToLayer.cpp @@ -6,7 +6,6 @@ #include "BroadcastToLayer.hpp" #include "LayerCloneBase.hpp" - #include <armnn/TypesUtils.hpp> #include <armnn/backends/WorkloadData.hpp> #include <armnn/backends/WorkloadFactory.hpp> diff --git a/src/armnn/optimizations/DeleteBroadcastTo.hpp b/src/armnn/optimizations/DeleteBroadcastTo.hpp index 9ea20907df..38396c1a9c 100644 --- a/src/armnn/optimizations/DeleteBroadcastTo.hpp +++ b/src/armnn/optimizations/DeleteBroadcastTo.hpp @@ -20,11 +20,14 @@ public: { if(layer.GetType() == LayerType::BroadcastTo) { + TensorInfo info = layer.GetOutputSlot(0).GetTensorInfo(); Layer& next = layer.GetOutputSlot(0).GetConnection(0)->GetOwningLayer(); if (next.GetType() == LayerType::ElementwiseBinary) { Layer& connectedLayer = layer.GetInputSlots()[0].GetConnectedOutputSlot()->GetOwningLayer(); + auto tensorInfo = connectedLayer.GetOutputSlot().GetTensorInfo(); layer.GetOutputSlot().MoveAllConnections(connectedLayer.GetOutputSlot()); + connectedLayer.GetOutputSlot().GetOutputHandler().SetTensorInfo(tensorInfo); } } } diff --git a/src/armnnTfLiteParser/TfLiteParser.cpp b/src/armnnTfLiteParser/TfLiteParser.cpp index 052aac6101..3f4f0d811f 100644 --- a/src/armnnTfLiteParser/TfLiteParser.cpp +++ b/src/armnnTfLiteParser/TfLiteParser.cpp @@ -750,6 +750,7 @@ TfLiteParserImpl::TfLiteParserImpl(const Optional<ITfLiteParser::TfLiteParserOpt m_ParserFunctions[tflite::BuiltinOperator_AVERAGE_POOL_2D] = &TfLiteParserImpl::ParseAveragePool2D; m_ParserFunctions[tflite::BuiltinOperator_BATCH_TO_SPACE_ND] = &TfLiteParserImpl::ParseBatchToSpaceND; m_ParserFunctions[tflite::BuiltinOperator_BATCH_MATMUL] = &TfLiteParserImpl::ParseBatchMatMul; + m_ParserFunctions[tflite::BuiltinOperator_BROADCAST_TO] = &TfLiteParserImpl::ParseBroadcastTo; m_ParserFunctions[tflite::BuiltinOperator_CEIL] = &TfLiteParserImpl::ParseCeil; m_ParserFunctions[tflite::BuiltinOperator_CAST] = &TfLiteParserImpl::ParseCast; m_ParserFunctions[tflite::BuiltinOperator_CONCATENATION] = &TfLiteParserImpl::ParseConcatenation; @@ -1894,6 +1895,66 @@ void TfLiteParserImpl::ParseBatchToSpaceND(size_t subgraphIndex, size_t operator RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]}); } +void TfLiteParserImpl::ParseBroadcastTo(size_t subgraphIndex, size_t operatorIndex) +{ + CHECK_MODEL(m_Model, subgraphIndex, operatorIndex); + + auto inputs = GetInputs(m_Model, subgraphIndex, operatorIndex); + CHECK_VALID_SIZE(inputs.size(), 2); + + auto outputs = GetOutputs(m_Model, subgraphIndex, operatorIndex); + CHECK_VALID_SIZE(outputs.size(), 1); + + TensorInfo inputTensorInfo = ToTensorInfo(inputs[0]); + TensorInfo shapeTensorInfo = ToTensorInfo(inputs[1]); + TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]); + + auto layerName = fmt::format("Broadcast_to:{}:{}", subgraphIndex, operatorIndex); + + BroadcastToDescriptor descriptor; + + auto shapeBufferPtr = GetBuffer(m_Model, inputs[1]->buffer); + if (shapeBufferPtr != nullptr) + { + std::vector<unsigned int> targetShape; + unsigned int numElement = shapeTensorInfo.GetNumElements(); + auto shapeData = reinterpret_cast<const int32_t*>(shapeBufferPtr->data.data()); + if (shapeData) + { + for (unsigned int i = 0; i < numElement; ++i) + { + targetShape.push_back(armnn::numeric_cast<unsigned int>(shapeData[i])); + } + descriptor.m_BroadcastToShape = TensorShape(numElement, targetShape.data()); + } + /// get dataShape from outputShape if missing + else + { + if(outputTensorInfo.GetShape().GetNumElements() <= 1) + { + ARMNN_THROW_PARSE_EXCEPTION("For Broadcast_to layer, " + "data and output shape are not found in the buffer."); + } + descriptor.m_BroadcastToShape = outputTensorInfo.GetShape(); + } + } + else + { + ARMNN_THROW_PARSE_EXCEPTION("For Broadcast_to layer, Shape data was not found in the buffer."); + } + + IConnectableLayer* layer = m_Network->AddBroadcastToLayer(descriptor, layerName.c_str()); + ARMNN_ASSERT(layer != nullptr); + + layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + + auto inputTensorIndexes = AsUnsignedVector(GetInputTensorIds(m_Model, subgraphIndex, operatorIndex)); + RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]}); + + auto outputTensorIndexes = AsUnsignedVector(GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex)); + RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]}); +} + void TfLiteParserImpl::ParseL2Normalization(size_t subgraphIndex, size_t operatorIndex) { CHECK_MODEL(m_Model, subgraphIndex, operatorIndex); diff --git a/src/armnnTfLiteParser/TfLiteParser.hpp b/src/armnnTfLiteParser/TfLiteParser.hpp index e7f265915a..f0c7ddefb9 100644 --- a/src/armnnTfLiteParser/TfLiteParser.hpp +++ b/src/armnnTfLiteParser/TfLiteParser.hpp @@ -117,6 +117,7 @@ private: void ParseAveragePool2D(size_t subgraphIndex, size_t operatorIndex); void ParseBatchMatMul(size_t subgraphIndex, size_t operatorIndex); void ParseBatchToSpaceND(size_t subgraphIndex, size_t operatorIndex); + void ParseBroadcastTo(size_t subgraphIndex, size_t operatorIndex); void ParseCast(size_t subgraphIndex, size_t operatorIndex); void ParseCeil(size_t subgraphIndex, size_t operatorIndex); void ParseComparison(size_t subgraphIndex, size_t operatorIndex, armnn::ComparisonOperation comparisonOperation); diff --git a/src/armnnTfLiteParser/test/BroadcastTo.cpp b/src/armnnTfLiteParser/test/BroadcastTo.cpp new file mode 100644 index 0000000000..9a5d6c0ba8 --- /dev/null +++ b/src/armnnTfLiteParser/test/BroadcastTo.cpp @@ -0,0 +1,508 @@ +// +// Copyright © 2023 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "ParserFlatbuffersFixture.hpp" + +TEST_SUITE("TensorflowLiteParser_BroadcastTo") +{ +struct BroadcastToFixture : public ParserFlatbuffersFixture +{ + explicit BroadcastToFixture(const std::string& inputShape1, + const std::string& inputShape2, + const std::string& shapeShape, + const std::string& outputBroadcastToShape, + const std::string& outputShape, + const std::string& shapeData, + const bool checkThrows, + const std::string& scale = "1.0", + const std::string& offset = "0") + { + m_JsonString = R"( + { + "version": 3, + "operator_codes": [ + { + "deprecated_builtin_code": 127, + "version": 2, + "builtin_code": "BROADCAST_TO" + }, + { + "version": 1, + "builtin_code": "MUL" + } + ], + "subgraphs": [ + { + "tensors": [ + { + "shape": )" + inputShape1 + R"(, + "type": "FLOAT32", + "buffer": 1, + "name": "inputTensor1", + "quantization":{ + "min": [ 0.0 ], + "max": [ 255.0 ], + "scale": [ )" + scale + R"( ], + "zero_point": [ )" + offset + R"( ], + }, + "is_variable": false, + "shape_signature": [ + -1, + 3 + ], + "has_rank": true + }, + { + "shape": )" + inputShape2 + R"(, + "type": "FLOAT32", + "buffer": 2, + "name": "inputTensor2", + "quantization": { + "min": [ 0.0 ], + "max": [ 255.0 ], + "scale": [ )" + scale + R"( ], + "zero_point": [ )" + offset + R"( ], + }, + "is_variable": false, + "shape_signature": [ + -1, + 3 + ], + "has_rank": true + }, + { + "shape": )" + shapeShape + R"(, + "type": "INT32", + "buffer": 3, + "name": "shape", + "quantization": { + "details_type": "NONE", + "quantized_dimension": 0 + }, + "is_variable": false, + "shape_signature": [ + -1 + ], + "has_rank": true + }, + { + "shape": )" + outputBroadcastToShape + R"(, + "type": "FLOAT32", + "buffer": 4, + "name": "model/tf.broadcast_to/BroadcastTo", + "quantization": { + "min": [ 0.0 ], + "max": [ 255.0 ], + "scale": [ )" + scale + R"( ], + "zero_point": [ )" + offset + R"( ], + }, + "is_variable": false, + "has_rank": false + }, + { + "shape": )" + outputShape + R"(, + "type": "FLOAT32", + "buffer": 5, + "name": "outputTensor", + "quantization": { + "min": [ 0.0 ], + "max": [ 255.0 ], + "scale": [ )" + scale + R"( ], + "zero_point": [ )" + offset + R"( ], + }, + "is_variable": false, + "has_rank": false + } + ], + "inputs": [ + 0, + 1, + 2 + ], + "outputs": [ + 4 + ], + "operators": [ + { + "opcode_index": 0, + "inputs": [ + 0, + 2 + ], + "outputs": [ + 3 + ], + "builtin_options_type": "NONE", + "custom_options_format": "FLEXBUFFERS" + }, + { + "opcode_index": 1, + "inputs": [ + 1, + 3 + ], + "outputs": [ + 4 + ], + "builtin_options_type": "MulOptions", + "builtin_options": { + "fused_activation_function": "NONE" + }, + "custom_options_format": "FLEXBUFFERS" + } + ], + "name": "main" + } + ], + "description": "MLIR Converted.", + "buffers": [ + { + }, + { + }, + { + }, + { + )" + shapeData + R"( + }, + { + }, + { + }, + { + }, + { + } + ], + "metadata": [ + { + "name": "min_runtime_version", + "buffer": 6 + }, + { + "name": "CONVERSION_METADATA", + "buffer": 7 + } + ], + "signature_defs": [ + + ] + } + )"; + if(checkThrows) + { + CHECK_THROWS_AS(Setup(), armnn::ParseException); + } + else + { + Setup(); + } + } +}; + +struct BroadcastToSimpleFixture : public ParserFlatbuffersFixture +{ + explicit BroadcastToSimpleFixture(const std::string& inputShape, + const std::string& shapeShape, + const std::string& outputShape, + const std::string& shapeData, + const std::string& dataType, + const std::string& scale = "1.0", + const std::string& offset = "0") + { + m_JsonString = R"( + { + "version": 3, + "operator_codes": [ + { + "deprecated_builtin_code": 127, + "version": 2, + "builtin_code": "BROADCAST_TO" + } + ], + "subgraphs": [ + { + "tensors": [ + { + "shape": )" + inputShape + R"(, + "type": )" + dataType + R"(, + "buffer": 1, + "name": "input1", + "quantization": { + "min": [ 0.0 ], + "max": [ 255.0 ], + "scale": [ )" + scale + R"( ], + "zero_point": [ )" + offset + R"( ], + }, + "is_variable": false, + "shape_signature": [ + -1, + 3 + ], + "has_rank": true + }, + { + "shape": )" + shapeShape + R"(, + "type": "INT32", + "buffer": 2, + "name": "shape", + "quantization": { + "details_type": "NONE", + "quantized_dimension": 0 + }, + "is_variable": false, + "shape_signature": [ + -1 + ], + "has_rank": true + }, + { + "shape": )" + outputShape + R"(, + "type": )" + dataType + R"(, + "buffer": 3, + "name": "Identity", + "quantization": { + "min": [ 0.0 ], + "max": [ 255.0 ], + "scale": [ )" + scale + R"( ], + "zero_point": [ )" + offset + R"( ], + }, + "is_variable": false, + "has_rank": false + } + ], + "inputs": [ + 0, + 1 + ], + "outputs": [ + 2 + ], + "operators": [ + { + "opcode_index": 0, + "inputs": [ + 0, + 1 + ], + "outputs": [ + 2 + ], + "builtin_options_type": "NONE", + "custom_options_format": "FLEXBUFFERS" + } + ], + "name": "main" + } + ], + "description": "MLIR Converted.", + "buffers": [ + { + }, + { + }, + { + "data": )" + shapeData + R"(, + }, + { + }, + { + }, + { + } + ], + "metadata": [ + { + "name": "min_runtime_version", + "buffer": 4 + }, + { + "name": "CONVERSION_METADATA", + "buffer": 5 + } + ], + "signature_defs": [ + + ] + } + )"; + SetupSingleInputSingleOutput("inputTensor", "outputTensor"); + } +}; + +struct SimpleBroadcastToSimpleFixtureFloat32 : public BroadcastToSimpleFixture +{ + SimpleBroadcastToSimpleFixtureFloat32() : BroadcastToSimpleFixture("[1, 4]", + "[2]", + "[3, 4]", + "[3, 0, 0, 0, 4, 0, 0, 0]", + "FLOAT32") {} +}; + +TEST_CASE_FIXTURE(SimpleBroadcastToSimpleFixtureFloat32, "SimpleParseBroadcastToFloat32") +{ + RunTest<2, armnn::DataType::Float32, armnn::DataType::Float32> + (0, {{ "input1", { 1.f, 2.f, 3.f, 4.f }}}, + {{ "Identity", { 1.f, 2.f, 3.f, 4.f, + 1.f, 2.f, 3.f, 4.f, + 1.f, 2.f, 3.f, 4.f}}}); + +} +struct SimpleBroadcastToSimpleFixtureSigned32 : public BroadcastToSimpleFixture +{ + SimpleBroadcastToSimpleFixtureSigned32() : BroadcastToSimpleFixture("[1, 4]", + "[2]", + "[3, 4]", + "[3, 0, 0, 0, 4, 0, 0, 0]", + "INT32") {} +}; + +TEST_CASE_FIXTURE(SimpleBroadcastToSimpleFixtureSigned32, "SimpleParseBroadcastToSigned32") +{ + RunTest<2, armnn::DataType::Signed32, armnn::DataType::Signed32> + (0, {{ "input1", { 1, 2, 3, -4 }}}, + {{ "Identity", { 1, 2, 3, -4, + 1, 2, 3, -4, + 1, 2, 3, -4}}}); + +} + +struct SimpleBroadcastToSimpleFixtureQAsymmU8 : public BroadcastToSimpleFixture +{ + SimpleBroadcastToSimpleFixtureQAsymmU8() : BroadcastToSimpleFixture("[1, 4]", + "[2]", + "[3, 4]", + "[3, 0, 0, 0, 4, 0, 0, 0]", + "UINT8") {} +}; + +TEST_CASE_FIXTURE(SimpleBroadcastToSimpleFixtureQAsymmU8, "SimpleParseBroadcastToQAsymmU8") +{ + RunTest<2, armnn::DataType::QAsymmU8, armnn::DataType::QAsymmU8> + (0, {{ "input1", { 1, 2, 3, 4 }}}, + {{ "Identity", { 1, 2, 3, 4, + 1, 2, 3, 4, + 1, 2, 3, 4}}}); + +} + +struct SimpleBroadcastToFixture : public BroadcastToFixture +{ + SimpleBroadcastToFixture() : BroadcastToFixture("[1, 4]", + "[3, 4]", + "[2]", + "[3, 4]", + "[3, 4]", + "\"data\":[3, 0, 0, 0, 4, 0, 0, 0]", + false) {} +}; + +TEST_CASE_FIXTURE(SimpleBroadcastToFixture, "ParseBroadcastTo") +{ + RunTest<2, armnn::DataType::Float32, armnn::DataType::Float32, armnn::DataType::Float32> + ( + 0, {{ "inputTensor1", { 1, 2, 3, 4 }}}, + {{"inputTensor2", {1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1}}}, + {{ "outputTensor", { 1, 2, 3, 4, + 1, 2, 3, 4, + 1, 2, 3, 4}}} + ); + +} + +struct DynamicBroadcastToFixture : public BroadcastToFixture +{ + DynamicBroadcastToFixture() : BroadcastToFixture("[1, 4]", + "[3, 4]", + "[2]", + "[3, 4]", + "[3, 4]", + "\"data\":[3, 0, 0, 0, 4, 0, 0, 0]", + false) {} +}; + +TEST_CASE_FIXTURE(DynamicBroadcastToFixture, "DynamicParseBroadcastTo") +{ + RunTest<2, armnn::DataType::Float32, armnn::DataType::Float32, armnn::DataType::Float32> + ( + 0, {{ "inputTensor1", { 1, 2, 3, 4 }}}, + {{"inputTensor2", {1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1}}}, + {{ "outputTensor", { 1, 2, 3, 4, + 1, 2, 3, 4, + 1, 2, 3, 4}}} + ); + +} + +struct DynamicBroadcastToFixtureNoOutputShape : public BroadcastToFixture +{ + DynamicBroadcastToFixtureNoOutputShape() : BroadcastToFixture("[1, 4]", + "[3, 4]", + "[2]", + "[]", + "[3, 4]", + "\"data\":[3, 0, 0, 0, 4, 0, 0, 0]", + false) {} +}; + +TEST_CASE_FIXTURE(DynamicBroadcastToFixtureNoOutputShape, "DynamicParseBroadcastToNoOutputShape") +{ + RunTest<2, armnn::DataType::Float32, armnn::DataType::Float32, armnn::DataType::Float32> + ( + 0, {{ "inputTensor1", { 1, 2, 3, 4 }}}, + {{"inputTensor2", {1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1}}}, + {{ "outputTensor", { 1, 2, 3, 4, + 1, 2, 3, 4, + 1, 2, 3, 4}}} + ); + +} + +struct DynamicBroadcastToFixtureNoData : public BroadcastToFixture +{ + DynamicBroadcastToFixtureNoData() : BroadcastToFixture("[1, 4]", + "[3, 4]", + "[2]", + "[3, 4]", + "[3, 4]", + "", + false) {} +}; + +TEST_CASE_FIXTURE(DynamicBroadcastToFixtureNoData, "DynamicParseBroadcastToNoData") +{ + RunTest<2, armnn::DataType::Float32, armnn::DataType::Float32, armnn::DataType::Float32> + ( + 0, {{ "inputTensor1", { 1, 2, 3, 4 }}}, + {{"inputTensor2", {1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1}}}, + {{ "outputTensor", { 1, 2, 3, 4, + 1, 2, 3, 4, + 1, 2, 3, 4}}} + ); + +} + +struct DynamicBroadcastToFixtureNoDataNoOutputShape : public BroadcastToFixture +{ + DynamicBroadcastToFixtureNoDataNoOutputShape() : BroadcastToFixture("[1, 4]", + "[3, 4]", + "[2]", + "[]", + "[3, 4]", + "", true) { } +}; + +TEST_CASE_FIXTURE(DynamicBroadcastToFixtureNoDataNoOutputShape, "DynamicParseBroadcastToNoDataNoOutputShape") +{ +} +}
\ No newline at end of file diff --git a/src/backends/backendsCommon/test/BroadcastToEndToEndTestImpl.hpp b/src/backends/backendsCommon/test/BroadcastToEndToEndTestImpl.hpp index 3b2c47fb94..f9de3b928f 100644 --- a/src/backends/backendsCommon/test/BroadcastToEndToEndTestImpl.hpp +++ b/src/backends/backendsCommon/test/BroadcastToEndToEndTestImpl.hpp @@ -87,7 +87,8 @@ namespace } template <armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>> - void BroadcastToEndToEndElementWiseBinary(const std::vector<BackendId>& backends) + void BroadcastToEndToEndElementWiseBinary(const std::vector<BackendId>& backends, + const ElementwiseBinaryDescriptor& elementWiseDescriptor) { float qScale = 1.0f; int32_t qOffset = 0; @@ -114,17 +115,39 @@ namespace 1, 1, 1, 1 }, qScale, qOffset); - std::vector<T> expectedOutputData = armnnUtils::QuantizedVector<T>({ - 65, 144, 91, 161, - 65, 144, 91, 161, - 65, 144, 91, 161, - 65, 144, 91, 161 - }, qScale, qOffset); + std::vector<T> expectedOutputData; + if (elementWiseDescriptor.m_Operation == BinaryOperation::Mul || + elementWiseDescriptor.m_Operation == BinaryOperation::Div) { + expectedOutputData = armnnUtils::QuantizedVector<T>({ + 65, 144, 91, 161, + 65, 144, 91, 161, + 65, 144, 91, 161, + 65, 144, 91, 161 + }, qScale, qOffset); + } + else if (elementWiseDescriptor.m_Operation == BinaryOperation::Add) + { + expectedOutputData = armnnUtils::QuantizedVector<T>({ + 66, 145, 92, 162, + 66, 145, 92, 162, + 66, 145, 92, 162, + 66, 145, 92, 162 + }, qScale, qOffset); + } + else if (elementWiseDescriptor.m_Operation == BinaryOperation::Sub) + { + expectedOutputData = armnnUtils::QuantizedVector<T>({ + 64, 143, 90, 160, + 64, 143, 90, 160, + 64, 143, 90, 160, + 64, 143, 90, 160 + }, qScale, qOffset); + } auto descriptor = armnn::BroadcastToDescriptor(armnn::TensorShape({ 4, 4 })); CHECK(descriptor.m_BroadcastToShape == outputTensorShape); INetworkPtr network = CreateBroadcastToNetworkWithElementWiseBinary(descriptor, - BinaryOperation::Mul, + elementWiseDescriptor, inputInfo, inputInfoElementWise, outputInfo); diff --git a/src/backends/reference/test/RefEndToEndTests.cpp b/src/backends/reference/test/RefEndToEndTests.cpp index e503d3fb7f..13995f5c6f 100644 --- a/src/backends/reference/test/RefEndToEndTests.cpp +++ b/src/backends/reference/test/RefEndToEndTests.cpp @@ -1736,8 +1736,27 @@ TEST_CASE("RefBroadcastToEndToEndFloat32") BroadcastToEndToEnd<armnn::DataType::Float32>(defaultBackends); } -TEST_CASE("RefBroadcastToEndToEndWithElementWiseBinaryFloat32") +TEST_CASE("RefBroadcastToEndToEndWithMultiplicationFloat32") { - BroadcastToEndToEndElementWiseBinary<armnn::DataType::Float32>(defaultBackends); + BroadcastToEndToEndElementWiseBinary<armnn::DataType::Float32>(defaultBackends, + BinaryOperation::Mul); +} + +TEST_CASE("RefBroadcastToEndToEndWithDivisionFloat32") +{ + BroadcastToEndToEndElementWiseBinary<armnn::DataType::Float32>(defaultBackends, + BinaryOperation::Div); +} + +TEST_CASE("RefBroadcastToEndToEndWithAdditionFloat32") +{ + BroadcastToEndToEndElementWiseBinary<armnn::DataType::Float32>(defaultBackends, + BinaryOperation::Add); +} + +TEST_CASE("RefBroadcastToEndToEndWithSubtractionFloat32") +{ + BroadcastToEndToEndElementWiseBinary<armnn::DataType::Float32>(defaultBackends, + BinaryOperation::Sub); } } |