From 363b572b61f7a32e92cde51478d7556ce43db56f Mon Sep 17 00:00:00 2001 From: Mike Kelly Date: Wed, 11 Oct 2023 14:25:50 +0100 Subject: Revert "Revert "MLCE-1093 Reshape and concat invalid results"" This reverts commit 008270f8c1359a7d62c2f881326b4d3f0d8b7b56. Signed-off-by: Mike Kelly Change-Id: If8f5151aa349ff3834f03391e813669e5c51ed66 --- delegate/classic/src/Split.hpp | 4 + delegate/classic/src/Unpack.hpp | 2 + delegate/opaque/src/Split.hpp | 4 + delegate/opaque/src/Unpack.hpp | 2 + src/armnn/Descriptors.cpp | 8 + src/armnnDeserializer/Deserializer.cpp | 5 + src/armnnSerializer/Serializer.cpp | 4 +- src/armnnSerializer/test/SerializerTests.cpp | 1 + src/armnnTfLiteParser/TfLiteParser.cpp | 8 +- src/backends/aclCommon/ArmComputeUtils.hpp | 16 +- .../test/layerTests/SplitterTestImpl.cpp | 49 +++- src/backends/cl/ClTensorHandleFactory.cpp | 2 +- src/backends/neon/NeonTensorHandleFactory.cpp | 2 +- src/backends/neon/test/NeonTensorHandleTests.cpp | 283 +-------------------- 14 files changed, 98 insertions(+), 292 deletions(-) diff --git a/delegate/classic/src/Split.hpp b/delegate/classic/src/Split.hpp index aaa610259f..57b7f8074e 100644 --- a/delegate/classic/src/Split.hpp +++ b/delegate/classic/src/Split.hpp @@ -107,6 +107,8 @@ TfLiteStatus VisitSplitOperator(DelegateData& delegateData, splitterDimSizes[splitDim] /= numSplits; armnn::SplitterDescriptor splitDescriptor(numSplits, inputDimSize); + splitDescriptor.SetAxis(axis); + for (unsigned int j = 0; j < numSplits; ++j) { // Set the size of the views. @@ -301,6 +303,8 @@ TfLiteStatus VisitSplitVOperator(DelegateData& delegateData, } armnn::SplitterDescriptor splitDescriptor(numSplits, inputDimSize); + splitDescriptor.SetAxis(axis); + unsigned int accumSplit = 0; for (unsigned int j = 0; j < numSplits; ++j) { diff --git a/delegate/classic/src/Unpack.hpp b/delegate/classic/src/Unpack.hpp index 2cd32564c1..b3336ec990 100644 --- a/delegate/classic/src/Unpack.hpp +++ b/delegate/classic/src/Unpack.hpp @@ -96,6 +96,8 @@ TfLiteStatus VisitUnpackOperator(DelegateData& delegateData, unpackDimSizes[unpackAxis] /= unpackNum; armnn::SplitterDescriptor splitDesc(unpackNum, static_cast(unpackDimSizes.size())); + splitDesc.SetAxis(unpackAxis); + for (unsigned int j = 0; j < unpackNum; ++j) { // Set the size of the views. diff --git a/delegate/opaque/src/Split.hpp b/delegate/opaque/src/Split.hpp index 2dbfa602fb..199f46b126 100644 --- a/delegate/opaque/src/Split.hpp +++ b/delegate/opaque/src/Split.hpp @@ -134,6 +134,8 @@ TfLiteStatus VisitSplitOperator(DelegateData& delegateData, splitterDimSizes[splitDim] /= numSplits; armnn::SplitterDescriptor splitDescriptor(numSplits, inputDimSize); + splitDescriptor.SetAxis(axis); + for (int j = 0; j < numSplits; ++j) { // Set the size of the views. @@ -367,7 +369,9 @@ TfLiteStatus VisitSplitVOperator(DelegateData& delegateData, } armnn::SplitterDescriptor splitDescriptor(numSplits, inputDimSize); + splitDescriptor.SetAxis(axis); unsigned int accumSplit = 0; + for (int j = 0; j < numSplits; ++j) { unsigned int splitSize = armnn::numeric_cast(splitsTensorData[j]); diff --git a/delegate/opaque/src/Unpack.hpp b/delegate/opaque/src/Unpack.hpp index 0956d1688e..525529ff7b 100644 --- a/delegate/opaque/src/Unpack.hpp +++ b/delegate/opaque/src/Unpack.hpp @@ -96,6 +96,8 @@ TfLiteStatus VisitUnpackOperator(DelegateData& delegateData, unpackDimSizes[unpackAxis] /= unpackNum; armnn::SplitterDescriptor splitDesc(unpackNum, static_cast(unpackDimSizes.size())); + splitDesc.SetAxis(unpackAxis); + for (unsigned int j = 0; j < unpackNum; ++j) { // Set the size of the views. diff --git a/src/armnn/Descriptors.cpp b/src/armnn/Descriptors.cpp index e6374aea8f..5e4628bd77 100644 --- a/src/armnn/Descriptors.cpp +++ b/src/armnn/Descriptors.cpp @@ -216,12 +216,16 @@ void OriginsDescriptor::ReorderOrigins(unsigned int* newOrdering, unsigned int ViewsDescriptor::ViewsDescriptor() : m_Origins() , m_ViewSizes(nullptr) +, m_IsAxisSet(false) +, m_Axis(0) {} ViewsDescriptor::ViewsDescriptor(uint32_t numViews, uint32_t numDimensions /*= 4*/) : m_Origins(numViews, numDimensions) , m_ViewSizes(numViews > 0 && numDimensions > 0 ? new uint32_t *[numViews]() : nullptr) + , m_IsAxisSet(false) + , m_Axis(0) { if (m_ViewSizes) { @@ -236,6 +240,8 @@ ViewsDescriptor::ViewsDescriptor(const ViewsDescriptor& other) : m_Origins(other.m_Origins) , m_ViewSizes(other.GetNumViews() > 0 && other.GetNumDimensions() > 0 ? new uint32_t *[other.GetNumViews()]() : nullptr) + , m_IsAxisSet(other.m_IsAxisSet) + , m_Axis(other.m_Axis) { if (m_ViewSizes) { @@ -361,6 +367,8 @@ void swap(ViewsDescriptor& first, ViewsDescriptor& second) using std::swap; swap(first.m_Origins, second.m_Origins); swap(first.m_ViewSizes, second.m_ViewSizes); + swap(first.m_IsAxisSet, second.m_IsAxisSet); + swap(first.m_Axis, second.m_Axis); } void ViewsDescriptor::SetAxis(int32_t axis) diff --git a/src/armnnDeserializer/Deserializer.cpp b/src/armnnDeserializer/Deserializer.cpp index f455b1af0a..f27489f339 100644 --- a/src/armnnDeserializer/Deserializer.cpp +++ b/src/armnnDeserializer/Deserializer.cpp @@ -3263,6 +3263,11 @@ void IDeserializer::DeserializerImpl::ParseSplitter(GraphPtr graph, unsigned int } } + if (flatBufferViewsDescriptor->hasAxis()) + { + viewsDescriptor.SetAxis(flatBufferViewsDescriptor->axis()); + } + auto layerName = GetLayerName(graph, layerIndex); IConnectableLayer* layer = m_Network->AddSplitterLayer(viewsDescriptor, layerName.c_str()); diff --git a/src/armnnSerializer/Serializer.cpp b/src/armnnSerializer/Serializer.cpp index 0df675d1db..ef2ca48e04 100644 --- a/src/armnnSerializer/Serializer.cpp +++ b/src/armnnSerializer/Serializer.cpp @@ -1308,7 +1308,9 @@ void SerializerStrategy::SerializeSplitterLayer(const armnn::IConnectableLayer* // Create FlatBuffer ViewsDescriptor auto flatBufferViewsDescriptor = CreateViewsDescriptor(m_flatBufferBuilder, flatBufferOriginDescriptor, - m_flatBufferBuilder.CreateVector(flatBufferViewSizes)); + m_flatBufferBuilder.CreateVector(flatBufferViewSizes), + viewsDescriptor.HasAxis(), + viewsDescriptor.GetAxis()); // Create FlatBuffer BaseLayer auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Splitter); diff --git a/src/armnnSerializer/test/SerializerTests.cpp b/src/armnnSerializer/test/SerializerTests.cpp index b2590eaa42..bfe3fc6467 100644 --- a/src/armnnSerializer/test/SerializerTests.cpp +++ b/src/armnnSerializer/test/SerializerTests.cpp @@ -2644,6 +2644,7 @@ TEST_CASE("SerializeSplitter") desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]); } } + desc.SetAxis(1); const std::string layerName("splitter"); const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32); diff --git a/src/armnnTfLiteParser/TfLiteParser.cpp b/src/armnnTfLiteParser/TfLiteParser.cpp index 30875d5650..dcd385023b 100644 --- a/src/armnnTfLiteParser/TfLiteParser.cpp +++ b/src/armnnTfLiteParser/TfLiteParser.cpp @@ -4303,7 +4303,7 @@ void TfLiteParserImpl::ParseUnpack(size_t subgraphIndex, size_t operatorIndex) } splitDesc.SetViewOriginCoord(j, unpackAxis, unpackDimSizes[unpackAxis] * j); } - + splitDesc.SetAxis(unpackAxis); auto layerName = fmt::format("Unpack:{}:{}", subgraphIndex, operatorIndex); IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str()); @@ -4442,7 +4442,10 @@ void TfLiteParserImpl::ParseSplit(size_t subgraphIndex, size_t operatorIndex) } splitDesc.SetViewOriginCoord(j, splitDim, splitterDimSizes[splitDim] * j); } - + if (axisTensorInfo.GetNumElements() == 1) + { + splitDesc.SetAxis(axis); + } auto layerName = fmt::format("Split:{}:{}", subgraphIndex, operatorIndex); IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str()); @@ -4621,6 +4624,7 @@ void TfLiteParserImpl::ParseSplitV(size_t subgraphIndex, size_t operatorIndex) splitDesc.SetViewOriginCoord(j, splitDim, accumSplit); accumSplit += splitSize; } + splitDesc.SetAxis(axis); auto layerName = fmt::format("SplitV:{}:{}", subgraphIndex, operatorIndex); IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str()); diff --git a/src/backends/aclCommon/ArmComputeUtils.hpp b/src/backends/aclCommon/ArmComputeUtils.hpp index f466ab1777..5d424afa9a 100644 --- a/src/backends/aclCommon/ArmComputeUtils.hpp +++ b/src/backends/aclCommon/ArmComputeUtils.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -248,13 +249,20 @@ inline std::set ComputeSplitAxis(const armnn::SplitterDescriptor& unsigned int numDimensions = desc.GetNumDimensions(); std::set splitAxis; - for (unsigned int i = 0; i < numSplit; ++i) + if (desc.HasAxis()) { - for (unsigned int dimIdx = 0; dimIdx < numDimensions; ++dimIdx) + splitAxis.insert(armnnUtils::GetUnsignedAxis(desc.GetNumDimensions(), desc.GetAxis())); + } + else + { + for (unsigned int i = 0; i < numSplit; ++i) { - if (desc.GetViewSizes(i)[dimIdx] != input[dimIdx]) + for (unsigned int dimIdx = 0; dimIdx < numDimensions; ++dimIdx) { - splitAxis.insert(dimIdx); + if (desc.GetViewSizes(i)[dimIdx] != input[dimIdx]) + { + splitAxis.insert(dimIdx); + } } } } diff --git a/src/backends/backendsCommon/test/layerTests/SplitterTestImpl.cpp b/src/backends/backendsCommon/test/layerTests/SplitterTestImpl.cpp index 9e3d83c0f4..13483e5ebd 100644 --- a/src/backends/backendsCommon/test/layerTests/SplitterTestImpl.cpp +++ b/src/backends/backendsCommon/test/layerTests/SplitterTestImpl.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2017, 2023 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2019-2020,2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -199,11 +199,29 @@ std::vector> SplitterTestCommon( // Do the first split armnn::SplitterQueueDescriptor data; + data.m_Parameters = armnn::SplitterDescriptor(2, 3); + armnn::WorkloadInfo info; AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); AddOutputToWorkload(data, info, outputTensorInfo1, outputHandle1.get()); AddOutputToWorkload(data, info, outputTensorInfo2, outputHandle2.get()); + data.m_Parameters.SetViewSize(0, 0, outputChannels1); + data.m_Parameters.SetViewSize(0, 1, outputHeight1); + data.m_Parameters.SetViewSize(0, 2, outputWidth1); + + data.m_Parameters.SetViewSize(1, 0, outputChannels2); + data.m_Parameters.SetViewSize(1, 1, outputHeight2); + data.m_Parameters.SetViewSize(1, 2, outputWidth2); + + data.m_Parameters.SetViewOriginCoord(0, 0, 0); + data.m_Parameters.SetViewOriginCoord(0, 1, 0); + data.m_Parameters.SetViewOriginCoord(0, 2, 0); + + data.m_Parameters.SetViewOriginCoord(1, 0, 1); + data.m_Parameters.SetViewOriginCoord(1, 1, 0); + data.m_Parameters.SetViewOriginCoord(1, 2, 0); + data.m_ViewOrigins.push_back(window1); data.m_ViewOrigins.push_back(window2); @@ -224,11 +242,29 @@ std::vector> SplitterTestCommon( // Do the second split. armnn::SplitterQueueDescriptor data2; + data2.m_Parameters = armnn::SplitterDescriptor(2, 3); + armnn::WorkloadInfo info2; AddInputToWorkload(data2, info2, outputTensorInfo2, outputHandle2.get()); AddOutputToWorkload(data2, info2, outputTensorInfo3, outputHandle3.get()); AddOutputToWorkload(data2, info2, outputTensorInfo4, outputHandle4.get()); + data2.m_Parameters.SetViewSize(0, 0, outputChannels1); + data2.m_Parameters.SetViewSize(0, 1, outputHeight1); + data2.m_Parameters.SetViewSize(0, 2, outputWidth1); + + data2.m_Parameters.SetViewSize(1, 0, outputChannels2); + data2.m_Parameters.SetViewSize(1, 1, outputHeight2); + data2.m_Parameters.SetViewSize(1, 2, outputWidth1); + + data2.m_Parameters.SetViewOriginCoord(0, 0, 0); + data2.m_Parameters.SetViewOriginCoord(0, 1, 0); + data2.m_Parameters.SetViewOriginCoord(0, 2, 0); + + data2.m_Parameters.SetViewOriginCoord(1, 0, 1); + data2.m_Parameters.SetViewOriginCoord(1, 1, 0); + data2.m_Parameters.SetViewOriginCoord(1, 2, 0); + data2.m_ViewOrigins.push_back(window3); data2.m_ViewOrigins.push_back(window4); @@ -307,6 +343,17 @@ LayerTestResult CopyViaSplitterTestImpl( AddInputToWorkload(data, info, tensorInfo, inputHandle.get()); AddOutputToWorkload(data, info, tensorInfo, outputHandle.get()); + data.m_Parameters = armnn::SplitterDescriptor(1, 3); + data.m_Parameters.SetAxis(0); + + data.m_Parameters.SetViewSize(0, 0, 3); + data.m_Parameters.SetViewSize(0, 1, 6); + data.m_Parameters.SetViewSize(0, 2, 5); + + data.m_Parameters.SetViewOriginCoord(0, 0, 0); + data.m_Parameters.SetViewOriginCoord(0, 1, 0); + data.m_Parameters.SetViewOriginCoord(0, 2, 0); + data.m_ViewOrigins.push_back(window); std::unique_ptr workload = workloadFactory.CreateWorkload(armnn::LayerType::Splitter, diff --git a/src/backends/cl/ClTensorHandleFactory.cpp b/src/backends/cl/ClTensorHandleFactory.cpp index 82e41d3ff6..be3ca5e05a 100644 --- a/src/backends/cl/ClTensorHandleFactory.cpp +++ b/src/backends/cl/ClTensorHandleFactory.cpp @@ -103,7 +103,7 @@ const FactoryId& ClTensorHandleFactory::GetId() const bool ClTensorHandleFactory::SupportsSubTensors() const { - return true; + return false; } MemorySourceFlags ClTensorHandleFactory::GetExportFlags() const diff --git a/src/backends/neon/NeonTensorHandleFactory.cpp b/src/backends/neon/NeonTensorHandleFactory.cpp index ce3ce5c0d7..2597b5f28b 100644 --- a/src/backends/neon/NeonTensorHandleFactory.cpp +++ b/src/backends/neon/NeonTensorHandleFactory.cpp @@ -104,7 +104,7 @@ bool NeonTensorHandleFactory::SupportsInPlaceComputation() const bool NeonTensorHandleFactory::SupportsSubTensors() const { - return true; + return false; } MemorySourceFlags NeonTensorHandleFactory::GetExportFlags() const diff --git a/src/backends/neon/test/NeonTensorHandleTests.cpp b/src/backends/neon/test/NeonTensorHandleTests.cpp index c8e781b71d..a94e4dd187 100644 --- a/src/backends/neon/test/NeonTensorHandleTests.cpp +++ b/src/backends/neon/test/NeonTensorHandleTests.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2020 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2020-2021,2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #include @@ -89,81 +89,6 @@ TEST_CASE("NeonTensorHandleGetCapabilitiesPadding") CHECK(capabilities[0].m_Value); } -TEST_CASE("ConcatOnXorYSubTensorsNoPaddingRequiredTest") -{ - armnn::INetworkPtr net(armnn::INetwork::Create()); - - // Set up tensor infos - const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32); - const armnn::TensorInfo intermediateInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32); - const armnn::TensorInfo outputInfo = armnn::TensorInfo({2, 3, 4, 2}, armnn::DataType::Float32); - - armnn::ElementwiseUnaryDescriptor descriptor(armnn::UnaryOperation::Abs); - - // Create the network - armnn::IConnectableLayer* const input0Layer = net->AddInputLayer(0, "input_0"); - input0Layer->GetOutputSlot(0).SetTensorInfo(inputInfo); - armnn::IConnectableLayer* elementwiseUnaryLayer0 = net->AddElementwiseUnaryLayer(descriptor, "elementwiseUnary_0"); - elementwiseUnaryLayer0->GetOutputSlot(0).SetTensorInfo(intermediateInfo); - input0Layer->GetOutputSlot(0).Connect(elementwiseUnaryLayer0->GetInputSlot(0)); - - armnn::IConnectableLayer* const input1Layer = net->AddInputLayer(1, "input_1"); - input1Layer->GetOutputSlot(0).SetTensorInfo(inputInfo); - armnn::IConnectableLayer* elementwiseUnaryLayer1 = net->AddElementwiseUnaryLayer(descriptor, "elementwiseUnary_1"); - elementwiseUnaryLayer1->GetOutputSlot(0).SetTensorInfo(intermediateInfo); - input1Layer->GetOutputSlot(0).Connect(elementwiseUnaryLayer1->GetInputSlot(0)); - - std::array concatInputShapes = { intermediateInfo.GetShape(), intermediateInfo.GetShape() }; - armnn::IConnectableLayer* const concatLayer = net->AddConcatLayer(armnn::CreateDescriptorForConcatenation( - concatInputShapes.begin(), concatInputShapes.end(), 2), "concatenation"); - concatLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); - elementwiseUnaryLayer0->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0)); - elementwiseUnaryLayer1->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1)); - - armnn::IConnectableLayer* const outputLayer = net->AddOutputLayer(0, "output"); - concatLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - - armnn::IRuntime::CreationOptions options; - armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options)); - - std::vector backends = { armnn::Compute::CpuAcc }; - armnn::IOptimizedNetworkPtr optimizedNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec()); - - const armnn::Graph& theGraph = GetGraphForTesting(optimizedNet.get()); - - // Load graph into runtime - armnn::NetworkId networkIdentifier; - runtime->LoadNetwork(networkIdentifier, std::move(optimizedNet)); - - // now check the concat how many sub-tensors it is using.. - auto TraceSubTensorHandleAncestry = [](armnn::ITensorHandle* const subTensorHandle) - { - if (subTensorHandle && subTensorHandle->GetParent()) - { - return true; - } - return false; - }; - - for (auto&& layer : theGraph) - { - if(layer->GetType() == armnn::LayerType::Concat) - { - unsigned int numberOfSubTensors = 0; - for (unsigned int i = 0; i < layer->GetNumInputSlots(); ++i) - { - const armnn::OutputSlot* slot = layer->GetInputSlot(i).GetConnectedOutputSlot(); - if (TraceSubTensorHandleAncestry(slot->GetOutputHandler().GetData())) - { - ++numberOfSubTensors; - } - } - // sub-tensors should be supported in this configuration - ARMNN_ASSERT(numberOfSubTensors > 0); - } - } -} - TEST_CASE("ConcatonXorYPaddingRequiredTest") { armnn::INetworkPtr net(armnn::INetwork::Create()); @@ -247,212 +172,6 @@ TEST_CASE("ConcatonXorYPaddingRequiredTest") ARMNN_ASSERT(numberOfSubTensors == 0); } -TEST_CASE("SplitteronXorYNoPaddingRequiredTest") -{ - using namespace armnn; - - unsigned int splitAxis = 2; - unsigned int numSplit = 2; - - const TensorShape& inputShape = { 2, 3, 4, 2 }; - const armnn::TensorInfo intermediateInfo = armnn::TensorInfo({ 2, 3, 2, 2 }, armnn::DataType::Float32); - const std::vector outputShapes{{ 2, 3, 2, 2 }, - { 2, 3, 2, 2 }}; - const float qScale = 1.0f; - const int32_t qOffset = 0; - - // Creates structures for input & output. - std::vector inputData{ - 1, 2, - 3, 4, - 5, 6, - 7, 8, - 9, 10, - 11, 12, - 13, 14, - 15, 16, - 17, 18, - 19, 20, - 21, 22, - 23, 24, - 25, 26, - 27, 28, - 29, 30, - 31, 32, - 33, 34, - 35, 36, - 37, 38, - 39, 40, - 41, 42, - 43, 44, - 45, 46, - 47, 48 - }; - - std::vector expectedOutput0{ - 1, 2, - 3, 4, - 9, 10, - 11, 12, - 17, 18, - 19, 20, - 25, 26, - 27, 28, - 33, 34, - 35, 36, - 41, 42, - 43, 44 - }; - - std::vector expectedOutput1{ - 5, 6, - 7, 8, - 13, 14, - 15, 16, - 21, 22, - 23, 24, - 29, 30, - 31, 32, - 37, 38, - 39, 40, - 45, 46, - 47, 48 - }; - - // Builds up the structure of the network. - INetworkPtr net(INetwork::Create()); - - TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32, qScale, qOffset); - - armnn::ElementwiseUnaryDescriptor descriptor(armnn::UnaryOperation::Abs); - - // Splitter - std::vector splitterDimSizes(inputShape.GetNumDimensions()); - - // Add current input shape to splitterDimSizes - for (unsigned int i = 0; i < inputShape.GetNumDimensions(); ++i) - { - splitterDimSizes[i] = inputTensorInfo.GetShape()[i]; - } - - if (splitterDimSizes[splitAxis] % numSplit != 0) - { - throw ParseException("Number of splits must evenly divide the dimension"); - } - - splitterDimSizes[splitAxis] /= numSplit; - - SplitterDescriptor splitDesc(numSplit, inputShape.GetNumDimensions()); - - for (unsigned int g = 0; g < numSplit; ++g) - { - // Set the size of the views. - for (unsigned int dimIdx = 0; dimIdx < splitterDimSizes.size(); ++dimIdx) - { - splitDesc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]); - } - splitDesc.SetViewOriginCoord(g, splitAxis, splitterDimSizes[splitAxis] * g); - } - IConnectableLayer* input = net->AddInputLayer(0, "input"); - IConnectableLayer* elementWiseUnary0 = net->AddElementwiseUnaryLayer(descriptor, "elementwiseunary_0"); - IConnectableLayer* elementWiseUnary1 = net->AddElementwiseUnaryLayer(descriptor, "elementwiseunary_0"); - IConnectableLayer* splitter = net->AddSplitterLayer(splitDesc, "splitter"); - - // Connections - Connect(input, splitter, inputTensorInfo, 0, 0); - Connect(splitter, elementWiseUnary0, intermediateInfo, 0, 0); - Connect(splitter, elementWiseUnary1, intermediateInfo, 1, 0); - - std::vector pooling2dLayers{elementWiseUnary0, elementWiseUnary1}; - - for (unsigned int i = 0; i < outputShapes.size(); ++i) - { - TensorInfo outputTensorInfo(outputShapes[i], armnn::DataType::Float32, qScale, qOffset); - IConnectableLayer* output = net->AddOutputLayer(armnn::numeric_cast(i)); - Connect(pooling2dLayers[i], output, outputTensorInfo, 0, 0); - } - - std::map> inputTensorData = {{ 0,inputData }}; - std::map> expectedOutputData = {{ 0, expectedOutput0 }, { 1, expectedOutput1 }}; - - armnn::IRuntime::CreationOptions options; - armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options)); - - std::vector backends = { armnn::Compute::CpuAcc }; - armnn::IOptimizedNetworkPtr optimizedNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec()); - - const armnn::Graph& theGraph = GetGraphForTesting(optimizedNet.get()); - - // Load graph into runtime - armnn::NetworkId networkIdentifier; - runtime->LoadNetwork(networkIdentifier, std::move(optimizedNet)); - - // now check the concat how many sub-tensors it is using.. - auto TraceSubTensorHandleAncestry = [](armnn::ITensorHandle* const subTensorHandle) - { - if (subTensorHandle && subTensorHandle->GetParent()) - { - return true; - } - return false; - }; - - for (auto&& layer : theGraph) - { - if(layer->GetType() == armnn::LayerType::ElementwiseUnary) - { - unsigned int numberOfSubTensors = 0; - for (unsigned int i = 0; i < layer->GetNumInputSlots(); ++i) - { - const armnn::OutputSlot* slot = layer->GetInputSlot(i).GetConnectedOutputSlot(); - if (TraceSubTensorHandleAncestry(slot->GetOutputHandler().GetData())) - { - ++numberOfSubTensors; - } - } - // sub-tensors should be supported in this configuration - ARMNN_ASSERT(numberOfSubTensors > 0); - } - } - - InputTensors inputTensors; - inputTensors.reserve(inputTensorData.size()); - for (auto&& it : inputTensorData) - { - TensorInfo inputTensorInfo = runtime->GetInputTensorInfo(networkIdentifier, it.first); - inputTensorInfo.SetConstant(true); - inputTensors.push_back({it.first, - ConstTensor(inputTensorInfo, it.second.data())}); - } - OutputTensors outputTensors; - outputTensors.reserve(expectedOutputData.size()); - std::map> outputStorage; - for (auto&& it : expectedOutputData) - { - std::vector out(it.second.size()); - outputStorage.emplace(it.first, out); - outputTensors.push_back({it.first, - Tensor(runtime->GetOutputTensorInfo(networkIdentifier, it.first), - outputStorage.at(it.first).data())}); - } - - // Does the inference. - runtime->EnqueueWorkload(networkIdentifier, inputTensors, outputTensors); - - // Checks the results. - float tolerance = 0.000001f; - for (auto&& it : expectedOutputData) - { - std::vector out = outputStorage.at(it.first); - for (unsigned int i = 0; i < out.size(); ++i) - { - CHECK_MESSAGE(Compare(it.second[i], out[i], tolerance) == true, - "Actual output: " << out[i] << ". Expected output:" << it.second[i]); - - } - } -} - TEST_CASE("SplitteronXorYPaddingRequiredTest") { using namespace armnn; -- cgit v1.2.1