From adddddb6cbcb777d92a8c464c9ad0cb9aecc76a3 Mon Sep 17 00:00:00 2001 From: Matteo Martincigh Date: Thu, 24 Jan 2019 14:06:23 +0000 Subject: IVGCVSW-2458 Refactor the Optimize function (Network.cpp) so that subgraphs are optimized by the backends * Added a new method OptimizeSubGraph to the backend interface * Refactored the Optimize function so that the backend-specific optimization is performed by the backend itself (through the new OptimizeSubGraph interface method) * Added a new ApplyBackendOptimizations function to apply the new changes * Added some new convenient constructors to the SubGraph class * Added AddLayer method and a pointer to the parent graph to the SubGraph class * Updated the sub-graph unit tests to match the changes * Added SelectSubGraphs and ReplaceSubGraphConnections overloads that work with sub-graphs * Removed unused code and minor refactoring where necessary Change-Id: I46181794c6a9e3b10558944f804e06a8f693a6d0 --- src/armnn/test/SubGraphTests.cpp | 100 +++++++++++++++++++++++++++++---------- 1 file changed, 75 insertions(+), 25 deletions(-) (limited to 'src/armnn/test') diff --git a/src/armnn/test/SubGraphTests.cpp b/src/armnn/test/SubGraphTests.cpp index 9e49197ea6..e5b444a076 100644 --- a/src/armnn/test/SubGraphTests.cpp +++ b/src/armnn/test/SubGraphTests.cpp @@ -34,7 +34,7 @@ bool AreAnySubGraphLayersPresentInGraph(const SubGraph::Layers &subGraphLayers, // // this helper only works if all layers where the inputs connect to are not selected // -SubGraph::InputSlots CreateInputsFrom(const std::vector & layers) +SubGraph::InputSlots CreateInputsFrom(const std::vector& layers) { SubGraph::InputSlots result; for (auto&& layer : layers) @@ -50,7 +50,7 @@ SubGraph::InputSlots CreateInputsFrom(const std::vector & layers) // // this helper only works if all layers where the outputs connect to are not selected // -SubGraph::OutputSlots CreateOutputsFrom(const std::vector & layers) +SubGraph::OutputSlots CreateOutputsFrom(const std::vector& layers) { SubGraph::OutputSlots result; for (auto && layer : layers) @@ -67,11 +67,12 @@ SubGraph::OutputSlots CreateOutputsFrom(const std::vector & layers) // this takes the inputs, outputs and layers as a copy and the move these copies into the // resulting subgraph, so the pass bay value is intentional // -SubGraphSelector::SubGraphPtr CreateSubGraphFrom(SubGraph::InputSlots inputs, - SubGraph::OutputSlots outputs, - SubGraph::Layers layers) +SubGraphSelector::SubGraphPtr CreateSubGraphFrom(Graph& graph, + SubGraph::InputSlots&& inputs, + SubGraph::OutputSlots&& outputs, + SubGraph::Layers&& layers) { - return std::make_unique(std::move(inputs), std::move(outputs), std::move(layers)); + return std::make_unique(&graph, std::move(inputs), std::move(outputs), std::move(layers)); } template @@ -146,8 +147,10 @@ BOOST_AUTO_TEST_CASE(SingleInputSingleOutput) convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); // Construct sub-graph - SubGraphSelector::SubGraphPtr subGraph = - CreateSubGraphFrom(CreateInputsFrom({convLayer1}), CreateOutputsFrom({convLayer2}), {}); + SubGraphSelector::SubGraphPtr subGraph = CreateSubGraphFrom(graph, + CreateInputsFrom({convLayer1}), + CreateOutputsFrom({convLayer2}), + {}); // Save sub-graph connections for comparison after substitution IOutputSlot* subGraphInputConn = subGraph->GetInputSlot(0)->GetConnection(); @@ -192,8 +195,10 @@ BOOST_AUTO_TEST_CASE(MultiInputSingleOutput) mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); // Construct sub-graph - SubGraphSelector::SubGraphPtr subGraph = - CreateSubGraphFrom(CreateInputsFrom({convLayer1, convLayer2}), CreateOutputsFrom({mergerLayer}), {}); + SubGraphSelector::SubGraphPtr subGraph = CreateSubGraphFrom(graph, + CreateInputsFrom({convLayer1, convLayer2}), + CreateOutputsFrom({mergerLayer}), + {}); // Save sub-graph connections for comparison after substitution IOutputSlot* subGraphInputConn1 = subGraph->GetInputSlot(0)->GetConnection(); @@ -240,8 +245,10 @@ BOOST_AUTO_TEST_CASE(SingleInputMultiOutput) mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); // Construct sub-graph - SubGraphSelector::SubGraphPtr subGraph = - CreateSubGraphFrom(CreateInputsFrom({splitterLayer}), CreateOutputsFrom({convLayer1, convLayer2}), {}); + SubGraphSelector::SubGraphPtr subGraph = CreateSubGraphFrom(graph, + CreateInputsFrom({splitterLayer}), + CreateOutputsFrom({convLayer1, convLayer2}), + {}); // Save sub-graph connections for comparison after substitution IOutputSlot* subGraphInputConn1 = subGraph->GetInputSlot(0)->GetConnection(); @@ -290,7 +297,8 @@ BOOST_AUTO_TEST_CASE(MultiInputMultiOutput) mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); // Construct sub-graph - SubGraphSelector::SubGraphPtr subGraph = CreateSubGraphFrom(CreateInputsFrom({convLayer1, convLayer2}), + SubGraphSelector::SubGraphPtr subGraph = CreateSubGraphFrom(graph, + CreateInputsFrom({convLayer1, convLayer2}), CreateOutputsFrom({convLayer1, convLayer2}), {}); @@ -336,8 +344,10 @@ BOOST_AUTO_TEST_CASE(EraseReplacedLayers) graph.AddLayer(0, "output"); // Construct sub-graph - SubGraphSelector::SubGraphPtr subGraph = - CreateSubGraphFrom({}, {}, {splitterLayer, convLayer1, convLayer2, mergerLayer}); + SubGraphSelector::SubGraphPtr subGraph = CreateSubGraphFrom(graph, + {}, + {}, + {splitterLayer, convLayer1, convLayer2, mergerLayer}); // Construct dummy pre-compiled layer PreCompiledDescriptor preCompiledDescriptor(0, 0); @@ -357,6 +367,36 @@ BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE(SubGraphSelection) +BOOST_AUTO_TEST_CASE(SubGraphForEmptyGraph) +{ + Graph graph; + SubGraph subGraph(graph); + + BOOST_TEST(subGraph.GetInputSlots().empty()); + BOOST_TEST(subGraph.GetOutputSlots().empty()); + BOOST_TEST(subGraph.GetLayers().empty()); +} + +BOOST_AUTO_TEST_CASE(SubGraphForEntireGraph) +{ + Graph graph; + + auto output = graph.AddLayer(0, "output"); + auto mid0 = graph.InsertNewLayer(output->GetInputSlot(0), + ActivationDescriptor{}, + "mid0"); + auto mid1 = graph.InsertNewLayer(mid0->GetInputSlot(0), + ActivationDescriptor{}, + "mid1"); + graph.InsertNewLayer(mid1->GetInputSlot(0), 0, "input"); + + SubGraph subGraph(graph); + + BOOST_TEST(subGraph.GetInputSlots().empty()); + BOOST_TEST(subGraph.GetOutputSlots().empty()); + BOOST_TEST(subGraph.GetLayers().size() == graph.GetNumLayers()); +} + BOOST_AUTO_TEST_CASE(NoSubGraphsForNoMatch) { Graph graph; @@ -390,7 +430,8 @@ BOOST_AUTO_TEST_CASE(OneSubGraphsSelectedASingleMatch) BOOST_TEST(subGraphs.size() == 1); if (subGraphs.size() == 1) { - auto expected = CreateSubGraphFrom(CreateInputsFrom({output}), + auto expected = CreateSubGraphFrom(graph, + CreateInputsFrom({output}), // outputs of 'output' will be empty CreateOutputsFrom({output}), {output}); @@ -425,7 +466,8 @@ BOOST_AUTO_TEST_CASE(MultipleLayersSelectedInTheMiddle) BOOST_TEST(subGraphs.size() == 1); if (subGraphs.size() == 1) { - auto expected = CreateSubGraphFrom(CreateInputsFrom({mid1}), + auto expected = CreateSubGraphFrom(graph, + CreateInputsFrom({mid1}), CreateOutputsFrom({mid0}), {mid1, mid0}); @@ -496,11 +538,13 @@ BOOST_AUTO_TEST_CASE(IslandInTheMiddle) }); // expected results to test against - auto largerSubGraph = CreateSubGraphFrom(CreateInputsFrom({m1, m4}), + auto largerSubGraph = CreateSubGraphFrom(graph, + CreateInputsFrom({m1, m4}), CreateOutputsFrom({m3, m4}), {m1, m4, m2, m3}); - auto smallerSubGraph = CreateSubGraphFrom(CreateInputsFrom({m5}), + auto smallerSubGraph = CreateSubGraphFrom(graph, + CreateInputsFrom({m5}), CreateOutputsFrom({m5}), {m5}); @@ -572,11 +616,13 @@ BOOST_AUTO_TEST_CASE(MultipleSimpleSubGraphs) }); // expected results to test against - auto largerSubGraph = CreateSubGraphFrom(CreateInputsFrom({m1}), + auto largerSubGraph = CreateSubGraphFrom(graph, + CreateInputsFrom({m1}), CreateOutputsFrom({m2}), {m1, m2}); - auto smallerSubGraph = CreateSubGraphFrom(CreateInputsFrom({m3}), + auto smallerSubGraph = CreateSubGraphFrom(graph, + CreateInputsFrom({m3}), CreateOutputsFrom({m3}), {m3}); @@ -644,7 +690,8 @@ BOOST_AUTO_TEST_CASE(SimpleLinearTest) BOOST_CHECK(subGraphs.size() == 1); if(subGraphs.size() == 1) { - auto expected = CreateSubGraphFrom(CreateInputsFrom({layerM1}), + auto expected = CreateSubGraphFrom(graph, + CreateInputsFrom({layerM1}), CreateOutputsFrom({layerM2}), {layerM1, layerM2}); @@ -699,7 +746,8 @@ BOOST_AUTO_TEST_CASE(MultiInputSingleOutput) BOOST_CHECK(subGraphs.size() == 1); if (subGraphs.size() == 1) { - auto expected = CreateSubGraphFrom(CreateInputsFrom({layerM1, layerM2}), + auto expected = CreateSubGraphFrom(graph, + CreateInputsFrom({layerM1, layerM2}), CreateOutputsFrom({layerM3}), {layerM1, layerM2, layerM3}); @@ -755,7 +803,8 @@ BOOST_AUTO_TEST_CASE(SingleInputMultiOutput) BOOST_CHECK(subGraphs.size() == 1); if(subGraphs.size() == 1) { - auto expected = CreateSubGraphFrom(CreateInputsFrom({layerM1}), + auto expected = CreateSubGraphFrom(graph, + CreateInputsFrom({layerM1}), CreateOutputsFrom({layerM2, layerM3}), {layerM1, layerM2, layerM3}); @@ -819,7 +868,8 @@ BOOST_AUTO_TEST_CASE(MultiInputMultiOutput) BOOST_CHECK(subGraphs.size() == 1); if (subGraphs.size() == 1) { - auto expected = CreateSubGraphFrom(CreateInputsFrom({m1, m2}), + auto expected = CreateSubGraphFrom(graph, + CreateInputsFrom({m1, m2}), CreateOutputsFrom({m4, m5}), {m1, m2, m3, m4, m5}); -- cgit v1.2.1