5 #include <boost/test/unit_test.hpp> 18 using namespace armnn;
25 for(
auto&& layer : subgraphLayers)
27 auto posInGraph = std::find(graph.
begin(), graph.
end(), layer);
28 if(posInGraph != graph.
end())
43 for (
auto&& layer : layers)
45 for (
auto&& it = layer->BeginInputSlots(); it != layer->EndInputSlots(); ++it)
47 result.push_back(&(*it));
59 for (
auto && layer : layers)
61 for (
auto&& it = layer->BeginOutputSlots(); it != layer->EndOutputSlots(); ++it)
63 result.push_back(&(*it));
77 return std::make_unique<SubgraphView>(std::move(inputs), std::move(outputs), std::move(layers));
80 template <
typename T,
typename Iterator>
81 std::vector<T> ToSortedArray(Iterator begin, Iterator end)
83 std::vector<T> result(begin, end);
84 std::sort(result.begin(), result.end());
89 void CompareVectors(
const std::vector<T>& result,
const std::vector<T>& expected)
91 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
98 BOOST_TEST((result.get() !=
nullptr));
99 BOOST_TEST((expected.get() !=
nullptr));
101 if (result.get() !=
nullptr && expected.get() !=
nullptr)
106 BOOST_TEST(result->GetInputSlots().size() == expected->GetInputSlots().size());
107 BOOST_TEST(result->GetOutputSlots().size() == expected->GetOutputSlots().size());
108 BOOST_TEST(result->GetLayers().size() == expected->GetLayers().size());
110 auto resultLayers = ToSortedArray<Layer *>(result->GetLayers().begin(),
111 result->GetLayers().end());
112 auto expectedLayers = ToSortedArray<Layer *>(expected->GetLayers().begin(),
113 expected->GetLayers().end());
114 CompareVectors(resultLayers, expectedLayers);
116 auto resultInputs = ToSortedArray<InputSlot *>(result->GetInputSlots().begin(),
117 result->GetInputSlots().end());
118 auto expectedInputs = ToSortedArray<InputSlot *>(expected->GetInputSlots().begin(),
119 expected->GetInputSlots().end());
120 CompareVectors(resultInputs, expectedInputs);
122 auto resultOutputs = ToSortedArray<OutputSlot *>(result->GetOutputSlots().begin(),
123 result->GetOutputSlots().end());
124 auto expectedOutputs = ToSortedArray<OutputSlot *>(expected->GetOutputSlots().begin(),
125 expected->GetOutputSlots().end());
126 CompareVectors(resultOutputs, expectedOutputs);
149 convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
187 convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
199 Graph substituteGraph;
238 convLayer2->GetOutputSlot(0).Connect(concatLayer->
GetInputSlot(1));
287 convLayer2->GetOutputSlot(0).Connect(concatLayer->
GetInputSlot(1));
338 convLayer2->GetOutputSlot(0).Connect(concatLayer->
GetInputSlot(1));
406 BOOST_CHECK(!AreAnySubgraphLayersPresentInGraph(subgraphLayers, graph));
420 BOOST_TEST(subgraph.
GetLayers().empty());
438 BOOST_TEST(subgraph.GetInputSlots().empty());
439 BOOST_TEST(subgraph.GetOutputSlots().empty());
440 BOOST_TEST(subgraph.GetLayers().size() == graph.
GetNumLayers());
453 BOOST_TEST(subgraphs.empty());
469 bool isOutput = l.
GetNameStr().compare(
"output") == 0;
473 BOOST_TEST(subgraphs.size() == 1);
474 if (subgraphs.size() == 1)
481 CompareSubgraphViews(subgraphs[0], expected);
508 BOOST_TEST(subgraphs.size() == 1);
509 if (subgraphs.size() == 1)
515 CompareSubgraphViews(subgraphs[0], expected);
544 BOOST_TEST(subgraphs.size() == 2);
545 if (subgraphs.size() == 2)
547 BOOST_TEST((subgraphs[0] !=
nullptr));
548 BOOST_TEST((subgraphs[1] !=
nullptr));
549 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr)
551 if (std::find(subgraphs[0]->GetLayers().begin(), subgraphs[0]->GetLayers().end(), i0) !=
552 subgraphs[0]->GetLayers().end())
554 CompareSubgraphViews(subgraphs[0], expected1);
555 CompareSubgraphViews(subgraphs[1], expected2);
559 CompareSubgraphViews(subgraphs[0], expected2);
560 CompareSubgraphViews(subgraphs[1], expected1);
617 bool toSelect = std::string(l.
GetName())[0] ==
'm';
624 { m0, m1, m2, m3, m4 });
626 auto smallerSubgraph =
628 std::vector<OutputSlot*>{},
631 BOOST_TEST(subgraphs.size() == 2);
632 if (subgraphs.size() == 2)
635 BOOST_TEST((subgraphs[0] !=
nullptr));
636 BOOST_TEST((subgraphs[1] !=
nullptr));
638 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr)
641 std::sort(subgraphs.begin(), subgraphs.end(),
644 return (lhs->GetLayers().size() < rhs->GetLayers().size());
648 BOOST_TEST(subgraphs[0]->GetLayers().size() == 2);
649 BOOST_TEST(subgraphs[1]->GetLayers().size() == 5);
651 CompareSubgraphViews(subgraphs[0], smallerSubgraph);
652 CompareSubgraphViews(subgraphs[1], largerSubgraph);
706 BOOST_TEST(subgraphs.size() == 2);
707 if (subgraphs.size() == 2)
710 BOOST_TEST((subgraphs[0] !=
nullptr));
711 BOOST_TEST((subgraphs[1] !=
nullptr));
713 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr)
716 std::sort(subgraphs.begin(), subgraphs.end(),
719 return (lhs->GetLayers().size() < rhs->GetLayers().size());
723 BOOST_TEST(subgraphs[0]->GetLayers().size() == 1);
724 BOOST_TEST(subgraphs[1]->GetLayers().size() == 2);
726 CompareSubgraphViews(subgraphs[0], smallerSubgraph);
727 CompareSubgraphViews(subgraphs[1], largerSubgraph);
768 if(subgraphs.size() == 1)
774 CompareSubgraphViews(subgraphs[0], expected);
823 if (subgraphs.size() == 1)
827 {layerM1, layerM2, layerM3});
829 CompareSubgraphViews(subgraphs[0], expected);
862 layerM1->GetOutputSlot(0).Connect(layerM2->GetInputSlot(0));
863 layerM1->GetOutputSlot(1).Connect(layerM3->GetInputSlot(0));
864 layerM2->GetOutputSlot(0).Connect(layerX2->GetInputSlot(0));
865 layerM3->GetOutputSlot(0).Connect(layerX3->GetInputSlot(0));
879 if(subgraphs.size() == 1)
883 {layerM1, layerM2, layerM3});
885 CompareSubgraphViews(subgraphs[0], expected);
943 if (subgraphs.size() == 1)
947 {m1, m2, m3, m4, m5});
949 CompareSubgraphViews(subgraphs[0], expected);
988 return std::string(l.
GetName())[0] ==
'm';
992 auto expectedSubgraph0 =
1003 BOOST_TEST(subgraphs.size() == 2);
1004 if (subgraphs.size() == 2)
1007 BOOST_TEST((subgraphs[0] !=
nullptr));
1008 BOOST_TEST((subgraphs[1] !=
nullptr));
1010 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr)
1012 if (subgraphs[0]->GetInputSlots().size() == 1)
1014 CompareSubgraphViews(subgraphs[0], expectedSubgraph0);
1015 CompareSubgraphViews(subgraphs[1], expectedSubgraph1);
1019 CompareSubgraphViews(subgraphs[0], expectedSubgraph1);
1020 CompareSubgraphViews(subgraphs[1], expectedSubgraph0);
1082 bool toSelect = std::string(l.
GetName())[0] ==
'm';
1089 { m0, m1, m2, m3, m4 });
1092 std::vector<OutputSlot*>{}, { m5, m6 });
1094 auto smallerSubgraph =
1097 BOOST_TEST(subgraphs.size() == 3);
1098 if (subgraphs.size() == 3)
1101 BOOST_TEST((subgraphs[0] !=
nullptr));
1102 BOOST_TEST((subgraphs[1] !=
nullptr));
1103 BOOST_TEST((subgraphs[2] !=
nullptr));
1105 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr && subgraphs[2].
get() !=
nullptr)
1108 std::sort(subgraphs.begin(), subgraphs.end(),
1111 return (lhs->GetLayers().size() < rhs->GetLayers().size());
1115 CompareSubgraphViews(subgraphs[0], smallerSubgraph);
1116 CompareSubgraphViews(subgraphs[1], mediumSubgraph);
1117 CompareSubgraphViews(subgraphs[2], largerSubgraph);
1127 constexpr
bool debug =
false;
1129 std::mt19937 randomGenerator;
1132 auto GetRandom = [&randomGenerator](
auto maxExclusive) {
1136 std::uniform_real_distribution<float> uniform(0.0f, 1.0f);
1137 return static_cast<decltype(maxExclusive)
>(uniform(randomGenerator) *
static_cast<float>(maxExclusive));
1140 auto GetRandomFlag = [&randomGenerator](
float trueProb) {
1141 std::uniform_real_distribution<float> uniform(0.0f, 1.0f);
1142 return uniform(randomGenerator) < trueProb;
1145 constexpr uint32_t numTests = 100;
1146 for (uint32_t testIdx = 0; testIdx < numTests; ++testIdx)
1148 randomGenerator.seed(testIdx);
1156 uint32_t numInputs = 1 + GetRandom(4u);
1157 uint32_t numConstants = 1 + GetRandom(4u);
1158 uint32_t numOutputs = 1 + GetRandom(4u);
1159 uint32_t numConcats = 0 + GetRandom(500u);
1160 uint32_t numSplits = 0 + GetRandom(500u);
1161 float supportedProb = 0.7f;
1163 for (uint32_t i = 0; i < numInputs; ++i)
1165 std::string name =
"input" + std::to_string(i) + (GetRandomFlag(supportedProb) ?
"S" :
"N");
1168 for (uint32_t i = 0; i < numConstants; ++i)
1170 std::string name =
"constant" + std::to_string(i) + (GetRandomFlag(supportedProb) ?
"S" :
"N");
1173 for (uint32_t i = 0; i < numOutputs; ++i)
1175 std::string name =
"output" + std::to_string(i) + (GetRandomFlag(supportedProb) ?
"S" :
"N");
1178 for (uint32_t i = 0; i < numConcats; ++i)
1180 std::string name =
"concat" + std::to_string(i) + (GetRandomFlag(supportedProb) ?
"S" :
"N");
1181 uint32_t numInputs = 1 + GetRandom(3u);
1185 for (uint32_t i = 0; i < numSplits; ++i)
1187 std::string name =
"split" + std::to_string(i) + (GetRandomFlag(supportedProb) ?
"S" :
"N");
1188 uint32_t numOutputs = 1 + GetRandom(3u);
1198 uint32_t maxLayerDepth = 5 + GetRandom(2000u);
1199 std::map<Layer*, uint32_t> layerDepths;
1200 std::map<uint32_t, std::vector<Layer*>> layersAtDepth;
1201 for (
Layer* layer : graph)
1213 depth = 1 + GetRandom(maxLayerDepth);
1215 layerDepths[layer] = depth;
1216 layersAtDepth[depth].push_back(layer);
1221 for (
Layer* layer : graph)
1223 for (uint32_t inputSlotIdx = 0; inputSlotIdx < layer->GetNumInputSlots(); ++inputSlotIdx)
1225 InputSlot& inputSlot = layer->GetInputSlot(inputSlotIdx);
1226 uint32_t maxLayerDepthToConnectTo = layerDepths[layer];
1230 uint32_t layerDepth = GetRandom(maxLayerDepthToConnectTo);
1231 const std::vector<Layer*>& layersToChooseFrom = layersAtDepth[layerDepth];
1232 if (layersToChooseFrom.size() == 0)
1236 Layer* layerToConnectWith = layersToChooseFrom[GetRandom(layersToChooseFrom.size())];
1250 std::ofstream f(
"INPUT_" + std::to_string(testIdx) +
".dot");
1255 auto startTime = std::chrono::high_resolution_clock::now();
1259 [](
const Layer& l) {
return std::string(l.
GetName()).back() ==
'S'; });
1261 auto endTime = std::chrono::high_resolution_clock::now();
1262 auto duration = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime);
1265 std::cout <<
"Test " << testIdx <<
": " << duration.count() <<
" microseconds" << std::endl;
1270 std::map<Layer*, SubgraphView*> layerToSubgraph;
1271 for (
Layer* layer : graph)
1274 for (std::unique_ptr<SubgraphView>& subgraph : subgraphs)
1276 std::string name = std::to_string(i++);
1277 if (std::find(subgraph->begin(), subgraph->end(), layer) != subgraph->end())
1279 layerToSubgraph[layer] = subgraph.get();
1289 for (
Layer* layer : graph)
1291 std::string name =
"NotAssigned";
1292 auto subgraphIt = layerToSubgraph.find(layer);
1293 if (subgraphIt != layerToSubgraph.end())
1295 auto subgraphIdx = std::distance(subgraphs.begin(),
1296 std::find_if(subgraphs.begin(), subgraphs.end(),
1297 [&](
auto& s) {
return s.get() == subgraphIt->second; }));
1298 name = std::to_string(subgraphIdx);
1303 std::ofstream f(
"GRAPH_" + std::to_string(testIdx) +
".dot");
1304 graph.SerializeToDot(f);
1310 for (std::unique_ptr<SubgraphView>& subgraph : subgraphs)
1312 for (
InputSlot* inputSlot : subgraph->GetInputSlots())
1314 std::queue<Layer*> toProcess;
1315 toProcess.push(&inputSlot->GetConnectedOutputSlot()->GetOwningLayer());
1316 while (toProcess.size() > 0)
1318 Layer* l = toProcess.front();
1321 BOOST_CHECK(layerToSubgraph[l] != subgraph.get());
1325 toProcess.push(&is.GetConnectedOutputSlot()->GetOwningLayer());
1365 [](
const Layer & l){
1370 BOOST_TEST(subgraphs.size() == 1);
1371 if(subgraphs.size() == 1)
1373 BOOST_TEST((subgraphs[0] !=
nullptr));
1375 if (subgraphs[0].
get() !=
nullptr)
1377 unsigned int numInputSlots =
boost::numeric_cast<
unsigned int>(subgraphs[0]->GetInputSlots().size());
1378 unsigned int numOutputSlots =
boost::numeric_cast<
unsigned int>(subgraphs[0]->GetOutputSlots().size());
1380 BOOST_TEST((numInputSlots == 1));
1381 BOOST_TEST((numOutputSlots == 1));
1430 convLayer2->GetOutputSlot(0).Connect(pConcatLayer->
GetInputSlot(1));
1438 [](
const Layer & l){
1443 BOOST_TEST(subgraphs.size() == 2);
1444 if(subgraphs.size() == 2)
1446 BOOST_TEST((subgraphs[0] !=
nullptr));
1447 BOOST_TEST((subgraphs[1] !=
nullptr));
1449 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr)
1452 std::sort(subgraphs.begin(), subgraphs.end(),
1455 return (lhs->GetInputSlots().size() < rhs->GetInputSlots().size());
1459 unsigned int numInputSlots1 =
boost::numeric_cast<
unsigned int>(subgraphs[0]->GetInputSlots().size());
1460 unsigned int numOutputSlots1 =
boost::numeric_cast<
unsigned int>(subgraphs[0]->GetOutputSlots().size());
1462 unsigned int numInputSlots2 =
boost::numeric_cast<
unsigned int>(subgraphs[1]->GetInputSlots().size());
1463 unsigned int numOutputSlots2 =
boost::numeric_cast<
unsigned int>(subgraphs[1]->GetOutputSlots().size());
1544 bool toSelect = (l.
GetNameStr().find(
'm') != std::string::npos);
1557 BOOST_TEST(subgraphs.size() == 2);
1558 if (subgraphs.size() == 2)
1561 BOOST_TEST((subgraphs[0] !=
nullptr));
1562 BOOST_TEST((subgraphs[1] !=
nullptr));
1564 if (subgraphs[0].
get() !=
nullptr && subgraphs[1].
get() !=
nullptr)
1567 std::sort(subgraphs.begin(), subgraphs.end(),
1570 return (lhs->GetLayers().size() < rhs->GetLayers().size());
1575 BOOST_TEST(subgraphs[0]->GetLayers().size() == 1);
1576 BOOST_TEST(subgraphs[1]->GetLayers().size() == 2);
1578 CompareSubgraphViews(subgraphs[0], outputSubgraph);
1579 CompareSubgraphViews(subgraphs[1], inputSubgraph);
A layer that the constant data can be bound to.
BOOST_AUTO_TEST_SUITE(TensorflowLiteParser)
Iterator begin()
Returns iterator pointing to the beginning of the list. Lowercase for range-based for loops...
This layer represents a split operation.
A ViewsDescriptor for the SplitterLayer.
Status SerializeToDot(std::ostream &stream)
LayerT * AddLayer(Args &&... args)
Adds a new layer, of type LayerType, to the graph constructed with the arguments passed.
A Convolution2dDescriptor for the Convolution2dLayer.
int Connect(InputSlot &destination)
std::vector< OutputSlot * > OutputSlots
This layer represents an activation operation with the specified activation function.
Copyright (c) 2020 ARM Limited.
void SetBackendId(const BackendId &id)
const std::vector< InputSlot > & GetInputSlots() const
virtual const IInputSlot * GetConnection(unsigned int index) const =0
unsigned int GetNumOutputSlots() const override
Returns the number of connectable output slots.
BOOST_CHECK(profilingService.GetCurrentState()==ProfilingState::WaitingForAck)
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
The SubgraphView class represents a subgraph of a Graph.
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
A layer user-provided data can be bound to (e.g. inputs, outputs).
An output connection slot for a layer.
SubgraphView::InputSlots CreateInputsFrom(const std::vector< Layer *> &layers)
An OriginsDescriptor for the ConcatLayer.
This layer represents a merge operation.
const std::string & GetNameStr() const
std::vector< SubgraphViewPtr > Subgraphs
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
GPU Execution: OpenCL: ArmCompute.
BOOST_AUTO_TEST_CASE(CheckConvolution2dLayer)
An ActivationDescriptor for the ActivationLayer.
const BackendId & GetBackendId() const
std::vector< InputSlot * > InputSlots
This layer represents an addition operation.
void SubstituteSubgraph(SubgraphView &subgraph, IConnectableLayer *substituteLayer)
Substitutes the given sub-graph with either a new layer or a new sub-graph.
const InputSlots & GetInputSlots() const
std::unique_ptr< SubgraphView > SubgraphViewPtr
BOOST_AUTO_TEST_SUITE_END()
SubgraphView::SubgraphViewPtr CreateSubgraphViewFrom(SubgraphView::InputSlots &&inputs, SubgraphView::OutputSlots &&outputs, SubgraphView::Layers &&layers)
SubgraphView::OutputSlots CreateOutputsFrom(const std::vector< Layer *> &layers)
static Subgraphs SelectSubgraphs(Graph &graph, const LayerSelectorFunction &selector)
Selects subgraphs from a graph based on the selector function and the algorithm.
const OutputSlots & GetOutputSlots() const
CPU Execution: NEON: ArmCompute.
Iterator end()
Returns iterator pointing to the end of the list. Lowercase for range-based for loops.
const Layers & GetLayers() const
LayerType GetType() 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 PreCompiledDescriptor for the PreCompiledLayer.
std::list< Layer * > Layers
size_t GetNumLayers() const
LayerT * InsertNewLayer(InputSlot &insertBefore, Args &&... args)
Inserts a new layer between the output slot currently connected to insertBefore and insertBefore itse...
const InputSlot * GetConnection(unsigned int index) const override