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);
61 const std::string& layerName,
73 const std::string& layerName)
82 LayerNameToLayerMap& layersInGraph,
84 const std::string& layerName,
93 layersInGraph.insert(std::make_pair(convLayer->
GetName(), convLayer));
99 LayerNameToLayerMap& layersInGraph,
101 const std::string& layerName,
107 layersInGraph.insert(std::make_pair(poolingLayer->
GetName(), poolingLayer));
113 LayerNameToLayerMap& layersInGraph,
114 const std::string& layerName,
118 CHECK(additionLayer);
120 layersInGraph.insert(std::make_pair(additionLayer->
GetName(), additionLayer));
121 return additionLayer;
126 const ExpectedSubgraphSize& expectedSubstitutableSubgraphSize,
127 const ExpectedSubgraphSize& expectedReplacementSubgraphSize,
142 CHECK(substitutableSubgraphInputSlots.size() == expectedSubstitutableSubgraphSize.m_NumInputSlots);
143 CHECK(substitutableSubgraphOutputSlots.size() == expectedSubstitutableSubgraphSize.m_NumOutputSlots);
144 CHECK(substitutableSubgraphLayers.size() == expectedSubstitutableSubgraphSize.m_NumLayers);
146 CHECK(
AreEqual(substitutableSubgraphInputSlots, expectedSubstitutableInputSlots));
147 CHECK(
AreEqual(substitutableSubgraphOutputSlots, expectedSubstitutableOutputSlots));
148 CHECK(
AreEqual(substitutableSubgraphLayers, expectedSubstitutableLayers));
150 CHECK(replacementSubgraphInputSlots.size() == expectedReplacementSubgraphSize.m_NumInputSlots);
151 CHECK(replacementSubgraphOutputSlots.size() == expectedReplacementSubgraphSize.m_NumOutputSlots);
152 CHECK(replacementSubgraphLayers.size() == expectedReplacementSubgraphSize.m_NumLayers);
154 CHECK(!
AreEqual(replacementSubgraphInputSlots, expectedSubstitutableInputSlots));
155 CHECK(!
AreEqual(replacementSubgraphOutputSlots, expectedSubstitutableOutputSlots));
156 CHECK(!
AreEqual(replacementSubgraphLayers, expectedSubstitutableLayers));
158 CHECK(std::all_of(replacementSubgraphLayers.begin(),
159 replacementSubgraphLayers.end(),
160 [](
const Layer* layer)
167 void CheckFailedSubgraph(
const SubgraphView& failedSubgraph,
168 const ExpectedSubgraphSize& expectedFailedSubgraphSize,
177 CHECK(failedSubgraphInputSlots.size() == expectedFailedSubgraphSize.m_NumInputSlots);
178 CHECK(failedSubgraphOutputSlots.size() == expectedFailedSubgraphSize.m_NumOutputSlots);
179 CHECK(failedSubgraphLayers.size() == expectedFailedSubgraphSize.m_NumLayers);
181 CHECK(
AreEqual(failedSubgraphInputSlots, expectedFailedInputSlots));
182 CHECK(
AreEqual(failedSubgraphOutputSlots, expectedFailedOutputSlots));
183 CHECK(
AreEqual(failedSubgraphLayers, expectedFailedLayers));
187 void CheckUntouchedSubgraph(
const SubgraphView& untouchedSubgraph,
188 const ExpectedSubgraphSize& expectedUntouchedSubgraphSize,
197 CHECK(untouchedSubgraphInputSlots.size() == expectedUntouchedSubgraphSize.m_NumInputSlots);
198 CHECK(untouchedSubgraphOutputSlots.size() == expectedUntouchedSubgraphSize.m_NumOutputSlots);
199 CHECK(untouchedSubgraphLayers.size() == expectedUntouchedSubgraphSize.m_NumLayers);
201 CHECK(
AreEqual(untouchedSubgraphInputSlots, expectedUntouchedInputSlots));
202 CHECK(
AreEqual(untouchedSubgraphOutputSlots, expectedUntouchedOutputSlots));
203 CHECK(
AreEqual(untouchedSubgraphLayers, expectedUntouchedLayers));
214 poolingDescriptor.m_PoolWidth = 2;
215 poolingDescriptor.m_PoolHeight = 2;
216 poolingDescriptor.m_StrideX = 2;
217 poolingDescriptor.m_StrideY = 2;
218 poolingDescriptor.m_PadLeft = 1;
219 poolingDescriptor.m_PadRight = 1;
220 poolingDescriptor.m_PadTop = 1;
221 poolingDescriptor.m_PadBottom = 1;
226 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
227 Pooling2dLayer*
const poolingLayer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
228 "pooling layer", outputInfo);
229 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
249 poolingDescriptor.m_PoolWidth = 2;
250 poolingDescriptor.m_PoolHeight = 2;
251 poolingDescriptor.m_StrideX = 2;
252 poolingDescriptor.m_StrideY = 2;
253 poolingDescriptor.m_PadLeft = 1;
254 poolingDescriptor.m_PadRight = 1;
255 poolingDescriptor.m_PadTop = 1;
256 poolingDescriptor.m_PadBottom = 1;
261 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
262 Pooling2dLayer*
const pooling1Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
263 "pooling1 layer", outputInfo);
264 Pooling2dLayer*
const pooling2Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
265 "pooling2 layer", outputInfo);
266 Pooling2dLayer*
const pooling3Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
267 "pooling3 layer", outputInfo);
268 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
293 convolutionDescriptor.m_StrideX = 1;
294 convolutionDescriptor.m_StrideY = 1;
295 convolutionDescriptor.m_BiasEnabled =
true;
299 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
300 Convolution2dLayer*
const convLayer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
301 "conv layer", weightInfo, biasInfo, outputInfo);
302 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
324 convolutionDescriptor.m_StrideY = 1;
325 convolutionDescriptor.m_BiasEnabled =
true;
329 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
330 Convolution2dLayer*
const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
331 "conv1 layer", weightInfo, biasInfo, outputInfo);
332 Convolution2dLayer*
const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
333 "conv2 layer", weightInfo, biasInfo, outputInfo);
334 Convolution2dLayer*
const conv3Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
335 "conv3 layer", weightInfo, biasInfo, outputInfo);
336 Convolution2dLayer*
const conv4Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
337 "conv4 layer", weightInfo, biasInfo, outputInfo);
338 Convolution2dLayer*
const conv5Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
339 "conv5 layer", weightInfo, biasInfo, outputInfo);
340 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
371 convolutionDescriptor.m_StrideY = 1;
372 convolutionDescriptor.m_BiasEnabled =
true;
389 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
390 Convolution2dLayer*
const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
391 "conv1 layer", weightInfo, biasInfo, outputInfo);
392 Pooling2dLayer*
const pooling1Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
393 "pooling1 layer", outputInfo);
394 Pooling2dLayer*
const pooling2Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
395 "pooling2 layer", outputInfo);
396 Convolution2dLayer*
const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
397 "conv2 layer", weightInfo, biasInfo, outputInfo);
398 Pooling2dLayer*
const pooling3Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
399 "pooling3 layer", outputInfo);
400 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
430 convolutionDescriptor.m_StrideY = 1;
431 convolutionDescriptor.m_BiasEnabled =
true;
435 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
436 Convolution2dLayer*
const convLayer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
437 "conv layer unoptimizable", weightInfo, biasInfo,
439 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
461 convolutionDescriptor.m_StrideY = 1;
462 convolutionDescriptor.m_BiasEnabled =
true;
466 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
467 Convolution2dLayer*
const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
468 "conv1 layer", weightInfo, biasInfo, outputInfo);
469 Convolution2dLayer*
const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
470 "conv2 layer unoptimizable", weightInfo, biasInfo,
472 Convolution2dLayer*
const conv3Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
473 "conv3 layer", weightInfo, biasInfo, outputInfo);
474 Convolution2dLayer*
const conv4Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
475 "conv4 layer unoptimizable", weightInfo, biasInfo,
477 Convolution2dLayer*
const conv5Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
478 "conv5 layer", weightInfo, biasInfo, outputInfo);
479 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
510 convolutionDescriptor.m_StrideY = 1;
511 convolutionDescriptor.m_BiasEnabled =
true;
515 Layer*
const input1Layer = AddInputLayer(graph,
"input1 layer", inputInfo, 0);
516 Layer*
const input2Layer = AddInputLayer(graph,
"input2 layer", inputInfo, 1);
517 Convolution2dLayer*
const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
518 "conv1 layer", weightInfo, biasInfo, outputInfo);
519 Convolution2dLayer*
const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
520 "conv2 layer unoptimizable", weightInfo, biasInfo,
522 Convolution2dLayer*
const conv3Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
523 "conv3 layer", weightInfo, biasInfo, outputInfo);
524 AdditionLayer*
const addLayer = AddAdditionaLayer(graph, layersInGraph,
"add layer", outputInfo);
525 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
546 void FullyUnsupporteSubgraphTestImpl1()
549 LayerNameToLayerMap layersInGraph;
553 CHECK((subgraphPtr !=
nullptr));
559 CHECK(subgraphInputSlots.size() == 1);
560 CHECK(subgraphOutputSlots.size() == 1);
561 CHECK(subgraphLayers.size() == 1);
563 CHECK(
Contains(layersInGraph,
"pooling layer"));
568 CHECK((backendObjPtr !=
nullptr));
574 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
594 CHECK(failedSubgraphs.size() == 1);
596 CheckFailedSubgraph(failedSubgraphs.at(0),
597 { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
610 void FullyUnsupporteSubgraphTestImpl2()
613 LayerNameToLayerMap layersInGraph;
617 CHECK((subgraphPtr !=
nullptr));
623 CHECK(subgraphInputSlots.size() == 1);
624 CHECK(subgraphOutputSlots.size() == 1);
625 CHECK(subgraphLayers.size() == 3);
627 CHECK(
Contains(layersInGraph,
"pooling1 layer"));
628 CHECK(
Contains(layersInGraph,
"pooling2 layer"));
629 CHECK(
Contains(layersInGraph,
"pooling3 layer"));
634 CHECK((backendObjPtr !=
nullptr));
640 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
660 CHECK(failedSubgraphs.size() == 1);
662 std::list<Layer*> expectedFailedLayers{ layersInGraph.at(
"pooling1 layer"),
663 layersInGraph.at(
"pooling2 layer"),
664 layersInGraph.at(
"pooling3 layer") };
666 const SubgraphView& failedSubgraph = failedSubgraphs.at(0);
668 CheckFailedSubgraph(failedSubgraph,
669 { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
676 CHECK_EQ(failedSubgraphLayers.front() + 0, expectedFailedLayers.front() + 0);
677 CHECK_EQ(failedSubgraphLayers.front() + 1, expectedFailedLayers.front() + 1);
678 CHECK_EQ(failedSubgraphLayers.front() + 2, expectedFailedLayers.front() + 2);
688 void FullyOptimizableSubgraphTestImpl1()
691 LayerNameToLayerMap layersInGraph;
695 CHECK((subgraphPtr !=
nullptr));
701 CHECK(subgraphInputSlots.size() == 1);
702 CHECK(subgraphOutputSlots.size() == 1);
703 CHECK(subgraphLayers.size() == 1);
705 CHECK(
Contains(layersInGraph,
"conv layer"));
710 CHECK((backendObjPtr !=
nullptr));
716 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
730 CHECK(substitutions.size() == 1);
732 CheckSubstitution(substitutions.at(0),
733 { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
734 { subgraphInputSlots.size(), subgraphOutputSlots.size(), 1 },
753 void FullyOptimizableSubgraphTestImpl2()
756 LayerNameToLayerMap layersInGraph;
760 CHECK((subgraphPtr !=
nullptr));
766 CHECK(subgraphPtr->GetInputSlots().size() == 1);
767 CHECK(subgraphPtr->GetOutputSlots().size() == 1);
768 CHECK(subgraphPtr->GetLayers().size() == 5);
770 CHECK(
Contains(layersInGraph,
"conv1 layer"));
771 CHECK(
Contains(layersInGraph,
"conv2 layer"));
772 CHECK(
Contains(layersInGraph,
"conv3 layer"));
773 CHECK(
Contains(layersInGraph,
"conv4 layer"));
774 CHECK(
Contains(layersInGraph,
"conv5 layer"));
779 CHECK((backendObjPtr !=
nullptr));
785 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
799 CHECK(substitutions.size() == 1);
801 std::list<Layer*> expectedSubstitutableLayers{ layersInGraph.at(
"conv1 layer"),
802 layersInGraph.at(
"conv2 layer"),
803 layersInGraph.at(
"conv3 layer"),
804 layersInGraph.at(
"conv4 layer"),
805 layersInGraph.at(
"conv5 layer") };
809 CheckSubstitution(substitution,
810 { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
811 { subgraphInputSlots.size(), subgraphOutputSlots.size(), 1 },
814 expectedSubstitutableLayers);
818 CHECK_EQ(substitutableSubgraphLayers.front() + 0, expectedSubstitutableLayers.front() + 0);
819 CHECK_EQ(substitutableSubgraphLayers.front() + 1, expectedSubstitutableLayers.front() + 1);
820 CHECK_EQ(substitutableSubgraphLayers.front() + 2, expectedSubstitutableLayers.front() + 2);
821 CHECK_EQ(substitutableSubgraphLayers.front() + 3, expectedSubstitutableLayers.front() + 3);
822 CHECK_EQ(substitutableSubgraphLayers.front() + 4, expectedSubstitutableLayers.front() + 4);
839 void PartiallySupportedSubgraphTestImpl()
842 LayerNameToLayerMap layersInGraph;
846 CHECK((subgraphPtr !=
nullptr));
852 CHECK(subgraphInputSlots.size() == 1);
853 CHECK(subgraphOutputSlots.size() == 1);
854 CHECK(subgraphLayers.size() == 5);
856 CHECK(
Contains(layersInGraph,
"conv1 layer"));
857 CHECK(
Contains(layersInGraph,
"pooling1 layer"));
858 CHECK(
Contains(layersInGraph,
"pooling2 layer"));
859 CHECK(
Contains(layersInGraph,
"conv2 layer"));
860 CHECK(
Contains(layersInGraph,
"pooling3 layer"));
865 CHECK((backendObjPtr !=
nullptr));
871 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
885 CHECK(substitutions.size() == 2);
887 std::sort(substitutions.begin(), substitutions.end(), [](
auto s1,
auto s2) {
888 return strcmp(s1.m_SubstitutableSubgraph.GetLayers().front()->GetName(),
889 s2.m_SubstitutableSubgraph.GetLayers().front()->GetName()) < 0;
892 std::vector<ExpectedSubgraphSize> expectedSubstitutableSubgraphSizes{ { 1, 1, 1 },
894 std::vector<ExpectedSubgraphSize> expectedReplacementSubgraphSizes{ { 1, 1, 1 },
896 std::vector<SubgraphView::InputSlots> expectedSubstitutableInputSlots
898 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetInputSlots()),
899 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer")->GetInputSlots())
901 std::vector<SubgraphView::OutputSlots> expectedSubstitutableOutputSlots
903 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetOutputSlots()),
904 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer")->GetOutputSlots())
906 std::vector<SubgraphView::Layers> expectedSubstitutableLayers
908 { layersInGraph.at(
"conv1 layer") },
909 { layersInGraph.at(
"conv2 layer") }
912 for (
size_t substitutionIndex = 0; substitutionIndex < substitutions.size(); substitutionIndex++)
914 CheckSubstitution(substitutions.at(substitutionIndex),
915 expectedSubstitutableSubgraphSizes.at(substitutionIndex),
916 expectedReplacementSubgraphSizes.at(substitutionIndex),
917 expectedSubstitutableInputSlots.at(substitutionIndex),
918 expectedSubstitutableOutputSlots.at(substitutionIndex),
919 expectedSubstitutableLayers.at(substitutionIndex));
927 CHECK(failedSubgraphs.size() == 2);
929 std::sort(failedSubgraphs.begin(), failedSubgraphs.end(), [](
auto s1,
auto s2) {
930 return strcmp(s1.GetLayers().front()->GetName(), s2.GetLayers().front()->GetName()) < 0;
933 std::vector<ExpectedSubgraphSize> expectedFailedSubgraphSizes{ { 1, 1, 2 },
935 std::vector<SubgraphView::InputSlots> expectedFailedInputSlots
937 ConvertReferenceTypeToPointerType(layersInGraph.at(
"pooling1 layer")->GetInputSlots()),
938 ConvertReferenceTypeToPointerType(layersInGraph.at(
"pooling3 layer")->GetInputSlots())
940 std::vector<SubgraphView::OutputSlots> expectedFailedOutputSlots
942 ConvertReferenceTypeToPointerType(layersInGraph.at(
"pooling2 layer")->GetOutputSlots()),
943 ConvertReferenceTypeToPointerType(layersInGraph.at(
"pooling3 layer")->GetOutputSlots())
945 std::vector<SubgraphView::Layers> expectedFailedLayers
947 { layersInGraph.at(
"pooling1 layer"),
948 layersInGraph.at(
"pooling2 layer") },
949 { layersInGraph.at(
"pooling3 layer") }
952 for (
size_t failedIndex = 0; failedIndex < failedSubgraphs.size(); failedIndex++)
954 CheckFailedSubgraph(failedSubgraphs.at(failedIndex),
955 expectedFailedSubgraphSizes.at(failedIndex),
956 expectedFailedInputSlots.at(failedIndex),
957 expectedFailedOutputSlots.at(failedIndex),
958 expectedFailedLayers.at(failedIndex));
969 void FullyUnoptimizableSubgraphTestImpl1()
972 LayerNameToLayerMap layersInGraph;
976 CHECK((subgraphPtr !=
nullptr));
982 CHECK(subgraphInputSlots.size() == 1);
983 CHECK(subgraphOutputSlots.size() == 1);
984 CHECK(subgraphLayers.size() == 1);
986 CHECK(
Contains(layersInGraph,
"conv layer unoptimizable"));
991 CHECK((backendObjPtr !=
nullptr));
997 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
1023 CHECK(untouchedSubgraphs.size() == 1);
1025 CheckUntouchedSubgraph(untouchedSubgraphs.at(0),
1026 { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
1028 subgraphOutputSlots,
1033 void PartiallyOptimizableSubgraphTestImpl1()
1036 LayerNameToLayerMap layersInGraph;
1040 CHECK((subgraphPtr !=
nullptr));
1046 CHECK(subgraphInputSlots.size() == 1);
1047 CHECK(subgraphOutputSlots.size() == 1);
1048 CHECK(subgraphLayers.size() == 5);
1050 CHECK(
Contains(layersInGraph,
"conv1 layer"));
1051 CHECK(
Contains(layersInGraph,
"conv2 layer unoptimizable"));
1052 CHECK(
Contains(layersInGraph,
"conv3 layer"));
1053 CHECK(
Contains(layersInGraph,
"conv4 layer unoptimizable"));
1054 CHECK(
Contains(layersInGraph,
"conv5 layer"));
1059 CHECK((backendObjPtr !=
nullptr));
1065 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
1079 CHECK(substitutions.size() == 3);
1081 std::sort(substitutions.begin(), substitutions.end(),
1082 [](
auto s1,
auto s2) {
return strcmp(s1.m_SubstitutableSubgraph.GetLayers().front()->GetName(),
1083 s2.m_SubstitutableSubgraph.GetLayers().front()->GetName()) < 0; });
1085 std::vector<ExpectedSubgraphSize> expectedSubstitutableSubgraphSizes{ { 1, 1, 1 },
1088 std::vector<ExpectedSubgraphSize> expectedReplacementSubgraphSizes{ { 1, 1, 1 },
1091 std::vector<SubgraphView::InputSlots> expectedSubstitutableInputSlots
1093 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetInputSlots()),
1094 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv3 layer")->GetInputSlots()),
1095 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv5 layer")->GetInputSlots())
1097 std::vector<SubgraphView::OutputSlots> expectedSubstitutableOutputSlots
1099 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetOutputSlots()),
1100 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv3 layer")->GetOutputSlots()),
1101 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv5 layer")->GetOutputSlots())
1103 std::vector<SubgraphView::Layers> expectedSubstitutableLayers
1105 { layersInGraph.at(
"conv1 layer") },
1106 { layersInGraph.at(
"conv3 layer") },
1107 { layersInGraph.at(
"conv5 layer") }
1110 for (
size_t substitutionIndex = 0; substitutionIndex < substitutions.size(); substitutionIndex++)
1112 CheckSubstitution(substitutions.at(substitutionIndex),
1113 expectedSubstitutableSubgraphSizes.at(substitutionIndex),
1114 expectedReplacementSubgraphSizes.at(substitutionIndex),
1115 expectedSubstitutableInputSlots.at(substitutionIndex),
1116 expectedSubstitutableOutputSlots.at(substitutionIndex),
1117 expectedSubstitutableLayers.at(substitutionIndex));
1131 CHECK(untouchedSubgraphs.size() == 2);
1133 std::sort(untouchedSubgraphs.begin(), untouchedSubgraphs.end(), [](
auto s1,
auto s2) {
1134 return strcmp(s1.GetLayers().front()->GetName(), s2.GetLayers().front()->GetName()) < 0;
1137 std::vector<ExpectedSubgraphSize> expectedUntouchedSubgraphSizes{ { 1, 1, 1 },
1139 std::vector<SubgraphView::InputSlots> expectedUntouchedInputSlots
1141 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer unoptimizable")->GetInputSlots()),
1142 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv4 layer unoptimizable")->GetInputSlots())
1144 std::vector<SubgraphView::OutputSlots> expectedUntouchedOutputSlots
1146 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer unoptimizable")->GetOutputSlots()),
1147 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv4 layer unoptimizable")->GetOutputSlots())
1149 std::vector<SubgraphView::Layers> expectedUntouchedLayers
1151 { layersInGraph.at(
"conv2 layer unoptimizable") },
1152 { layersInGraph.at(
"conv4 layer unoptimizable") }
1155 for (
size_t untouchedIndex = 0; untouchedIndex < untouchedSubgraphs.size(); untouchedIndex++)
1157 CheckUntouchedSubgraph(untouchedSubgraphs.at(untouchedIndex),
1158 expectedUntouchedSubgraphSizes.at(untouchedIndex),
1159 expectedUntouchedInputSlots.at(untouchedIndex),
1160 expectedUntouchedOutputSlots.at(untouchedIndex),
1161 expectedUntouchedLayers.at(untouchedIndex));
1167 void PartiallyOptimizableSubgraphTestImpl2()
1170 LayerNameToLayerMap layersInGraph;
1174 CHECK((subgraphPtr !=
nullptr));
1180 CHECK(subgraphInputSlots.size() == 2);
1181 CHECK(subgraphOutputSlots.size() == 1);
1182 CHECK(subgraphLayers.size() == 4);
1184 CHECK(
Contains(layersInGraph,
"conv1 layer"));
1185 CHECK(
Contains(layersInGraph,
"conv2 layer unoptimizable"));
1186 CHECK(
Contains(layersInGraph,
"conv3 layer"));
1187 CHECK(
Contains(layersInGraph,
"add layer"));
1192 CHECK((backendObjPtr !=
nullptr));
1198 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
1212 CHECK(substitutions.size() == 1);
1214 ExpectedSubgraphSize expectedSubstitutableSubgraphSizes{ 2, 1, 3 };
1215 ExpectedSubgraphSize expectedReplacementSubgraphSizes{ 2, 1, 1 };
1218 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetInputSlots()[0]),
1219 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv3 layer")->GetInputSlots()[0])
1223 ConvertReferenceTypeToPointerType(layersInGraph.at(
"add layer")->GetOutputSlots()[0])
1227 layersInGraph.at(
"conv1 layer"),
1228 layersInGraph.at(
"conv3 layer"),
1229 layersInGraph.at(
"add layer")
1232 CheckSubstitution(substitutions[0],
1233 expectedSubstitutableSubgraphSizes,
1234 expectedReplacementSubgraphSizes,
1235 expectedSubstitutableInputSlots,
1236 expectedSubstitutableOutputSlots,
1237 expectedSubstitutableLayers);
1250 CHECK(untouchedSubgraphs.size() == 1);
1252 std::vector<ExpectedSubgraphSize> expectedUntouchedSubgraphSizes{ { 1, 1, 1 } };
1253 std::vector<SubgraphView::InputSlots> expectedUntouchedInputSlots
1255 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer unoptimizable")->GetInputSlots())
1257 std::vector<SubgraphView::OutputSlots> expectedUntouchedOutputSlots
1259 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer unoptimizable")->GetOutputSlots())
1261 std::vector<SubgraphView::Layers> expectedUntouchedLayers
1263 { layersInGraph.at(
"conv2 layer unoptimizable") }
1266 for (
size_t untouchedIndex = 0; untouchedIndex < untouchedSubgraphs.size(); untouchedIndex++)
1268 CheckUntouchedSubgraph(untouchedSubgraphs.at(untouchedIndex),
1269 expectedUntouchedSubgraphSizes.at(untouchedIndex),
1270 expectedUntouchedInputSlots.at(untouchedIndex),
1271 expectedUntouchedOutputSlots.at(untouchedIndex),
1272 expectedUntouchedLayers.at(untouchedIndex));
1280 TEST_CASE(
"FullyUnsupportedSubgraph1") { FullyUnsupporteSubgraphTestImpl1(); }
1281 TEST_CASE(
"FullyUnsupportedSubgraph2") { FullyUnsupporteSubgraphTestImpl2(); }
1282 TEST_CASE(
"FullyOptimizableSubgraph1") { FullyOptimizableSubgraphTestImpl1(); }
1283 TEST_CASE(
"FullyOptimizableSubgraph2") { FullyOptimizableSubgraphTestImpl2(); }
1284 TEST_CASE(
"PartiallySupportedSubgraph") { PartiallySupportedSubgraphTestImpl(); }
1285 TEST_CASE(
"FullyUnoptimizableSubgraph") { FullyUnoptimizableSubgraphTestImpl1(); }
1286 TEST_CASE(
"PartiallyOptimizableSubgraph1") { PartiallyOptimizableSubgraphTestImpl1(); }
1287 TEST_CASE(
"PartiallyOptimizableSubgraph2") { PartiallyOptimizableSubgraphTestImpl2(); }
TEST_SUITE("TestConstTensorLayerVisitor")
uint32_t m_PadBottom
Padding bottom value in the height dimension.
uint32_t m_PadLeft
Padding left value in the width dimension.
LayerT * AddLayer(Args &&... args)
Adds a new layer, of type LayerType, to the graph constructed with the arguments passed.
bool AreEqual(const CollectionType &lhs, const CollectionType &rhs)
uint32_t m_PoolWidth
Pooling width value.
A Convolution2dDescriptor for the Convolution2dLayer.
int Connect(InputSlot &destination)
std::vector< OutputSlot * > OutputSlots
The padding fields don't count and are ignored.
PaddingMethod m_PaddingMethod
The padding method to be used. (Exclude, IgnoreValue).
constexpr const char * MockBackendId()
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
uint32_t m_PadRight
Padding right value in the width dimension.
SubgraphView::InputSlots CreateInputsFrom(const std::vector< Layer *> &layers)
bool Contains(const CollectionType &collection, const typename CollectionType::value_type &item)
const Subgraphs & GetUntouchedSubgraphs() const
const Subgraphs & GetFailedSubgraphs() const
SubgraphView m_ReplacementSubgraph
A subgraph of new layers which will replace layers in m_SubstitutableSubgraph.
This layer represents a pooling 2d operation.
std::vector< InputSlot * > InputSlots
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
This layer represents an addition operation.
const InputSlots & GetInputSlots() const
const Substitutions & GetSubstitutions() const
std::unique_ptr< SubgraphView > SubgraphViewPtr
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).
const OutputSlots & GetOutputSlots() const
void SetWeightAndBias(ConvolutionLayer *layer, const armnn::TensorInfo &weightInfo, const armnn::TensorInfo &biasInfo)
void SetTensorInfo(const TensorInfo &tensorInfo) override
armnn::IBackendInternalUniquePtr CreateBackendObject(const armnn::BackendId &backendId)
const Layers & GetLayers() const
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.
std::list< Layer * > Layers
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.