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,
112 const std::string& layerName,
117 CHECK(constantLayer);
118 constantLayer->
m_LayerOutput = std::make_shared<ScopedTensorHandle>(constTensor);
120 layersInGraph.insert(std::make_pair(constantLayer->
GetName(), constantLayer));
121 return constantLayer;
126 LayerNameToLayerMap& layersInGraph,
128 const std::string& layerName,
134 layersInGraph.insert(std::make_pair(poolingLayer->
GetName(), poolingLayer));
140 LayerNameToLayerMap& layersInGraph,
141 const std::string& layerName,
145 CHECK(additionLayer);
147 layersInGraph.insert(std::make_pair(additionLayer->
GetName(), additionLayer));
148 return additionLayer;
153 const ExpectedSubgraphSize& expectedSubstitutableSubgraphSize,
154 const ExpectedSubgraphSize& expectedReplacementSubgraphSize,
170 CHECK(substitutableSubgraphInputSlots.size() == expectedSubstitutableSubgraphSize.m_NumInputSlots);
171 CHECK(substitutableSubgraphOutputSlots.size() == expectedSubstitutableSubgraphSize.m_NumOutputSlots);
172 CHECK(substitutableSubgraphLayers.size() == expectedSubstitutableSubgraphSize.m_NumLayers);
174 CHECK(
AreEqual(substitutableSubgraphInputSlots, expectedSubstitutableInputSlots));
175 CHECK(
AreEqual(substitutableSubgraphOutputSlots, expectedSubstitutableOutputSlots));
176 CHECK(
AreEqual(substitutableSubgraphLayers, expectedSubstitutableLayers));
178 CHECK(replacementSubgraphInputSlots.size() == expectedReplacementSubgraphSize.m_NumInputSlots);
179 CHECK(replacementSubgraphOutputSlots.size() == expectedReplacementSubgraphSize.m_NumOutputSlots);
180 CHECK(replacementSubgraphLayers.size() == expectedReplacementSubgraphSize.m_NumLayers);
182 CHECK(!
AreEqual(replacementSubgraphInputSlots, expectedSubstitutableInputSlots));
183 CHECK(!
AreEqual(replacementSubgraphOutputSlots, expectedSubstitutableOutputSlots));
184 CHECK(!
AreEqual(replacementSubgraphLayers, expectedSubstitutableLayers));
186 CHECK(std::all_of(replacementSubgraphLayers.begin(),
187 replacementSubgraphLayers.end(),
195 void CheckFailedSubgraph(
const SubgraphView& failedSubgraph,
196 const ExpectedSubgraphSize& expectedFailedSubgraphSize,
205 CHECK(failedSubgraphInputSlots.size() == expectedFailedSubgraphSize.m_NumInputSlots);
206 CHECK(failedSubgraphOutputSlots.size() == expectedFailedSubgraphSize.m_NumOutputSlots);
207 CHECK(failedSubgraphLayers.size() == expectedFailedSubgraphSize.m_NumLayers);
209 CHECK(
AreEqual(failedSubgraphInputSlots, expectedFailedInputSlots));
210 CHECK(
AreEqual(failedSubgraphOutputSlots, expectedFailedOutputSlots));
211 CHECK(
AreEqual(failedSubgraphLayers, expectedFailedLayers));
215 void CheckUntouchedSubgraph(
const SubgraphView& untouchedSubgraph,
216 const ExpectedSubgraphSize& expectedUntouchedSubgraphSize,
225 CHECK(untouchedSubgraphInputSlots.size() == expectedUntouchedSubgraphSize.m_NumInputSlots);
226 CHECK(untouchedSubgraphOutputSlots.size() == expectedUntouchedSubgraphSize.m_NumOutputSlots);
227 CHECK(untouchedSubgraphLayers.size() == expectedUntouchedSubgraphSize.m_NumLayers);
229 CHECK(
AreEqual(untouchedSubgraphInputSlots, expectedUntouchedInputSlots));
230 CHECK(
AreEqual(untouchedSubgraphOutputSlots, expectedUntouchedOutputSlots));
231 CHECK(
AreEqual(untouchedSubgraphLayers, expectedUntouchedLayers));
242 poolingDescriptor.m_PoolWidth = 2;
243 poolingDescriptor.m_PoolHeight = 2;
244 poolingDescriptor.m_StrideX = 2;
245 poolingDescriptor.m_StrideY = 2;
246 poolingDescriptor.m_PadLeft = 1;
247 poolingDescriptor.m_PadRight = 1;
248 poolingDescriptor.m_PadTop = 1;
249 poolingDescriptor.m_PadBottom = 1;
254 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
255 Pooling2dLayer*
const poolingLayer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
256 "pooling layer", outputInfo);
257 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
277 poolingDescriptor.m_PoolWidth = 2;
278 poolingDescriptor.m_PoolHeight = 2;
279 poolingDescriptor.m_StrideX = 2;
280 poolingDescriptor.m_StrideY = 2;
281 poolingDescriptor.m_PadLeft = 1;
282 poolingDescriptor.m_PadRight = 1;
283 poolingDescriptor.m_PadTop = 1;
284 poolingDescriptor.m_PadBottom = 1;
289 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
290 Pooling2dLayer*
const pooling1Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
291 "pooling1 layer", outputInfo);
292 Pooling2dLayer*
const pooling2Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
293 "pooling2 layer", outputInfo);
294 Pooling2dLayer*
const pooling3Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
295 "pooling3 layer", outputInfo);
296 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
329 std::vector<float> weightsVector(64);
330 ConstTensor constWeightsTensor(weightInfo, weightsVector);
332 std::vector<float> biasVector(16);
336 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
337 Convolution2dLayer*
const convLayer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
338 "conv layer", weightInfo, biasInfo, outputInfo);
341 AddConstantLayer(graph, layersInGraph,
"Weights Layer", constWeightsTensor, outputInfo);
342 ConstantLayer*
const biasLayer = AddConstantLayer(graph, layersInGraph,
"Bias Layer", constBiasTensor, outputInfo);
344 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
352 std::vector<unsigned int> ignoreSlots = {1, 2};
356 {convLayer, weightsLayer, biasLayer});
370 std::vector<float> weightsVector(64);
371 ConstTensor constWeightsTensor(weightInfo, weightsVector);
373 std::vector<float> biasVector(16);
384 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
385 Convolution2dLayer*
const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
386 "conv1 layer", weightInfo, biasInfo, outputInfo);
388 AddConstantLayer(graph, layersInGraph,
"Weights Layer 1", constWeightsTensor, outputInfo);
390 AddConstantLayer(graph, layersInGraph,
"Bias Layer 1", constBiasTensor, outputInfo);
392 Convolution2dLayer*
const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
393 "conv2 layer", weightInfo, biasInfo, outputInfo);
395 AddConstantLayer(graph, layersInGraph,
"Weights Layer 2", constWeightsTensor, outputInfo);
397 AddConstantLayer(graph, layersInGraph,
"Bias Layer 2", constBiasTensor, outputInfo);
400 Convolution2dLayer*
const conv3Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
401 "conv3 layer", weightInfo, biasInfo, outputInfo);
403 AddConstantLayer(graph, layersInGraph,
"Weights Layer 3", constWeightsTensor, outputInfo);
405 AddConstantLayer(graph, layersInGraph,
"Bias Layer 3", constBiasTensor, outputInfo);
407 Convolution2dLayer*
const conv4Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
408 "conv4 layer", weightInfo, biasInfo, outputInfo);
410 AddConstantLayer(graph, layersInGraph,
"Weights Layer 4", constWeightsTensor, outputInfo);
412 AddConstantLayer(graph, layersInGraph,
"Bias Layer 4", constBiasTensor, outputInfo);
414 Convolution2dLayer*
const conv5Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
415 "conv5 layer", weightInfo, biasInfo, outputInfo);
417 AddConstantLayer(graph, layersInGraph,
"Weights Layer 5", constWeightsTensor, outputInfo);
419 AddConstantLayer(graph, layersInGraph,
"Bias Layer 5", constBiasTensor, outputInfo);
422 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
446 std::vector<unsigned int> ignoreSlots = {1, 2};
479 std::vector<float> weightsVector(64);
480 ConstTensor constWeightsTensor(weightInfo, weightsVector);
482 std::vector<float> biasVector(16);
505 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
507 AddConstantLayer(graph, layersInGraph,
"Weights Layer 1", constWeightsTensor, outputInfo);
510 AddConstantLayer(graph, layersInGraph,
"Bias Layer 1", constBiasTensor, outputInfo);
512 Convolution2dLayer*
const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
513 "conv1 layer", weightInfo, biasInfo, outputInfo);
514 Pooling2dLayer*
const pooling1Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
515 "pooling1 layer", outputInfo);
516 Pooling2dLayer*
const pooling2Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
517 "pooling2 layer", outputInfo);
520 AddConstantLayer(graph, layersInGraph,
"Weights Layer 2", constWeightsTensor, outputInfo);
523 AddConstantLayer(graph, layersInGraph,
"Bias Layer 2", constBiasTensor, outputInfo);
525 Convolution2dLayer*
const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
526 "conv2 layer", weightInfo, biasInfo, outputInfo);
527 Pooling2dLayer*
const pooling3Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
528 "pooling3 layer", outputInfo);
529 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
543 std::vector<unsigned int> ignoreSlots = {1, 2};
569 std::vector<float> weightsVector(64);
570 ConstTensor constWeightsTensor(weightInfo, weightsVector);
572 std::vector<float> biasVector(16);
581 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
584 AddConstantLayer(graph, layersInGraph,
"Weights Layer unoptimizable", constWeightsTensor, outputInfo);
587 AddConstantLayer(graph, layersInGraph,
"Bias Layer unoptimizable", constBiasTensor, outputInfo);
589 Convolution2dLayer*
const convLayer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
590 "conv layer unoptimizable", weightInfo, biasInfo,
592 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
600 std::vector<unsigned int> ignoreSlots = {1, 2};
604 {convLayer, weightsLayer, biasLayer});
618 std::vector<float> weightsVector(64);
619 ConstTensor constWeightsTensor(weightInfo, weightsVector);
621 std::vector<float> biasVector(16);
631 Layer*
const inputLayer = AddInputLayer(graph,
"input layer", inputInfo);
634 AddConstantLayer(graph, layersInGraph,
"Weights Layer 1", constWeightsTensor, outputInfo);
636 AddConstantLayer(graph, layersInGraph,
"Bias Layer 1", constBiasTensor, outputInfo);
638 AddConstantLayer(graph, layersInGraph,
"Weights Layer 2 unoptimizable", constWeightsTensor, outputInfo);
640 AddConstantLayer(graph, layersInGraph,
"Bias Layer 2 unoptimizable", constBiasTensor, outputInfo);
642 AddConstantLayer(graph, layersInGraph,
"Weights Layer 3", constWeightsTensor, outputInfo);
644 AddConstantLayer(graph, layersInGraph,
"Bias Layer 3", constBiasTensor, outputInfo);
646 AddConstantLayer(graph, layersInGraph,
"Weights Layer 4 unoptimizable", constWeightsTensor, outputInfo);
648 AddConstantLayer(graph, layersInGraph,
"Bias Layer 4 unoptimizable", constBiasTensor, outputInfo);
650 AddConstantLayer(graph, layersInGraph,
"Weights Layer 5", constWeightsTensor, outputInfo);
652 AddConstantLayer(graph, layersInGraph,
"Bias Layer 5", constBiasTensor, outputInfo);
654 Convolution2dLayer*
const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
655 "conv1 layer", weightInfo, biasInfo, outputInfo);
658 convolutionDescriptor,
659 "conv2 layer unoptimizable",
663 Convolution2dLayer*
const conv3Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
664 "conv3 layer", weightInfo, biasInfo, outputInfo);
667 convolutionDescriptor,
668 "conv4 layer unoptimizable",
672 Convolution2dLayer*
const conv5Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
673 "conv5 layer", weightInfo, biasInfo, outputInfo);
675 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
700 std::vector<unsigned int> ignoreSlots = {1, 2};
733 std::vector<float> weightsVector(64);
734 ConstTensor constWeightsTensor(weightInfo, weightsVector);
736 std::vector<float> biasVector(16);
746 Layer*
const input1Layer = AddInputLayer(graph,
"input1 layer", inputInfo, 0);
747 Layer*
const input2Layer = AddInputLayer(graph,
"input2 layer", inputInfo, 1);
750 AddConstantLayer(graph, layersInGraph,
"Weights Layer 1", constWeightsTensor, outputInfo);
752 AddConstantLayer(graph, layersInGraph,
"Bias Layer 1", constBiasTensor, outputInfo);
754 AddConstantLayer(graph, layersInGraph,
"Weights Layer 2 unoptimizable", constWeightsTensor, outputInfo);
756 AddConstantLayer(graph, layersInGraph,
"Bias Layer 2 unoptimizable", constBiasTensor, outputInfo);
758 AddConstantLayer(graph, layersInGraph,
"Weights Layer 3", constWeightsTensor, outputInfo);
760 AddConstantLayer(graph, layersInGraph,
"Bias Layer 3", constBiasTensor, outputInfo);
762 Convolution2dLayer*
const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
763 "conv1 layer", weightInfo, biasInfo, outputInfo);
764 Convolution2dLayer*
const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
765 "conv2 layer unoptimizable", weightInfo, biasInfo,
767 Convolution2dLayer*
const conv3Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
768 "conv3 layer", weightInfo, biasInfo, outputInfo);
769 AdditionLayer*
const addLayer = AddAdditionaLayer(graph, layersInGraph,
"add layer", outputInfo);
770 Layer*
const outputLayer = AddOutputLayer(graph,
"output layer");
789 std::vector<unsigned int> ignoreSlots = {1, 2};
791 conv2Layer}, ignoreSlots),
806 void FullyUnsupporteSubgraphTestImpl1()
809 LayerNameToLayerMap layersInGraph;
813 CHECK((subgraphPtr !=
nullptr));
819 CHECK(subgraphInputSlots.size() == 1);
820 CHECK(subgraphOutputSlots.size() == 1);
821 CHECK(subgraphLayers.size() == 1);
823 CHECK(
Contains(layersInGraph,
"pooling layer"));
828 CHECK((backendObjPtr !=
nullptr));
834 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
854 CHECK(failedSubgraphs.size() == 1);
856 CheckFailedSubgraph(failedSubgraphs.at(0),
857 { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
870 void FullyUnsupporteSubgraphTestImpl2()
873 LayerNameToLayerMap layersInGraph;
877 CHECK((subgraphPtr !=
nullptr));
883 CHECK(subgraphInputSlots.size() == 1);
884 CHECK(subgraphOutputSlots.size() == 1);
885 CHECK(subgraphLayers.size() == 3);
887 CHECK(
Contains(layersInGraph,
"pooling1 layer"));
888 CHECK(
Contains(layersInGraph,
"pooling2 layer"));
889 CHECK(
Contains(layersInGraph,
"pooling3 layer"));
894 CHECK((backendObjPtr !=
nullptr));
900 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
920 CHECK(failedSubgraphs.size() == 1);
922 std::list<IConnectableLayer*> expectedFailedLayers{ layersInGraph.at(
"pooling1 layer"),
923 layersInGraph.at(
"pooling2 layer"),
924 layersInGraph.at(
"pooling3 layer") };
926 const SubgraphView& failedSubgraph = failedSubgraphs.at(0);
928 CheckFailedSubgraph(failedSubgraph,
929 { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
936 CHECK_EQ(failedSubgraphLayers.front() + 0, expectedFailedLayers.front() + 0);
937 CHECK_EQ(failedSubgraphLayers.front() + 1, expectedFailedLayers.front() + 1);
938 CHECK_EQ(failedSubgraphLayers.front() + 2, expectedFailedLayers.front() + 2);
948 void FullyOptimizableSubgraphTestImpl1()
951 LayerNameToLayerMap layersInGraph;
955 CHECK((subgraphPtr !=
nullptr));
961 CHECK(subgraphInputSlots.size() == 1);
962 CHECK(subgraphOutputSlots.size() == 1);
963 CHECK(subgraphLayers.size() == 3);
965 CHECK(
Contains(layersInGraph,
"conv layer"));
966 CHECK(
Contains(layersInGraph,
"Weights Layer"));
967 CHECK(
Contains(layersInGraph,
"Bias Layer"));
972 CHECK((backendObjPtr !=
nullptr));
978 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
992 CHECK(substitutions.size() == 1);
994 CheckSubstitution(substitutions.at(0),
995 { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
996 { subgraphInputSlots.size(), subgraphOutputSlots.size(), 1 },
1015 void FullyOptimizableSubgraphTestImpl2()
1018 LayerNameToLayerMap layersInGraph;
1022 CHECK((subgraphPtr !=
nullptr));
1028 CHECK(subgraphInputSlots.size() == 1);
1029 CHECK(subgraphOutputSlots.size() == 1);
1030 CHECK(subgraphPtr->GetIConnectableLayers().size() == 15);
1032 CHECK(
Contains(layersInGraph,
"conv1 layer"));
1033 CHECK(
Contains(layersInGraph,
"conv2 layer"));
1034 CHECK(
Contains(layersInGraph,
"conv3 layer"));
1035 CHECK(
Contains(layersInGraph,
"conv4 layer"));
1036 CHECK(
Contains(layersInGraph,
"conv5 layer"));
1037 CHECK(
Contains(layersInGraph,
"Weights Layer 1"));
1038 CHECK(
Contains(layersInGraph,
"Weights Layer 2"));
1039 CHECK(
Contains(layersInGraph,
"Weights Layer 3"));
1040 CHECK(
Contains(layersInGraph,
"Weights Layer 4"));
1041 CHECK(
Contains(layersInGraph,
"Weights Layer 5"));
1042 CHECK(
Contains(layersInGraph,
"Bias Layer 1"));
1043 CHECK(
Contains(layersInGraph,
"Bias Layer 2"));
1044 CHECK(
Contains(layersInGraph,
"Bias Layer 3"));
1045 CHECK(
Contains(layersInGraph,
"Bias Layer 4"));
1046 CHECK(
Contains(layersInGraph,
"Bias Layer 5"));
1051 CHECK((backendObjPtr !=
nullptr));
1057 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
1071 CHECK(substitutions.size() == 1);
1073 std::list<IConnectableLayer*> expectedSubstitutableLayers{
1074 layersInGraph.at(
"Weights Layer 1"),
1075 layersInGraph.at(
"Weights Layer 2"),
1076 layersInGraph.at(
"Weights Layer 3"),
1077 layersInGraph.at(
"Weights Layer 4"),
1078 layersInGraph.at(
"Weights Layer 5"),
1079 layersInGraph.at(
"Bias Layer 1"),
1080 layersInGraph.at(
"Bias Layer 2"),
1081 layersInGraph.at(
"Bias Layer 3"),
1082 layersInGraph.at(
"Bias Layer 4"),
1083 layersInGraph.at(
"Bias Layer 5"),
1084 layersInGraph.at(
"conv1 layer"),
1085 layersInGraph.at(
"conv2 layer"),
1086 layersInGraph.at(
"conv3 layer"),
1087 layersInGraph.at(
"conv4 layer"),
1088 layersInGraph.at(
"conv5 layer")};
1094 {subgraphInputSlots.size(), subgraphOutputSlots.size(),
1095 subgraphLayers.size()},
1096 {subgraphInputSlots.size(), subgraphOutputSlots.size(), 1},
1097 subgraphInputSlots, subgraphOutputSlots, expectedSubstitutableLayers);
1102 CHECK_EQ(substitutableSubgraphLayers.front() + 0, expectedSubstitutableLayers.front() + 0);
1103 CHECK_EQ(substitutableSubgraphLayers.front() + 1, expectedSubstitutableLayers.front() + 1);
1104 CHECK_EQ(substitutableSubgraphLayers.front() + 2, expectedSubstitutableLayers.front() + 2);
1105 CHECK_EQ(substitutableSubgraphLayers.front() + 3, expectedSubstitutableLayers.front() + 3);
1106 CHECK_EQ(substitutableSubgraphLayers.front() + 4, expectedSubstitutableLayers.front() + 4);
1123 void PartiallySupportedSubgraphTestImpl()
1126 LayerNameToLayerMap layersInGraph;
1130 CHECK((subgraphPtr !=
nullptr));
1136 CHECK(subgraphInputSlots.size() == 1);
1137 CHECK(subgraphOutputSlots.size() == 1);
1138 CHECK(subgraphLayers.size() == 9);
1140 CHECK(
Contains(layersInGraph,
"Weights Layer 1"));
1141 CHECK(
Contains(layersInGraph,
"Bias Layer 1"));
1142 CHECK(
Contains(layersInGraph,
"conv1 layer"));
1143 CHECK(
Contains(layersInGraph,
"pooling1 layer"));
1144 CHECK(
Contains(layersInGraph,
"pooling2 layer"));
1145 CHECK(
Contains(layersInGraph,
"Weights Layer 2"));
1146 CHECK(
Contains(layersInGraph,
"Bias Layer 2"));
1147 CHECK(
Contains(layersInGraph,
"conv2 layer"));
1148 CHECK(
Contains(layersInGraph,
"pooling3 layer"));
1153 CHECK((backendObjPtr !=
nullptr));
1159 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
1173 CHECK(substitutions.size() == 2);
1175 std::sort(substitutions.begin(), substitutions.end(), [](
auto s1,
auto s2) {
1176 return strcmp(s1.m_SubstitutableSubgraph.GetIConnectableLayers().front()->GetName(),
1177 s2.m_SubstitutableSubgraph.GetIConnectableLayers().front()->GetName()) < 0;
1180 std::vector<ExpectedSubgraphSize> expectedSubstitutableSubgraphSizes{ { 1, 1, 3 },
1182 std::vector<ExpectedSubgraphSize> expectedReplacementSubgraphSizes{ { 1, 1, 1 },
1184 std::vector<SubgraphView::IInputSlots> expectedSubstitutableInputSlots
1186 ConvertSlotsToISlots<InputSlot, IInputSlot>(
1187 {ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetInputSlot(0))}),
1188 ConvertSlotsToISlots<InputSlot, IInputSlot>(
1189 {ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer")->GetInputSlot(0))})
1192 std::vector<SubgraphView::IOutputSlots> expectedSubstitutableOutputSlots
1194 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1195 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetOutputSlots())),
1196 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1197 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer")->GetOutputSlots()))
1199 std::vector<SubgraphView::IConnectableLayers> expectedSubstitutableLayers
1201 { layersInGraph.at(
"Weights Layer 1"), layersInGraph.at(
"Bias Layer 1"), layersInGraph.at(
"conv1 layer") },
1202 { layersInGraph.at(
"Weights Layer 2"), layersInGraph.at(
"Bias Layer 2"), layersInGraph.at(
"conv2 layer") }
1205 for (
size_t substitutionIndex = 0; substitutionIndex < substitutions.size(); substitutionIndex++)
1207 CheckSubstitution(substitutions.at(substitutionIndex),
1208 expectedSubstitutableSubgraphSizes.at(substitutionIndex),
1209 expectedReplacementSubgraphSizes.at(substitutionIndex),
1210 expectedSubstitutableInputSlots.at(substitutionIndex),
1211 expectedSubstitutableOutputSlots.at(substitutionIndex),
1212 expectedSubstitutableLayers.at(substitutionIndex));
1220 CHECK(failedSubgraphs.size() == 2);
1222 std::sort(failedSubgraphs.begin(), failedSubgraphs.end(), [](
auto s1,
auto s2) {
1223 return strcmp(s1.GetIConnectableLayers().front()->GetName(),
1224 s2.GetIConnectableLayers().front()->GetName()) < 0;
1227 std::vector<ExpectedSubgraphSize> expectedFailedSubgraphSizes{ { 1, 1, 2 },
1229 std::vector<SubgraphView::IInputSlots> expectedFailedInputSlots
1231 ConvertSlotsToISlots<InputSlot, IInputSlot>(
1232 ConvertReferenceTypeToPointerType(layersInGraph.at(
"pooling1 layer")->GetInputSlots())),
1233 ConvertSlotsToISlots<InputSlot, IInputSlot>(
1234 ConvertReferenceTypeToPointerType(layersInGraph.at(
"pooling3 layer")->GetInputSlots()))
1236 std::vector<SubgraphView::IOutputSlots> expectedFailedOutputSlots
1238 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1239 ConvertReferenceTypeToPointerType(layersInGraph.at(
"pooling2 layer")->GetOutputSlots())),
1240 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1241 ConvertReferenceTypeToPointerType(layersInGraph.at(
"pooling3 layer")->GetOutputSlots()))
1243 std::vector<SubgraphView::IConnectableLayers> expectedFailedLayers
1245 { layersInGraph.at(
"pooling1 layer"),
1246 layersInGraph.at(
"pooling2 layer") },
1247 { layersInGraph.at(
"pooling3 layer") }
1250 for (
size_t failedIndex = 0; failedIndex < failedSubgraphs.size(); failedIndex++)
1252 CheckFailedSubgraph(failedSubgraphs.at(failedIndex),
1253 expectedFailedSubgraphSizes.at(failedIndex),
1254 expectedFailedInputSlots.at(failedIndex),
1255 expectedFailedOutputSlots.at(failedIndex),
1256 expectedFailedLayers.at(failedIndex));
1267 void FullyUnoptimizableSubgraphTestImpl1()
1270 LayerNameToLayerMap layersInGraph;
1274 CHECK((subgraphPtr !=
nullptr));
1280 CHECK(subgraphInputSlots.size() == 1);
1281 CHECK(subgraphOutputSlots.size() == 1);
1282 CHECK(subgraphLayers.size() == 3);
1284 CHECK(
Contains(layersInGraph,
"conv layer unoptimizable"));
1289 CHECK((backendObjPtr !=
nullptr));
1295 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
1321 CHECK(untouchedSubgraphs.size() == 1);
1323 CheckUntouchedSubgraph(untouchedSubgraphs.at(0),
1324 {subgraphInputSlots.size(),
1325 subgraphOutputSlots.size(), subgraphLayers.size()},
1326 subgraphInputSlots, subgraphOutputSlots,
1331 void PartiallyOptimizableSubgraphTestImpl1()
1334 LayerNameToLayerMap layersInGraph;
1338 CHECK((subgraphPtr !=
nullptr));
1344 CHECK(subgraphInputSlots.size() == 1);
1345 CHECK(subgraphOutputSlots.size() == 1);
1346 CHECK(subgraphLayers.size() == 15);
1348 CHECK(
Contains(layersInGraph,
"conv1 layer"));
1349 CHECK(
Contains(layersInGraph,
"conv2 layer unoptimizable"));
1350 CHECK(
Contains(layersInGraph,
"conv3 layer"));
1351 CHECK(
Contains(layersInGraph,
"conv4 layer unoptimizable"));
1352 CHECK(
Contains(layersInGraph,
"conv5 layer"));
1357 CHECK((backendObjPtr !=
nullptr));
1363 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
1377 CHECK(substitutions.size() == 3);
1379 std::sort(substitutions.begin(), substitutions.end(),
1380 [](
auto s1,
auto s2)
1381 {
return strcmp(s1.m_SubstitutableSubgraph.GetIConnectableLayers().front()->GetName(),
1382 s2.m_SubstitutableSubgraph.GetIConnectableLayers().front()->GetName()) < 0; });
1384 std::vector<ExpectedSubgraphSize> expectedSubstitutableSubgraphSizes{ { 1, 1, 3 },
1387 std::vector<ExpectedSubgraphSize> expectedReplacementSubgraphSizes{ { 1, 1, 1 },
1390 std::vector<SubgraphView::IInputSlots> expectedSubstitutableInputSlots
1392 ConvertSlotsToISlots<InputSlot, IInputSlot>(
1393 {ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetInputSlot(0))}),
1394 ConvertSlotsToISlots<InputSlot, IInputSlot>(
1395 {ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv3 layer")->GetInputSlot(0))}),
1396 ConvertSlotsToISlots<InputSlot, IInputSlot>(
1397 {ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv5 layer")->GetInputSlot(0))})
1399 std::vector<SubgraphView::IOutputSlots> expectedSubstitutableOutputSlots
1401 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1402 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetOutputSlots())),
1403 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1404 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv3 layer")->GetOutputSlots())),
1405 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1406 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv5 layer")->GetOutputSlots()))
1408 std::vector<SubgraphView::IConnectableLayers> expectedSubstitutableLayers
1410 { layersInGraph.at(
"Weights Layer 1"), layersInGraph.at(
"Bias Layer 1"), layersInGraph.at(
"conv1 layer") },
1411 { layersInGraph.at(
"Weights Layer 3"), layersInGraph.at(
"Bias Layer 3"), layersInGraph.at(
"conv3 layer") },
1412 { layersInGraph.at(
"Weights Layer 5"), layersInGraph.at(
"Bias Layer 5"), layersInGraph.at(
"conv5 layer") }
1415 for (
size_t substitutionIndex = 0; substitutionIndex < substitutions.size(); substitutionIndex++)
1417 CheckSubstitution(substitutions.at(substitutionIndex),
1418 expectedSubstitutableSubgraphSizes.at(substitutionIndex),
1419 expectedReplacementSubgraphSizes.at(substitutionIndex),
1420 expectedSubstitutableInputSlots.at(substitutionIndex),
1421 expectedSubstitutableOutputSlots.at(substitutionIndex),
1422 expectedSubstitutableLayers.at(substitutionIndex));
1436 CHECK(untouchedSubgraphs.size() == 2);
1438 std::sort(untouchedSubgraphs.begin(), untouchedSubgraphs.end(), [](
auto s1,
auto s2) {
1439 return strcmp(s1.GetIConnectableLayers().front()->GetName(),
1440 s2.GetIConnectableLayers().front()->GetName()) < 0;
1443 std::vector<ExpectedSubgraphSize> expectedUntouchedSubgraphSizes{ { 1, 1, 3 },
1445 std::vector<SubgraphView::IInputSlots> expectedUntouchedInputSlots{
1447 IInputSlot>({ConvertReferenceTypeToPointerType(
1448 layersInGraph.at(
"conv2 layer unoptimizable")->GetInputSlot(0))}),
1449 ConvertSlotsToISlots<InputSlot,
1450 IInputSlot>({ConvertReferenceTypeToPointerType(
1451 layersInGraph.at(
"conv4 layer unoptimizable")->GetInputSlot(0))})};
1453 std::vector<SubgraphView::IOutputSlots> expectedUntouchedOutputSlots
1455 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1456 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer unoptimizable")->GetOutputSlots())),
1457 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1458 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv4 layer unoptimizable")->GetOutputSlots()))
1461 std::vector<SubgraphView::IConnectableLayers> expectedUntouchedLayers
1463 { layersInGraph.at(
"Weights Layer 2 unoptimizable"),
1464 layersInGraph.at(
"Bias Layer 2 unoptimizable"),
1465 layersInGraph.at(
"conv2 layer unoptimizable") },
1466 { layersInGraph.at(
"Weights Layer 4 unoptimizable"),
1467 layersInGraph.at(
"Bias Layer 4 unoptimizable"),
1468 layersInGraph.at(
"conv4 layer unoptimizable") }
1471 for (
size_t untouchedIndex = 0; untouchedIndex < untouchedSubgraphs.size(); untouchedIndex++)
1473 CheckUntouchedSubgraph(untouchedSubgraphs.at(untouchedIndex),
1474 expectedUntouchedSubgraphSizes.at(untouchedIndex),
1475 expectedUntouchedInputSlots.at(untouchedIndex),
1476 expectedUntouchedOutputSlots.at(untouchedIndex),
1477 expectedUntouchedLayers.at(untouchedIndex));
1483 void PartiallyOptimizableSubgraphTestImpl2()
1486 LayerNameToLayerMap layersInGraph;
1490 CHECK((subgraphPtr !=
nullptr));
1496 CHECK(subgraphInputSlots.size() == 2);
1497 CHECK(subgraphOutputSlots.size() == 1);
1498 CHECK(subgraphLayers.size() == 10);
1500 CHECK(
Contains(layersInGraph,
"conv1 layer"));
1501 CHECK(
Contains(layersInGraph,
"conv2 layer unoptimizable"));
1502 CHECK(
Contains(layersInGraph,
"conv3 layer"));
1503 CHECK(
Contains(layersInGraph,
"add layer"));
1508 CHECK((backendObjPtr !=
nullptr));
1514 CHECK_NOTHROW(optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraphPtr));
1528 CHECK(substitutions.size() == 1);
1530 ExpectedSubgraphSize expectedSubstitutableSubgraphSizes{ 2, 1, 7 };
1531 ExpectedSubgraphSize expectedReplacementSubgraphSizes{ 2, 1, 1 };
1535 ConvertSlotsToISlots<InputSlot, IInputSlot>({
1536 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv1 layer")->GetInputSlots()[0])})[0],
1537 ConvertSlotsToISlots<InputSlot, IInputSlot>({
1538 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv3 layer")->GetInputSlots()[0])})[0]
1543 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1544 ConvertReferenceTypeToPointerType(layersInGraph.at(
"add layer")->GetOutputSlots()))
1549 layersInGraph.at(
"Weights Layer 1"),
1550 layersInGraph.at(
"Weights Layer 3"),
1551 layersInGraph.at(
"Bias Layer 1"),
1552 layersInGraph.at(
"Bias Layer 3"),
1553 layersInGraph.at(
"conv1 layer"),
1554 layersInGraph.at(
"conv3 layer"),
1555 layersInGraph.at(
"add layer")
1558 CheckSubstitution(substitutions[0],
1559 expectedSubstitutableSubgraphSizes,
1560 expectedReplacementSubgraphSizes,
1561 expectedSubstitutableInputSlots,
1562 expectedSubstitutableOutputSlots,
1563 expectedSubstitutableLayers);
1576 CHECK(untouchedSubgraphs.size() == 1);
1578 std::vector<ExpectedSubgraphSize> expectedUntouchedSubgraphSizes{ { 1, 1, 3 } };
1579 std::vector<SubgraphView::IInputSlots> expectedUntouchedInputSlots
1581 ConvertSlotsToISlots<InputSlot,
1582 IInputSlot>({ConvertReferenceTypeToPointerType(
1583 layersInGraph.at(
"conv2 layer unoptimizable")->GetInputSlot(0))})};
1584 std::vector<SubgraphView::IOutputSlots> expectedUntouchedOutputSlots
1586 ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
1587 ConvertReferenceTypeToPointerType(layersInGraph.at(
"conv2 layer unoptimizable")->GetOutputSlots()))
1589 std::vector<SubgraphView::IConnectableLayers> expectedUntouchedLayers
1591 { layersInGraph.at(
"conv2 layer unoptimizable"), layersInGraph.at(
"Weights Layer 2 unoptimizable"),
1592 layersInGraph.at(
"Bias Layer 2 unoptimizable") }
1595 for (
size_t untouchedIndex = 0; untouchedIndex < untouchedSubgraphs.size(); untouchedIndex++)
1597 CheckUntouchedSubgraph(untouchedSubgraphs.at(untouchedIndex),
1598 expectedUntouchedSubgraphSizes.at(untouchedIndex),
1599 expectedUntouchedInputSlots.at(untouchedIndex),
1600 expectedUntouchedOutputSlots.at(untouchedIndex),
1601 expectedUntouchedLayers.at(untouchedIndex));
1609 TEST_CASE(
"FullyUnsupportedSubgraph1") { FullyUnsupporteSubgraphTestImpl1(); }
1610 TEST_CASE(
"FullyUnsupportedSubgraph2") { FullyUnsupporteSubgraphTestImpl2(); }
1611 TEST_CASE(
"FullyOptimizableSubgraph1") { FullyOptimizableSubgraphTestImpl1(); }
1612 TEST_CASE(
"FullyOptimizableSubgraph2") { FullyOptimizableSubgraphTestImpl2(); }
1613 TEST_CASE(
"PartiallySupportedSubgraph") { PartiallySupportedSubgraphTestImpl(); }
1614 TEST_CASE(
"FullyUnoptimizableSubgraph") { FullyUnoptimizableSubgraphTestImpl1(); }
1615 TEST_CASE(
"PartiallyOptimizableSubgraph1") { PartiallyOptimizableSubgraphTestImpl1(); }
1616 TEST_CASE(
"PartiallyOptimizableSubgraph2") { PartiallyOptimizableSubgraphTestImpl2(); }
TEST_SUITE("TestConstTensorLayerVisitor")
A layer that the constant data can be bound to.
bool m_BiasEnabled
Enable/disable bias.
bool Contains(const CollectionType &collection, const typename CollectionType::value_type &item)
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
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
uint32_t m_PadLeft
Padding left value in the width dimension.
const IConnectableLayers & GetIConnectableLayers() const
const IInputSlots & GetIInputSlots() const
std::shared_ptr< ConstTensorHandle > m_LayerOutput
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).
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
std::list< IConnectableLayer * > IConnectableLayers
uint32_t m_PadRight
Padding right value in the width dimension.
std::vector< IOutputSlot * > IOutputSlots
const Subgraphs & GetUntouchedSubgraphs() const
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
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)
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
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)
void SetConstant(const bool IsConstant=true)
Marks the data corresponding to this tensor info as constant.
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.
SubgraphView::InputSlots CreateInputsFrom(Layer *layer, std::vector< unsigned int > ignoreSlots)
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.