14 #include <doctest/doctest.h> 23 using namespace armnn;
30 for(
auto&& layer : subgraphLayers)
32 auto posInGraph = std::find(graph.
begin(), graph.
end(), layer);
33 if(posInGraph != graph.
end())
48 for (
auto&& layer : layers)
50 for (
auto&& it = layer->BeginInputSlots(); it != layer->EndInputSlots(); ++it)
52 result.push_back(&(*it));
62 for (
auto&& layer : layers)
64 for (
unsigned int i = 0 ; i < layer->GetNumInputSlots(); ++i)
66 result.push_back(&(layer->GetInputSlot(i)));
78 for (
auto && layer : layers)
80 for (
auto&& it = layer->BeginOutputSlots(); it != layer->EndOutputSlots(); ++it)
82 result.push_back(&(*it));
92 for (
auto&& layer: layers)
94 for (
unsigned int i = 0; i < layer->GetNumOutputSlots(); ++i)
96 result.push_back(&(layer->GetOutputSlot(i)));
110 return std::make_unique<SubgraphView>(std::move(inputs), std::move(outputs), std::move(layers));
117 return std::make_unique<SubgraphView>(std::move(layers), std::move(inputs), std::move(outputs));
120 template <
typename T,
typename Iterator>
121 std::vector<T> ToSortedArray(Iterator begin, Iterator end)
123 std::vector<T> result(begin, end);
124 std::sort(result.begin(), result.end());
128 template <
typename T>
129 void CompareVectors(
const std::vector<T>& result,
const std::vector<T>& expected)
131 CHECK(std::equal(result.begin(), result.end(), expected.begin(), expected.end()));
138 CHECK((result.get() !=
nullptr));
139 CHECK((expected.get() !=
nullptr));
141 if (result.get() !=
nullptr && expected.get() !=
nullptr)
143 CHECK(result->GetIInputSlots().size() == expected->GetIInputSlots().size());
144 CHECK(result->GetIOutputSlots().size() == expected->GetIOutputSlots().size());
145 CHECK(result->GetIConnectableLayers().size() == expected->GetIConnectableLayers().size());
147 auto resultLayers = ToSortedArray<IConnectableLayer*>(result->GetIConnectableLayers().begin(),
148 result->GetIConnectableLayers().end());
149 auto expectedLayers = ToSortedArray<IConnectableLayer*>(expected->GetIConnectableLayers().begin(),
150 expected->GetIConnectableLayers().end());
151 CompareVectors(resultLayers, expectedLayers);
153 auto resultInputs = ToSortedArray<IInputSlot *>(result->GetIInputSlots().begin(),
154 result->GetIInputSlots().end());
155 auto expectedInputs = ToSortedArray<IInputSlot *>(expected->GetIInputSlots().begin(),
156 expected->GetIInputSlots().end());
157 CompareVectors(resultInputs, expectedInputs);
159 auto resultOutputs = ToSortedArray<IOutputSlot *>(result->GetIOutputSlots().begin(),
160 result->GetIOutputSlots().end());
161 auto expectedOutputs = ToSortedArray<IOutputSlot *>(expected->GetIOutputSlots().begin(),
162 expected->GetIOutputSlots().end());
163 CompareVectors(resultOutputs, expectedOutputs);
173 TEST_CASE(
"SubgraphViewIterators")
182 if (std::find(subgraph.cbeginIConnectable(), subgraph.cendIConnectable(), layer)
183 != subgraph.cendIConnectable())
191 if (std::find(subgraph.beginIConnectable(), subgraph.endIConnectable(), layer)
192 != subgraph.endIConnectable())
201 for (
auto& iConnectableLayer : subgraphLayers)
203 if (std::string(iConnectableLayer->GetName()) ==
"input")
215 for (
auto& layerOld : subgraphLayersOld)
217 if (std::string(layerOld->GetName()) ==
"input")
225 TEST_CASE(
"SubgraphViewSlots")
240 convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
244 CreateIInputsFrom({convLayer1}),
245 CreateIOutputsFrom({convLayer2}));
248 CHECK(subgraph->GetIInputSlots().size() == 1);
249 CHECK(subgraph->GetIOutputSlots().size() == 1);
252 CHECK(subgraph->GetInputSlots().size() == 1);
253 CHECK(subgraph->GetOutputSlots().size() == 1);
256 CHECK(subgraph->GetOutputSlot(0) == subgraph->GetIOutputSlot(0));
257 CHECK(subgraph->GetInputSlot(0) == subgraph->GetIInputSlot(0));
262 TEST_CASE(
"SubgraphViewConstructors")
277 convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
282 CreateIInputsFrom({convLayer1}),
283 CreateIOutputsFrom({convLayer2}));
287 CHECK(subgraph->GetIConnectableLayers() == subgraph2.GetIConnectableLayers());
288 CHECK(subgraph->GetIInputSlots() == subgraph2.GetIInputSlots());
289 CHECK(subgraph->GetIOutputSlots() == subgraph2.GetIOutputSlots());
292 CHECK(subgraph->GetLayers() == subgraph2.GetLayers());
293 CHECK(subgraph->GetInputSlots() == subgraph2.GetInputSlots());
294 CHECK(subgraph->GetOutputSlots() == subgraph2.GetOutputSlots());
299 CHECK(subgraph->GetIConnectableLayers() == subgraph3.GetIConnectableLayers());
300 CHECK(subgraph->GetIInputSlots() == subgraph3.GetIInputSlots());
301 CHECK(subgraph->GetIOutputSlots() == subgraph3.GetIOutputSlots());
304 CHECK(subgraph->GetLayers() == subgraph3.GetLayers());
305 CHECK(subgraph->GetInputSlots() == subgraph3.GetInputSlots());
306 CHECK(subgraph->GetOutputSlots() == subgraph3.GetOutputSlots());
310 subgraph.get()->Clear();
311 CHECK(subgraph->GetIConnectableLayers().size() == 0);
312 CHECK(subgraph->GetIInputSlots().size() == 0);
313 CHECK(subgraph->GetIOutputSlots().size() == 0);
320 TEST_CASE(
"SingleInputSingleOutput")
335 convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
340 CreateIInputsFrom({convLayer1}),
341 CreateIOutputsFrom({convLayer2}));
362 TEST_CASE(
"SingleInputSingleOutputAddPrecompiledLayerSubstituteSubgraph1")
377 convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
394 IConnectableLayer* preCompiledLayer = network->AddPrecompiledLayer(preCompiledDescriptor,
395 std::move(compiledBlobPtr),
406 TEST_CASE(
"SingleInputSingleOutputAddPrecompiledLayerSubstituteSubgraph2")
421 convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
438 IConnectableLayer* preCompiledLayer = network->AddPrecompiledLayer(preCompiledDescriptor,
439 std::move(compiledBlobPtr),
451 TEST_CASE(
"SingleInputSingleOutputSubstituteGraph")
466 convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
479 Graph substituteGraph;
495 TEST_CASE(
"MultiInputSingleOutput")
518 convLayer2->GetOutputSlot(0).Connect(concatLayer->
GetInputSlot(1));
546 TEST_CASE(
"SingleInputMultiOutput")
567 convLayer2->GetOutputSlot(0).Connect(concatLayer->
GetInputSlot(1));
596 TEST_CASE(
"MultiInputMultiOutput")
619 convLayer2->GetOutputSlot(0).Connect(concatLayer->
GetInputSlot(1));
650 TEST_CASE(
"EraseReplacedIConnectableLayers")
688 CHECK(!AreAnySubgraphLayersPresentInGraph(subgraphLayers, graph));
695 TEST_CASE(
"SubgraphForEmptyGraph")
705 TEST_CASE(
"SubgraphForEntireGraph")
720 CHECK(subgraph.GetIInputSlots().empty());
721 CHECK(subgraph.GetIOutputSlots().empty());
722 CHECK(subgraph.GetIConnectableLayers().size() == graph.
GetNumLayers());
725 TEST_CASE(
"NoSubgraphsForNoMatch")
735 CHECK(subgraphs.empty());
738 TEST_CASE(
"OneSubgraphsSelectedASingleMatch")
751 bool isOutput = l.
GetNameStr().compare(
"output") == 0;
755 CHECK(subgraphs.size() == 1);
756 if (subgraphs.size() == 1)
763 CompareSubgraphViews(subgraphs[0], expected);
767 TEST_CASE(
"MultipleLayersSelectedInTheMiddle")
790 CHECK(subgraphs.size() == 1);
791 if (subgraphs.size() == 1)
797 CompareSubgraphViews(subgraphs[0], expected);
801 TEST_CASE(
"DisjointGraphs")
826 CHECK(subgraphs.size() == 2);
827 if (subgraphs.size() == 2)
829 CHECK((subgraphs[0] !=
nullptr));
830 CHECK((subgraphs[1] !=
nullptr));
831 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr)
833 if (std::find(subgraphs[0]->GetIConnectableLayers().begin(),
834 subgraphs[0]->GetIConnectableLayers().end(), i0) !=
835 subgraphs[0]->GetIConnectableLayers().end())
837 CompareSubgraphViews(subgraphs[0], expected1);
838 CompareSubgraphViews(subgraphs[1], expected2);
842 CompareSubgraphViews(subgraphs[0], expected2);
843 CompareSubgraphViews(subgraphs[1], expected1);
849 TEST_CASE(
"IslandInTheMiddle")
900 bool toSelect = std::string(l.
GetName())[0] ==
'm';
907 { m0, m1, m2, m3, m4 });
909 auto smallerSubgraph =
911 std::vector<OutputSlot*>{},
914 CHECK(subgraphs.size() == 2);
915 if (subgraphs.size() == 2)
918 CHECK((subgraphs[0] !=
nullptr));
919 CHECK((subgraphs[1] !=
nullptr));
921 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr)
924 std::sort(subgraphs.begin(), subgraphs.end(),
927 return (lhs->GetIConnectableLayers().size() < rhs->GetIConnectableLayers().size());
931 CHECK(subgraphs[0]->GetIConnectableLayers().size() == 2);
932 CHECK(subgraphs[1]->GetIConnectableLayers().size() == 5);
934 CompareSubgraphViews(subgraphs[0], smallerSubgraph);
935 CompareSubgraphViews(subgraphs[1], largerSubgraph);
940 TEST_CASE(
"MultipleSimpleSubgraphs")
989 CHECK(subgraphs.size() == 2);
990 if (subgraphs.size() == 2)
993 CHECK((subgraphs[0] !=
nullptr));
994 CHECK((subgraphs[1] !=
nullptr));
996 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr)
999 std::sort(subgraphs.begin(), subgraphs.end(),
1002 return (lhs->GetIConnectableLayers().size() < rhs->GetIConnectableLayers().size());
1006 CHECK(subgraphs[0]->GetIConnectableLayers().size() == 1);
1007 CHECK(subgraphs[1]->GetIConnectableLayers().size() == 2);
1009 CompareSubgraphViews(subgraphs[0], smallerSubgraph);
1010 CompareSubgraphViews(subgraphs[1], largerSubgraph);
1015 TEST_CASE(
"SimpleLinearTest")
1050 CHECK(subgraphs.size() == 1);
1051 if(subgraphs.size() == 1)
1055 {layerM1, layerM2});
1057 CompareSubgraphViews(subgraphs[0], expected);
1061 TEST_CASE(
"MultiInputSingleOutput")
1105 CHECK(subgraphs.size() == 1);
1106 if (subgraphs.size() == 1)
1110 {layerM1, layerM2, layerM3});
1112 CompareSubgraphViews(subgraphs[0], expected);
1116 TEST_CASE(
"SingleInputMultiOutput")
1145 layerM1->GetOutputSlot(0).Connect(layerM2->GetInputSlot(0));
1146 layerM1->GetOutputSlot(1).Connect(layerM3->GetInputSlot(0));
1147 layerM2->GetOutputSlot(0).Connect(layerX2->GetInputSlot(0));
1148 layerM3->GetOutputSlot(0).Connect(layerX3->GetInputSlot(0));
1161 CHECK(subgraphs.size() == 1);
1162 if(subgraphs.size() == 1)
1166 {layerM1, layerM2, layerM3});
1168 CompareSubgraphViews(subgraphs[0], expected);
1172 TEST_CASE(
"MultiInputMultiOutput")
1225 CHECK(subgraphs.size() == 1);
1226 if (subgraphs.size() == 1)
1230 {m1, m2, m3, m4, m5});
1232 CompareSubgraphViews(subgraphs[0], expected);
1236 TEST_CASE(
"ValidMerge")
1270 [](
const Layer& l) {
1271 return std::string(l.
GetName())[0] ==
'm';
1275 auto expectedSubgraph0 =
1286 CHECK(subgraphs.size() == 2);
1287 if (subgraphs.size() == 2)
1290 CHECK((subgraphs[0] !=
nullptr));
1291 CHECK((subgraphs[1] !=
nullptr));
1293 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr)
1295 if (subgraphs[0]->GetIInputSlots().size() == 1)
1297 CompareSubgraphViews(subgraphs[0], expectedSubgraph0);
1298 CompareSubgraphViews(subgraphs[1], expectedSubgraph1);
1302 CompareSubgraphViews(subgraphs[0], expectedSubgraph1);
1303 CompareSubgraphViews(subgraphs[1], expectedSubgraph0);
1309 TEST_CASE(
"PropagatedDependencies")
1365 bool toSelect = std::string(l.
GetName())[0] ==
'm';
1372 { m0, m1, m2, m3, m4 });
1375 std::vector<OutputSlot*>{}, { m5, m6 });
1377 auto smallerSubgraph =
1380 CHECK(subgraphs.size() == 3);
1381 if (subgraphs.size() == 3)
1384 CHECK((subgraphs[0] !=
nullptr));
1385 CHECK((subgraphs[1] !=
nullptr));
1386 CHECK((subgraphs[2] !=
nullptr));
1388 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr && subgraphs[2].
get() !=
nullptr)
1391 std::sort(subgraphs.begin(), subgraphs.end(),
1394 return (lhs->GetIConnectableLayers().size() < rhs->GetIConnectableLayers().size());
1398 CompareSubgraphViews(subgraphs[0], smallerSubgraph);
1399 CompareSubgraphViews(subgraphs[1], mediumSubgraph);
1400 CompareSubgraphViews(subgraphs[2], largerSubgraph);
1410 constexpr
bool debug =
false;
1412 std::mt19937 randomGenerator;
1415 auto GetRandom = [&randomGenerator](
auto maxExclusive) {
1419 std::uniform_real_distribution<float> uniform(0.0f, 1.0f);
1420 return static_cast<decltype(maxExclusive)
>(uniform(randomGenerator) *
static_cast<float>(maxExclusive));
1423 auto GetRandomFlag = [&randomGenerator](
float trueProb) {
1424 std::uniform_real_distribution<float> uniform(0.0f, 1.0f);
1425 return uniform(randomGenerator) < trueProb;
1428 constexpr uint32_t numTests = 100;
1429 for (uint32_t testIdx = 0; testIdx < numTests; ++testIdx)
1431 randomGenerator.seed(testIdx);
1439 uint32_t numInputs = 1 + GetRandom(4u);
1440 uint32_t numConstants = 1 + GetRandom(4u);
1441 uint32_t numOutputs = 1 + GetRandom(4u);
1442 uint32_t numConcats = 0 + GetRandom(500u);
1443 uint32_t numSplits = 0 + GetRandom(500u);
1444 float supportedProb = 0.7f;
1446 for (uint32_t i = 0; i < numInputs; ++i)
1448 std::string name =
"input" + std::to_string(i) + (GetRandomFlag(supportedProb) ?
"S" :
"N");
1451 for (uint32_t i = 0; i < numConstants; ++i)
1453 std::string name =
"constant" + std::to_string(i) + (GetRandomFlag(supportedProb) ?
"S" :
"N");
1456 for (uint32_t i = 0; i < numOutputs; ++i)
1458 std::string name =
"output" + std::to_string(i) + (GetRandomFlag(supportedProb) ?
"S" :
"N");
1461 for (uint32_t i = 0; i < numConcats; ++i)
1463 std::string name =
"concat" + std::to_string(i) + (GetRandomFlag(supportedProb) ?
"S" :
"N");
1464 numInputs = 1 + GetRandom(3u);
1468 for (uint32_t i = 0; i < numSplits; ++i)
1470 std::string name =
"split" + std::to_string(i) + (GetRandomFlag(supportedProb) ?
"S" :
"N");
1471 numOutputs = 1 + GetRandom(3u);
1481 uint32_t maxLayerDepth = 5 + GetRandom(2000u);
1482 std::map<Layer*, uint32_t> layerDepths;
1483 std::map<uint32_t, std::vector<Layer*>> layersAtDepth;
1484 for (
Layer* layer : graph)
1496 depth = 1 + GetRandom(maxLayerDepth);
1498 layerDepths[layer] = depth;
1499 layersAtDepth[depth].push_back(layer);
1504 for (
Layer* layer : graph)
1506 for (uint32_t inputSlotIdx = 0; inputSlotIdx < layer->GetNumInputSlots(); ++inputSlotIdx)
1508 InputSlot& inputSlot = layer->GetInputSlot(inputSlotIdx);
1509 uint32_t maxLayerDepthToConnectTo = layerDepths[layer];
1514 uint32_t layerDepth = GetRandom(maxLayerDepthToConnectTo);
1515 const std::vector<Layer*>& layersToChooseFrom = layersAtDepth[layerDepth];
1516 if (layersToChooseFrom.size() == 0)
1520 Layer* layerToConnectWith = layersToChooseFrom[GetRandom(layersToChooseFrom.size())];
1534 std::ofstream f(
"INPUT_" + std::to_string(testIdx) +
".dot");
1539 auto startTime = std::chrono::high_resolution_clock::now();
1543 [](
const Layer& l) {
return std::string(l.
GetName()).back() ==
'S'; });
1545 auto endTime = std::chrono::high_resolution_clock::now();
1546 auto duration = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime);
1549 std::cout <<
"Test " << testIdx <<
": " << duration.count() <<
" microseconds" << std::endl;
1554 std::map<Layer*, SubgraphView*> layerToSubgraph;
1555 for (
Layer* layer : graph)
1558 for (std::unique_ptr<SubgraphView>& subgraph : subgraphs)
1560 std::string name = std::to_string(i++);
1561 if (std::find(subgraph->cbeginIConnectable(), subgraph->cendIConnectable(), layer)
1562 != subgraph->cendIConnectable())
1564 layerToSubgraph[layer] = subgraph.get();
1574 for (
Layer* layer : graph)
1576 std::string name =
"NotAssigned";
1577 auto subgraphIt = layerToSubgraph.find(layer);
1578 if (subgraphIt != layerToSubgraph.end())
1580 auto subgraphIdx = std::distance(subgraphs.begin(),
1581 std::find_if(subgraphs.begin(), subgraphs.end(),
1582 [&](
auto& s) {
return s.get() == subgraphIt->second; }));
1583 name = std::to_string(subgraphIdx);
1588 std::ofstream f(
"GRAPH_" + std::to_string(testIdx) +
".dot");
1589 graph.SerializeToDot(f);
1595 for (std::unique_ptr<SubgraphView>& subgraph : subgraphs)
1597 for (
IInputSlot* inSlot : subgraph->GetIInputSlots())
1599 std::queue<Layer*> toProcess;
1600 toProcess.push(&PolymorphicDowncast<InputSlot*>(inSlot)->GetConnectedOutputSlot()->GetOwningLayer());
1601 while (toProcess.size() > 0)
1603 Layer* l = toProcess.front();
1606 CHECK(layerToSubgraph[l] != subgraph.get());
1610 toProcess.push(&is.GetConnectedOutputSlot()->GetOwningLayer());
1622 TEST_CASE(
"SingleSubgraph")
1650 [](
const Layer & l){
1655 CHECK(subgraphs.size() == 1);
1656 if(subgraphs.size() == 1)
1658 CHECK((subgraphs[0] !=
nullptr));
1660 if (subgraphs[0].
get() !=
nullptr)
1662 unsigned int numInputSlots =
armnn::numeric_cast<
unsigned int>(subgraphs[0]->GetIInputSlots().size());
1663 unsigned int numOutputSlots =
armnn::numeric_cast<
unsigned int>(subgraphs[0]->GetIOutputSlots().size());
1665 CHECK((numInputSlots == 1));
1666 CHECK((numOutputSlots == 1));
1687 TEST_CASE(
"MultipleSubgraphs")
1715 convLayer2->GetOutputSlot(0).Connect(pConcatLayer->
GetInputSlot(1));
1723 [](
const Layer & l){
1728 CHECK(subgraphs.size() == 2);
1729 if(subgraphs.size() == 2)
1731 CHECK((subgraphs[0] !=
nullptr));
1732 CHECK((subgraphs[1] !=
nullptr));
1734 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr)
1737 std::sort(subgraphs.begin(), subgraphs.end(),
1740 return (lhs->GetIInputSlots().size() < rhs->GetIInputSlots().size());
1744 unsigned int numInputSlots1 =
armnn::numeric_cast<
unsigned int>(subgraphs[0]->GetIInputSlots().size());
1745 unsigned int numOutputSlots1 =
armnn::numeric_cast<
unsigned int>(subgraphs[0]->GetIOutputSlots().size());
1747 unsigned int numInputSlots2 =
armnn::numeric_cast<
unsigned int>(subgraphs[1]->GetIInputSlots().size());
1748 unsigned int numOutputSlots2 =
armnn::numeric_cast<
unsigned int>(subgraphs[1]->GetIOutputSlots().size());
1782 TEST_CASE(
"SubgraphCycles")
1829 bool toSelect = (l.
GetNameStr().find(
'm') != std::string::npos);
1842 CHECK(subgraphs.size() == 2);
1843 if (subgraphs.size() == 2)
1846 CHECK((subgraphs[0] !=
nullptr));
1847 CHECK((subgraphs[1] !=
nullptr));
1849 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr)
1852 std::sort(subgraphs.begin(), subgraphs.end(),
1855 return (lhs->GetIConnectableLayers().size() < rhs->GetIConnectableLayers().size());
1860 CHECK(subgraphs[0]->GetIConnectableLayers().size() == 1);
1861 CHECK(subgraphs[1]->GetIConnectableLayers().size() == 2);
1863 CompareSubgraphViews(subgraphs[0], outputSubgraph);
1864 CompareSubgraphViews(subgraphs[1], inputSubgraph);
1869 TEST_CASE(
"SubgraphOrder")
1883 {output, input, activation});
1888 view->ForEachLayer([&idx, &expectedSorted](
const Layer* l)
1890 CHECK((expectedSorted[idx] == l->
GetType()));
1896 TEST_CASE(
"SubgraphViewWorkingCopy")
1917 workingCopy.ForEachIConnectableLayer([&idx, &expectedSorted](
const IConnectableLayer* l)
1919 CHECK((expectedSorted[idx] == l->
GetType()));
1925 bool ReplaceConstantMultiplicationWithDepthwise(
SubgraphView& subgraph,
1959 ARMNN_ASSERT_MSG(M == 1,
"Constant multiplication only support 1x1x1xC, so M should always be 1 here");
1962 const void* weightData = PolymorphicPointerDowncast<const ConstantLayer>(constantLayer)
1963 ->m_LayerOutput->GetConstTensor<
void>();
1967 const auto depthwiseLayer = replacementGraph->AddDepthwiseConvolution2dLayer(
1973 layers.push_back(layer);
1974 layers.push_back(const_cast<IConnectableLayer*>(constantLayer));
1996 return ReplaceConstantMultiplicationWithDepthwise(subgraph, layer);
1999 throw Exception(
"Found unknown MultiplicationSupportedMode value");
2009 const ReplacementFunc replacementFuncs[] = {
2010 &ReplaceTestMultiplication,
2015 auto madeChange =
false;
2016 for (
const ReplacementFunc f : replacementFuncs)
2018 madeChange = f(subgraph, layer);
2029 TEST_CASE(
"SubgraphViewWorkingCopyReplacementFunc")
2037 std::vector<uint8_t> constData(constInfo.GetNumElements(), 0);
2038 std::iota(constData.begin(), constData.end(), 0);
2045 constant->m_LayerOutput = std::make_shared<ScopedTensorHandle>(constTensor);
2052 mul->GetOutputSlot(0).SetTensorInfo(outputInfo);
2056 mul->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2066 CHECK(workingCopy.GetIConnectableLayers().size() == 4);
2069 workingCopy.ForEachIConnectableLayer([&idx, &expectedSorted](
const IConnectableLayer* l)
2071 CHECK((expectedSorted[idx] == l->
GetType()));
2077 ReplaceUnsupportedLayers(workingCopy);
2080 CHECK(workingCopy.GetIConnectableLayers().size() == 3);
2083 workingCopy.ForEachIConnectableLayer([&idx, &expectedSortedReplaced](
const IConnectableLayer* l)
2085 CHECK((expectedSortedReplaced[idx] == l->
GetType()));
2091 TEST_CASE(
"SubgraphViewWorkingCopySubstituteSubgraph")
2112 auto workingCopy = view->GetWorkingCopy();
2113 CHECK_THROWS_AS(workingCopy.GetWorkingCopy(),
Exception);
2116 TEST_CASE(
"SubgraphViewWorkingCopyOptimizationViews")
2124 std::vector<uint8_t> constData(constInfo.GetNumElements(), 0);
2125 std::iota(constData.begin(), constData.end(), 0);
2132 constant->m_LayerOutput = std::make_shared<ScopedTensorHandle>(constTensor);
2139 mul->GetOutputSlot(0).SetTensorInfo(outputInfo);
2143 mul->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2155 workingCopy.ForEachIConnectableLayer([&idx, &expectedSorted](
const IConnectableLayer* l)
2157 CHECK((expectedSorted[idx] == l->
GetType()));
2163 ReplaceUnsupportedLayers(workingCopy);
2168 workingCopy.ForEachIConnectableLayer([&idx, &expectedSortedReplaced](
const IConnectableLayer* l)
2170 CHECK((expectedSortedReplaced[idx] == l->
GetType()));
2190 CHECK(optimizationViews.
Validate(*view));
2193 TEST_CASE(
"SubgraphViewWorkingCopyReplaceSlots")
2200 std::vector<uint8_t> constData(constInfo.GetNumElements(), 0);
2201 std::iota(constData.begin(), constData.end(), 0);
2208 constant->m_LayerOutput = std::make_shared<ScopedTensorHandle>(constTensor);
2215 mul->GetOutputSlot(0).SetTensorInfo(outputInfo);
2219 mul->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2222 CreateIInputsFrom({mul}),
2223 CreateIOutputsFrom({mul}));
2233 CHECK((expectedSorted[idx] == l->
GetType()));
2239 ReplaceUnsupportedLayers(workingCopy);
2247 CHECK((expectedSortedReplaced[idx] == l->
GetType()));
TEST_SUITE("TestConstTensorLayerVisitor")
A layer that the constant data can be bound to.
Iterator begin()
Returns iterator pointing to the beginning of the list. Lowercase for range-based for loops...
This layer represents a split operation.
A ViewsDescriptor for the SplitterLayer.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
const IOutputSlots & GetIOutputSlots() const
const TensorShape & GetShape() const
CPU Execution: Reference C++ kernels.
Status SerializeToDot(std::ostream &stream)
void swap(OriginsDescriptor &first, OriginsDescriptor &second)
const IConnectableLayers & GetIConnectableLayers() const
const IInputSlots & GetIInputSlots() const
#define ARMNN_NO_DEPRECATE_WARN_BEGIN
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
LayerT * AddLayer(Args &&... args)
Adds a new layer, of type LayerType, to the graph constructed with the arguments passed.
A Convolution2dDescriptor for the Convolution2dLayer.
int Connect(InputSlot &destination)
std::vector< OutputSlot * > OutputSlots
void AddSubstitution(SubstitutionPair &&substitution)
This layer represents an activation operation with the specified activation function.
Copyright (c) 2021 ARM Limited and Contributors.
void SetBackendId(const BackendId &id)
const std::vector< InputSlot > & GetInputSlots() const
virtual const IInputSlot * GetConnection(unsigned int index) const =0
unsigned int GetNumOutputSlots() const override
Returns the number of connectable output slots.
void SubstituteSubgraph(SubgraphView &, IConnectableLayer *)
These methods should be called on a working copy subgraph created from GetWorkingCopy.
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
void SetShape(const TensorShape &newShape)
std::unique_ptr< void, CompiledBlobDeleter > CompiledBlobPtr
The SubgraphView class represents a subgraph of a Graph.
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
A layer user-provided data can be bound to (e.g. inputs, outputs).
std::list< IConnectableLayer * > IConnectableLayers
#define ARMNN_NO_DEPRECATE_WARN_END
#define ARMNN_ASSERT_MSG(COND, MSG)
An output connection slot for a layer.
SubgraphView::InputSlots CreateInputsFrom(const std::vector< Layer *> &layers)
An OriginsDescriptor for the ConcatLayer.
std::vector< IOutputSlot * > IOutputSlots
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
This layer represents a merge operation.
void ForEachIConnectableLayer(Func func) const
const std::string & GetNameStr() const
LayerType GetType() const override
Returns the armnn::LayerType of this layer.
std::vector< SubgraphViewPtr > Subgraphs
virtual const IConnectableLayer & GetOwningIConnectableLayer() const =0
INetworkPtr & GetINetwork()
std::vector< IInputSlot * > IInputSlots
GPU Execution: OpenCL: ArmCompute.
bool Validate(const SubgraphView &originalSubgraph) const
An ActivationDescriptor for the ActivationLayer.
const BackendId & GetBackendId() const
virtual LayerType GetType() const =0
Returns the armnn::LayerType of this layer.
std::vector< InputSlot * > InputSlots
This layer represents an addition operation.
void SubstituteSubgraph(SubgraphView &subgraph, IConnectableLayer *substituteLayer)
Substitutes the given sub-graph with either a new layer or a new sub-graph.
std::unique_ptr< SubgraphView > SubgraphViewPtr
EmptyOptional is used to initialize the Optional class in case we want to have default value for an O...
SubgraphView::SubgraphViewPtr CreateSubgraphViewFrom(SubgraphView::InputSlots &&inputs, SubgraphView::OutputSlots &&outputs, SubgraphView::Layers &&layers)
SubgraphView::OutputSlots CreateOutputsFrom(const std::vector< Layer *> &layers)
static Subgraphs SelectSubgraphs(Graph &graph, const LayerSelectorFunction &selector)
Selects subgraphs from a graph based on the selector function and the algorithm.
Base class for all ArmNN exceptions so that users can filter to just those.
CPU Execution: NEON: ArmCompute.
Iterator end()
Returns iterator pointing to the end of the list. Lowercase for range-based for loops.
void SetTensorInfo(const TensorInfo &tensorInfo) override
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
virtual const TensorInfo & GetTensorInfo() const =0
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
const char * GetName() const override
Returns the name of the layer.
This layer represents a convolution 2d operation.
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
virtual int Connect(IInputSlot &destination)=0
void ForEachLayer(Func func) const
A PreCompiledDescriptor for the PreCompiledLayer.
std::list< Layer * > Layers
size_t GetNumLayers() const
LayerT * InsertNewLayer(InputSlot &insertBefore, Args &&... args)
Inserts a new layer between the output slot currently connected to insertBefore and insertBefore itse...
This layer represents a multiplication operation.
SubgraphView GetWorkingCopy()
This method returns a copy of the original SubgraphView provided by OptimizeSubgraphView with a separ...
static INetworkPtr Create(NetworkOptions networkOptions={})
A DepthwiseConvolution2dDescriptor for the DepthwiseConvolution2dLayer.
const InputSlot * GetConnection(unsigned int index) const override
LayerType
When adding a new layer, adapt also the LastLayer enum value in the enum class LayerType below...