15 #include <doctest/doctest.h> 16 #include <unordered_map> 18 using namespace armnn;
24 struct ExpectedSubgraphSize
26 size_t m_NumInputSlots = 0;
27 size_t m_NumOutputSlots = 0;
28 size_t m_NumLayers = 0;
32 using LayerNameToLayerMap = std::unordered_map<std::string, Layer*>;
36 template <
typename SlotType>
37 SlotType* ConvertReferenceTypeToPointerType(
const SlotType& input)
39 return const_cast<SlotType*
>(&input);
44 template <
typename SlotType>
45 std::vector<SlotType*> ConvertReferenceTypeToPointerType(
const std::vector<SlotType>& input)
47 std::vector<SlotType*> output;
48 std::transform(input.begin(),
50 std::back_inserter(output),
51 [](
const SlotType& inputItem)
53 return ConvertReferenceTypeToPointerType(inputItem);
60 template <
typename SlotType,
typename ResultSlotType>
61 std::vector<ResultSlotType*> ConvertSlotsToISlots(
const std::vector<SlotType*> input)
63 std::vector<ResultSlotType*> output;
64 for (
auto slot : input)
66 output.push_back(PolymorphicDowncast<ResultSlotType*>(slot));
73 const std::string& layerName,
85 const std::string& layerName)
94 LayerNameToLayerMap& layersInGraph,
96 const std::string& layerName,
105 layersInGraph.insert(std::make_pair(convLayer->
GetName(), convLayer));
111 LayerNameToLayerMap& layersInGraph,
113 const std::string& layerName,
119 layersInGraph.insert(std::make_pair(poolingLayer->
GetName(), poolingLayer));
125 LayerNameToLayerMap& layersInGraph,
126 const std::string& layerName,
130 CHECK(additionLayer);
132 layersInGraph.insert(std::make_pair(additionLayer->
GetName(), additionLayer));
133 return additionLayer;
138 const ExpectedSubgraphSize& expectedSubstitutableSubgraphSize,
139 const ExpectedSubgraphSize& expectedReplacementSubgraphSize,
155 CHECK(substitutableSubgraphInputSlots.size() == expectedSubstitutableSubgraphSize.m_NumInputSlots);
156 CHECK(substitutableSubgraphOutputSlots.size() == expectedSubstitutableSubgraphSize.m_NumOutputSlots);
157 CHECK(substitutableSubgraphLayers.size() == expectedSubstitutableSubgraphSize.m_NumLayers);
159 CHECK(
AreEqual(substitutableSubgraphInputSlots, expectedSubstitutableInputSlots));
160 CHECK(
AreEqual(substitutableSubgraphOutputSlots, expectedSubstitutableOutputSlots));
161 CHECK(
AreEqual(substitutableSubgraphLayers, expectedSubstitutableLayers));
163 CHECK(replacementSubgraphInputSlots.size() == expectedReplacementSubgraphSize.m_NumInputSlots);
164 CHECK(replacementSubgraphOutputSlots.size() == expectedReplacementSubgraphSize.m_NumOutputSlots);
165 CHECK(replacementSubgraphLayers.size() == expectedReplacementSubgraphSize.m_NumLayers);
167 CHECK(!
AreEqual(replacementSubgraphInputSlots, expectedSubstitutableInputSlots));
168 CHECK(!
AreEqual(replacementSubgraphOutputSlots, expectedSubstitutableOutputSlots));
169 CHECK(!
AreEqual(replacementSubgraphLayers, expectedSubstitutableLayers));
171 CHECK(std::all_of(replacementSubgraphLayers.begin(),
172 replacementSubgraphLayers.end(),
180 void CheckFailedSubgraph(
const SubgraphView& failedSubgraph,
181 const ExpectedSubgraphSize& expectedFailedSubgraphSize,
190 CHECK(failedSubgraphInputSlots.size() == expectedFailedSubgraphSize.m_NumInputSlots);
191 CHECK(failedSubgraphOutputSlots.size() == expectedFailedSubgraphSize.m_NumOutputSlots);
192 CHECK(failedSubgraphLayers.size() == expectedFailedSubgraphSize.m_NumLayers);
194 CHECK(
AreEqual(failedSubgraphInputSlots, expectedFailedInputSlots));
195 CHECK(
AreEqual(failedSubgraphOutputSlots, expectedFailedOutputSlots));
196 CHECK(
AreEqual(failedSubgraphLayers, expectedFailedLayers));
200 void CheckUntouchedSubgraph(
const SubgraphView& untouchedSubgraph,
201 const ExpectedSubgraphSize& expectedUntouchedSubgraphSize,
210 CHECK(untouchedSubgraphInputSlots.size() == expectedUntouchedSubgraphSize.m_NumInputSlots);
211 CHECK(untouchedSubgraphOutputSlots.size() == expectedUntouchedSubgraphSize.m_NumOutputSlots);
212 CHECK(untouchedSubgraphLayers.size() == expectedUntouchedSubgraphSize.m_NumLayers);
214 CHECK(
AreEqual(untouchedSubgraphInputSlots, expectedUntouchedInputSlots));
215 CHECK(
AreEqual(untouchedSubgraphOutputSlots, expectedUntouchedOutputSlots));
216 CHECK(
AreEqual(untouchedSubgraphLayers, expectedUntouchedLayers));
227 poolingDescriptor.m_PoolWidth = 2;
228 poolingDescriptor.m_PoolHeight = 2;
229 poolingDescriptor.m_StrideX = 2;
230 poolingDescriptor.m_StrideY = 2;
231 poolingDescriptor.m_PadLeft = 1;
232 poolingDescriptor.m_PadRight = 1;
233 poolingDescriptor.m_PadTop = 1;
234 poolingDescriptor.m_PadBottom = 1;
239 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
240 Pooling2dLayer*
const poolingLayer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
241 "pooling layer", outputInfo);
242 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
262 poolingDescriptor.m_PoolWidth = 2;
263 poolingDescriptor.m_PoolHeight = 2;
264 poolingDescriptor.m_StrideX = 2;
265 poolingDescriptor.m_StrideY = 2;
266 poolingDescriptor.m_PadLeft = 1;
267 poolingDescriptor.m_PadRight = 1;
268 poolingDescriptor.m_PadTop = 1;
269 poolingDescriptor.m_PadBottom = 1;
274 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
275 Pooling2dLayer*
const pooling1Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
276 "pooling1 layer", outputInfo);
277 Pooling2dLayer*
const pooling2Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
278 "pooling2 layer", outputInfo);
279 Pooling2dLayer*
const pooling3Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
280 "pooling3 layer", outputInfo);
281 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
306 convolutionDescriptor.m_StrideX = 1;
307 convolutionDescriptor.m_StrideY = 1;
308 convolutionDescriptor.m_BiasEnabled =
true;
312 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
313 Convolution2dLayer*
const convLayer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
314 "conv layer", weightInfo, biasInfo, outputInfo);
315 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
337 convolutionDescriptor.m_StrideY = 1;
338 convolutionDescriptor.m_BiasEnabled =
true;
342 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
343 Convolution2dLayer*
const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
344 "conv1 layer", weightInfo, biasInfo, outputInfo);
345 Convolution2dLayer*
const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
346 "conv2 layer", weightInfo, biasInfo, outputInfo);
347 Convolution2dLayer*
const conv3Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
348 "conv3 layer", weightInfo, biasInfo, outputInfo);
349 Convolution2dLayer*
const conv4Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
350 "conv4 layer", weightInfo, biasInfo, outputInfo);
351 Convolution2dLayer*
const conv5Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
352 "conv5 layer", weightInfo, biasInfo, outputInfo);
353 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
384 convolutionDescriptor.m_StrideY = 1;
385 convolutionDescriptor.m_BiasEnabled =
true;
402 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
403 Convolution2dLayer*
const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
404 "conv1 layer", weightInfo, biasInfo, outputInfo);
405 Pooling2dLayer*
const pooling1Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
406 "pooling1 layer", outputInfo);
407 Pooling2dLayer*
const pooling2Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
408 "pooling2 layer", outputInfo);
409 Convolution2dLayer*
const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
410 "conv2 layer", weightInfo, biasInfo, outputInfo);
411 Pooling2dLayer*
const pooling3Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
412 "pooling3 layer", outputInfo);
413 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
443 convolutionDescriptor.m_StrideY = 1;
444 convolutionDescriptor.m_BiasEnabled =
true;
448 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
449 Convolution2dLayer*
const convLayer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
450 "conv layer unoptimizable", weightInfo, biasInfo,
452 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
474 convolutionDescriptor.m_StrideY = 1;
475 convolutionDescriptor.m_BiasEnabled =
true;
479 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
480 Convolution2dLayer*
const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
481 "conv1 layer", weightInfo, biasInfo, outputInfo);
482 Convolution2dLayer*
const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
483 "conv2 layer unoptimizable", weightInfo, biasInfo,
485 Convolution2dLayer*
const conv3Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
486 "conv3 layer", weightInfo, biasInfo, outputInfo);
487 Convolution2dLayer*
const conv4Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
488 "conv4 layer unoptimizable", weightInfo, biasInfo,
490 Convolution2dLayer*
const conv5Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
491 "conv5 layer", weightInfo, biasInfo, outputInfo);
492 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
523 convolutionDescriptor.m_StrideY = 1;
524 convolutionDescriptor.m_BiasEnabled =
true;
528 Layer*
const input1Layer = AddInputLayer(graph,
"input1 layer", inputInfo, 0);
529 Layer*
const input2Layer = AddInputLayer(graph,
"input2 layer", inputInfo, 1);
530 Convolution2dLayer*
const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
531 "conv1 layer", weightInfo, biasInfo, outputInfo);
532 Convolution2dLayer*
const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
533 "conv2 layer unoptimizable", weightInfo, biasInfo,
535 Convolution2dLayer*
const conv3Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
536 "conv3 layer", weightInfo, biasInfo, outputInfo);
537 AdditionLayer*
const addLayer = AddAdditionaLayer(graph, layersInGraph,
"add layer", outputInfo);
538 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
559 void FullyUnsupporteSubgraphTestImpl1()
562 LayerNameToLayerMap layersInGraph;
566 CHECK((subgraphPtr !=
nullptr));
572 CHECK(subgraphInputSlots.size() == 1);
573 CHECK(subgraphOutputSlots.size() == 1);
574 CHECK(subgraphLayers.size() == 1);
576 CHECK(
Contains(layersInGraph,
"pooling layer"));
581 CHECK((backendObjPtr !=
nullptr));
587 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
607 CHECK(failedSubgraphs.size() == 1);
609 CheckFailedSubgraph(failedSubgraphs.at(0),
610 { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
623 void FullyUnsupporteSubgraphTestImpl2()
626 LayerNameToLayerMap layersInGraph;
630 CHECK((subgraphPtr !=
nullptr));
636 CHECK(subgraphInputSlots.size() == 1);
637 CHECK(subgraphOutputSlots.size() == 1);
638 CHECK(subgraphLayers.size() == 3);
640 CHECK(
Contains(layersInGraph,
"pooling1 layer"));
641 CHECK(
Contains(layersInGraph,
"pooling2 layer"));
642 CHECK(
Contains(layersInGraph,
"pooling3 layer"));
647 CHECK((backendObjPtr !=
nullptr));
653 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
673 CHECK(failedSubgraphs.size() == 1);
675 std::list<IConnectableLayer*> expectedFailedLayers{ layersInGraph.at(
"pooling1 layer"),
676 layersInGraph.at(
"pooling2 layer"),
677 layersInGraph.at(
"pooling3 layer") };
679 const SubgraphView& failedSubgraph = failedSubgraphs.at(0);
681 CheckFailedSubgraph(failedSubgraph,
682 { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
689 CHECK_EQ(failedSubgraphLayers.front() + 0, expectedFailedLayers.front() + 0);
690 CHECK_EQ(failedSubgraphLayers.front() + 1, expectedFailedLayers.front() + 1);
691 CHECK_EQ(failedSubgraphLayers.front() + 2, expectedFailedLayers.front() + 2);
701 void FullyOptimizableSubgraphTestImpl1()
704 LayerNameToLayerMap layersInGraph;
708 CHECK((subgraphPtr !=
nullptr));
714 CHECK(subgraphInputSlots.size() == 1);
715 CHECK(subgraphOutputSlots.size() == 1);
716 CHECK(subgraphLayers.size() == 1);
718 CHECK(
Contains(layersInGraph,
"conv layer"));
723 CHECK((backendObjPtr !=
nullptr));
729 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
743 CHECK(substitutions.size() == 1);
745 CheckSubstitution(substitutions.at(0),
746 { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
747 { subgraphInputSlots.size(), subgraphOutputSlots.size(), 1 },
766 void FullyOptimizableSubgraphTestImpl2()
769 LayerNameToLayerMap layersInGraph;
773 CHECK((subgraphPtr !=
nullptr));
779 CHECK(subgraphPtr->GetIInputSlots().size() == 1);
780 CHECK(subgraphPtr->GetIOutputSlots().size() == 1);
781 CHECK(subgraphPtr->GetIConnectableLayers().size() == 5);
783 CHECK(
Contains(layersInGraph,
"conv1 layer"));
784 CHECK(
Contains(layersInGraph,
"conv2 layer"));
785 CHECK(
Contains(layersInGraph,
"conv3 layer"));
786 CHECK(
Contains(layersInGraph,
"conv4 layer"));
787 CHECK(
Contains(layersInGraph,
"conv5 layer"));
792 CHECK((backendObjPtr !=
nullptr));
798 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
812 CHECK(substitutions.size() == 1);
814 std::list<IConnectableLayer*> expectedSubstitutableLayers{ layersInGraph.at(
"conv1 layer"),
815 layersInGraph.at(
"conv2 layer"),
816 layersInGraph.at(
"conv3 layer"),
817 layersInGraph.at(
"conv4 layer"),
818 layersInGraph.at(
"conv5 layer") };
822 CheckSubstitution(substitution,
823 { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
824 { subgraphInputSlots.size(), subgraphOutputSlots.size(), 1 },
827 expectedSubstitutableLayers);
832 CHECK_EQ(substitutableSubgraphLayers.front() + 0, expectedSubstitutableLayers.front() + 0);
833 CHECK_EQ(substitutableSubgraphLayers.front() + 1, expectedSubstitutableLayers.front() + 1);
834 CHECK_EQ(substitutableSubgraphLayers.front() + 2, expectedSubstitutableLayers.front() + 2);
835 CHECK_EQ(substitutableSubgraphLayers.front() + 3, expectedSubstitutableLayers.front() + 3);
836 CHECK_EQ(substitutableSubgraphLayers.front() + 4, expectedSubstitutableLayers.front() + 4);
853 void PartiallySupportedSubgraphTestImpl()
856 LayerNameToLayerMap layersInGraph;
860 CHECK((subgraphPtr !=
nullptr));
866 CHECK(subgraphInputSlots.size() == 1);
867 CHECK(subgraphOutputSlots.size() == 1);
868 CHECK(subgraphLayers.size() == 5);
870 CHECK(
Contains(layersInGraph,
"conv1 layer"));
871 CHECK(
Contains(layersInGraph,
"pooling1 layer"));
872 CHECK(
Contains(layersInGraph,
"pooling2 layer"));
873 CHECK(
Contains(layersInGraph,
"conv2 layer"));
874 CHECK(
Contains(layersInGraph,
"pooling3 layer"));
879 CHECK((backendObjPtr !=
nullptr));
885 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
899 CHECK(substitutions.size() == 2);
901 std::sort(substitutions.begin(), substitutions.end(), [](
auto s1,
auto s2) {
902 return strcmp(s1.m_SubstitutableSubgraph.GetIConnectableLayers().front()->GetName(),
903 s2.m_SubstitutableSubgraph.GetIConnectableLayers().front()->GetName()) < 0;
906 std::vector<ExpectedSubgraphSize> expectedSubstitutableSubgraphSizes{ { 1, 1, 1 },
908 std::vector<ExpectedSubgraphSize> expectedReplacementSubgraphSizes{ { 1, 1, 1 },
910 std::vector<SubgraphView::IInputSlots> expectedSubstitutableInputSlots
912 ConvertSlotsToISlots<InputSlot, IInputSlot>(
913 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetInputSlots())),
914 ConvertSlotsToISlots<InputSlot, IInputSlot>(
915 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer")->GetInputSlots()))
918 std::vector<SubgraphView::IOutputSlots> expectedSubstitutableOutputSlots
920 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
921 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetOutputSlots())),
922 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
923 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer")->GetOutputSlots()))
925 std::vector<SubgraphView::IConnectableLayers> expectedSubstitutableLayers
927 { layersInGraph.at(
"conv1 layer") },
928 { layersInGraph.at(
"conv2 layer") }
931 for (
size_t substitutionIndex = 0; substitutionIndex < substitutions.size(); substitutionIndex++)
933 CheckSubstitution(substitutions.at(substitutionIndex),
934 expectedSubstitutableSubgraphSizes.at(substitutionIndex),
935 expectedReplacementSubgraphSizes.at(substitutionIndex),
936 expectedSubstitutableInputSlots.at(substitutionIndex),
937 expectedSubstitutableOutputSlots.at(substitutionIndex),
938 expectedSubstitutableLayers.at(substitutionIndex));
946 CHECK(failedSubgraphs.size() == 2);
948 std::sort(failedSubgraphs.begin(), failedSubgraphs.end(), [](
auto s1,
auto s2) {
949 return strcmp(s1.GetIConnectableLayers().front()->GetName(),
950 s2.GetIConnectableLayers().front()->GetName()) < 0;
953 std::vector<ExpectedSubgraphSize> expectedFailedSubgraphSizes{ { 1, 1, 2 },
955 std::vector<SubgraphView::IInputSlots> expectedFailedInputSlots
957 ConvertSlotsToISlots<InputSlot, IInputSlot>(
958 ConvertReferenceTypeToPointerType(layersInGraph.at(
"pooling1 layer")->GetInputSlots())),
959 ConvertSlotsToISlots<InputSlot, IInputSlot>(
960 ConvertReferenceTypeToPointerType(layersInGraph.at(
"pooling3 layer")->GetInputSlots()))
962 std::vector<SubgraphView::IOutputSlots> expectedFailedOutputSlots
964 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
965 ConvertReferenceTypeToPointerType(layersInGraph.at(
"pooling2 layer")->GetOutputSlots())),
966 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
967 ConvertReferenceTypeToPointerType(layersInGraph.at(
"pooling3 layer")->GetOutputSlots()))
969 std::vector<SubgraphView::IConnectableLayers> expectedFailedLayers
971 { layersInGraph.at(
"pooling1 layer"),
972 layersInGraph.at(
"pooling2 layer") },
973 { layersInGraph.at(
"pooling3 layer") }
976 for (
size_t failedIndex = 0; failedIndex < failedSubgraphs.size(); failedIndex++)
978 CheckFailedSubgraph(failedSubgraphs.at(failedIndex),
979 expectedFailedSubgraphSizes.at(failedIndex),
980 expectedFailedInputSlots.at(failedIndex),
981 expectedFailedOutputSlots.at(failedIndex),
982 expectedFailedLayers.at(failedIndex));
993 void FullyUnoptimizableSubgraphTestImpl1()
996 LayerNameToLayerMap layersInGraph;
1000 CHECK((subgraphPtr !=
nullptr));
1006 CHECK(subgraphInputSlots.size() == 1);
1007 CHECK(subgraphOutputSlots.size() == 1);
1008 CHECK(subgraphLayers.size() == 1);
1010 CHECK(
Contains(layersInGraph,
"conv layer unoptimizable"));
1015 CHECK((backendObjPtr !=
nullptr));
1021 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
1047 CHECK(untouchedSubgraphs.size() == 1);
1049 CheckUntouchedSubgraph(untouchedSubgraphs.at(0),
1050 { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
1052 subgraphOutputSlots,
1057 void PartiallyOptimizableSubgraphTestImpl1()
1060 LayerNameToLayerMap layersInGraph;
1064 CHECK((subgraphPtr !=
nullptr));
1070 CHECK(subgraphInputSlots.size() == 1);
1071 CHECK(subgraphOutputSlots.size() == 1);
1072 CHECK(subgraphLayers.size() == 5);
1074 CHECK(
Contains(layersInGraph,
"conv1 layer"));
1075 CHECK(
Contains(layersInGraph,
"conv2 layer unoptimizable"));
1076 CHECK(
Contains(layersInGraph,
"conv3 layer"));
1077 CHECK(
Contains(layersInGraph,
"conv4 layer unoptimizable"));
1078 CHECK(
Contains(layersInGraph,
"conv5 layer"));
1083 CHECK((backendObjPtr !=
nullptr));
1089 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
1103 CHECK(substitutions.size() == 3);
1105 std::sort(substitutions.begin(), substitutions.end(),
1106 [](
auto s1,
auto s2)
1107 {
return strcmp(s1.m_SubstitutableSubgraph.GetIConnectableLayers().front()->GetName(),
1108 s2.m_SubstitutableSubgraph.GetIConnectableLayers().front()->GetName()) < 0; });
1110 std::vector<ExpectedSubgraphSize> expectedSubstitutableSubgraphSizes{ { 1, 1, 1 },
1113 std::vector<ExpectedSubgraphSize> expectedReplacementSubgraphSizes{ { 1, 1, 1 },
1116 std::vector<SubgraphView::IInputSlots> expectedSubstitutableInputSlots
1118 ConvertSlotsToISlots<InputSlot, IInputSlot>(
1119 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetInputSlots())),
1120 ConvertSlotsToISlots<InputSlot, IInputSlot>(
1121 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv3 layer")->GetInputSlots())),
1122 ConvertSlotsToISlots<InputSlot, IInputSlot>(
1123 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv5 layer")->GetInputSlots()))
1125 std::vector<SubgraphView::IOutputSlots> expectedSubstitutableOutputSlots
1127 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1128 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetOutputSlots())),
1129 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1130 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv3 layer")->GetOutputSlots())),
1131 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1132 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv5 layer")->GetOutputSlots()))
1134 std::vector<SubgraphView::IConnectableLayers> expectedSubstitutableLayers
1136 { layersInGraph.at(
"conv1 layer") },
1137 { layersInGraph.at(
"conv3 layer") },
1138 { layersInGraph.at(
"conv5 layer") }
1141 for (
size_t substitutionIndex = 0; substitutionIndex < substitutions.size(); substitutionIndex++)
1143 CheckSubstitution(substitutions.at(substitutionIndex),
1144 expectedSubstitutableSubgraphSizes.at(substitutionIndex),
1145 expectedReplacementSubgraphSizes.at(substitutionIndex),
1146 expectedSubstitutableInputSlots.at(substitutionIndex),
1147 expectedSubstitutableOutputSlots.at(substitutionIndex),
1148 expectedSubstitutableLayers.at(substitutionIndex));
1162 CHECK(untouchedSubgraphs.size() == 2);
1164 std::sort(untouchedSubgraphs.begin(), untouchedSubgraphs.end(), [](
auto s1,
auto s2) {
1165 return strcmp(s1.GetIConnectableLayers().front()->GetName(),
1166 s2.GetIConnectableLayers().front()->GetName()) < 0;
1169 std::vector<ExpectedSubgraphSize> expectedUntouchedSubgraphSizes{ { 1, 1, 1 },
1171 std::vector<SubgraphView::IInputSlots> expectedUntouchedInputSlots
1173 ConvertSlotsToISlots<InputSlot, IInputSlot>(
1174 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer unoptimizable")->GetInputSlots())),
1175 ConvertSlotsToISlots<InputSlot, IInputSlot>(
1176 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv4 layer unoptimizable")->GetInputSlots()))
1178 std::vector<SubgraphView::IOutputSlots> expectedUntouchedOutputSlots
1180 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1181 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer unoptimizable")->GetOutputSlots())),
1182 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1183 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv4 layer unoptimizable")->GetOutputSlots()))
1185 std::vector<SubgraphView::IConnectableLayers> expectedUntouchedLayers
1187 { layersInGraph.at(
"conv2 layer unoptimizable") },
1188 { layersInGraph.at(
"conv4 layer unoptimizable") }
1191 for (
size_t untouchedIndex = 0; untouchedIndex < untouchedSubgraphs.size(); untouchedIndex++)
1193 CheckUntouchedSubgraph(untouchedSubgraphs.at(untouchedIndex),
1194 expectedUntouchedSubgraphSizes.at(untouchedIndex),
1195 expectedUntouchedInputSlots.at(untouchedIndex),
1196 expectedUntouchedOutputSlots.at(untouchedIndex),
1197 expectedUntouchedLayers.at(untouchedIndex));
1203 void PartiallyOptimizableSubgraphTestImpl2()
1206 LayerNameToLayerMap layersInGraph;
1210 CHECK((subgraphPtr !=
nullptr));
1216 CHECK(subgraphInputSlots.size() == 2);
1217 CHECK(subgraphOutputSlots.size() == 1);
1218 CHECK(subgraphLayers.size() == 4);
1220 CHECK(
Contains(layersInGraph,
"conv1 layer"));
1221 CHECK(
Contains(layersInGraph,
"conv2 layer unoptimizable"));
1222 CHECK(
Contains(layersInGraph,
"conv3 layer"));
1223 CHECK(
Contains(layersInGraph,
"add layer"));
1228 CHECK((backendObjPtr !=
nullptr));
1234 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
1248 CHECK(substitutions.size() == 1);
1250 ExpectedSubgraphSize expectedSubstitutableSubgraphSizes{ 2, 1, 3 };
1251 ExpectedSubgraphSize expectedReplacementSubgraphSizes{ 2, 1, 1 };
1255 ConvertSlotsToISlots<InputSlot, IInputSlot>({
1256 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetInputSlots()[0])})[0],
1257 ConvertSlotsToISlots<InputSlot, IInputSlot>({
1258 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv3 layer")->GetInputSlots()[0])})[0]
1263 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1264 ConvertReferenceTypeToPointerType(layersInGraph.at(
"add layer")->GetOutputSlots()))
1269 layersInGraph.at(
"conv1 layer"),
1270 layersInGraph.at(
"conv3 layer"),
1271 layersInGraph.at(
"add layer")
1274 CheckSubstitution(substitutions[0],
1275 expectedSubstitutableSubgraphSizes,
1276 expectedReplacementSubgraphSizes,
1277 expectedSubstitutableInputSlots,
1278 expectedSubstitutableOutputSlots,
1279 expectedSubstitutableLayers);
1292 CHECK(untouchedSubgraphs.size() == 1);
1294 std::vector<ExpectedSubgraphSize> expectedUntouchedSubgraphSizes{ { 1, 1, 1 } };
1295 std::vector<SubgraphView::IInputSlots> expectedUntouchedInputSlots
1297 ConvertSlotsToISlots<InputSlot, IInputSlot>(
1298 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer unoptimizable")->GetInputSlots()))
1300 std::vector<SubgraphView::IOutputSlots> expectedUntouchedOutputSlots
1302 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1303 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer unoptimizable")->GetOutputSlots()))
1305 std::vector<SubgraphView::IConnectableLayers> expectedUntouchedLayers
1307 { layersInGraph.at(
"conv2 layer unoptimizable") }
1310 for (
size_t untouchedIndex = 0; untouchedIndex < untouchedSubgraphs.size(); untouchedIndex++)
1312 CheckUntouchedSubgraph(untouchedSubgraphs.at(untouchedIndex),
1313 expectedUntouchedSubgraphSizes.at(untouchedIndex),
1314 expectedUntouchedInputSlots.at(untouchedIndex),
1315 expectedUntouchedOutputSlots.at(untouchedIndex),
1316 expectedUntouchedLayers.at(untouchedIndex));
1324 TEST_CASE(
"FullyUnsupportedSubgraph1") { FullyUnsupporteSubgraphTestImpl1(); }
1325 TEST_CASE(
"FullyUnsupportedSubgraph2") { FullyUnsupporteSubgraphTestImpl2(); }
1326 TEST_CASE(
"FullyOptimizableSubgraph1") { FullyOptimizableSubgraphTestImpl1(); }
1327 TEST_CASE(
"FullyOptimizableSubgraph2") { FullyOptimizableSubgraphTestImpl2(); }
1328 TEST_CASE(
"PartiallySupportedSubgraph") { PartiallySupportedSubgraphTestImpl(); }
1329 TEST_CASE(
"FullyUnoptimizableSubgraph") { FullyUnoptimizableSubgraphTestImpl1(); }
1330 TEST_CASE(
"PartiallyOptimizableSubgraph1") { PartiallyOptimizableSubgraphTestImpl1(); }
1331 TEST_CASE(
"PartiallyOptimizableSubgraph2") { PartiallyOptimizableSubgraphTestImpl2(); }
TEST_SUITE("TestConstTensorLayerVisitor")
bool Contains(const CollectionType &collection, const typename CollectionType::value_type &item)
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
uint32_t m_PadBottom
Padding bottom value in the height dimension.
const IOutputSlots & GetIOutputSlots() const
constexpr const char * MockBackendId()
uint32_t m_PadLeft
Padding left value in the width dimension.
const IConnectableLayers & GetIConnectableLayers() const
const IInputSlots & GetIInputSlots() const
LayerT * AddLayer(Args &&... args)
Adds a new layer, of type LayerType, to the graph constructed with the arguments passed.
uint32_t m_PoolWidth
Pooling width value.
A Convolution2dDescriptor for the Convolution2dLayer.
int Connect(InputSlot &destination)
The padding fields don't count and are ignored.
PaddingMethod m_PaddingMethod
The padding method to be used. (Exclude, IgnoreValue).
uint32_t m_PadTop
Padding top value in the height dimension.
std::vector< SubgraphView > Subgraphs
std::vector< SubstitutionPair > Substitutions
Copyright (c) 2021 ARM Limited and Contributors.
SubgraphView m_SubstitutableSubgraph
Subgraph of Layers from the original graph which should be replaced.
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
The SubgraphView class represents a subgraph of a Graph.
uint32_t m_PoolHeight
Pooling height value.
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
A layer user-provided data can be bound to (e.g. inputs, outputs).
std::unique_ptr< SubgraphView > SubgraphViewPtr
std::list< IConnectableLayer * > IConnectableLayers
uint32_t m_PadRight
Padding right value in the width dimension.
SubgraphView::InputSlots CreateInputsFrom(const std::vector< Layer *> &layers)
std::vector< IOutputSlot * > IOutputSlots
const Subgraphs & GetUntouchedSubgraphs() const
const Subgraphs & GetFailedSubgraphs() const
SubgraphView m_ReplacementSubgraph
A subgraph of new layers which will replace layers in m_SubstitutableSubgraph.
std::vector< IInputSlot * > IInputSlots
void SetWeightAndBias(ConvolutionLayer *layer, const armnn::TensorInfo &weightInfo, const armnn::TensorInfo &biasInfo)
This layer represents a pooling 2d operation.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
This layer represents an addition operation.
const Substitutions & GetSubstitutions() const
std::unique_ptr< SubgraphView > SubgraphViewPtr
bool AreEqual(const CollectionType &lhs, const CollectionType &rhs)
SubgraphView::SubgraphViewPtr CreateSubgraphViewFrom(SubgraphView::InputSlots &&inputs, SubgraphView::OutputSlots &&outputs, SubgraphView::Layers &&layers)
SubgraphView::OutputSlots CreateOutputsFrom(const std::vector< Layer *> &layers)
PoolingAlgorithm m_PoolType
The pooling algorithm to use (Max. Average, L2).
void SetTensorInfo(const TensorInfo &tensorInfo) override
armnn::IBackendInternalUniquePtr CreateBackendObject(const armnn::BackendId &backendId)
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
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.
A Pooling2dDescriptor for the Pooling2dLayer.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.