18 #include <boost/cast.hpp> 19 #include <boost/test/unit_test.hpp> 28 auto firstPos = std::find(order.begin(), order.end(), first);
29 auto secondPos = std::find(firstPos, order.end(), second);
31 return (secondPos != order.end());
91 std::vector<armnn::Layer*> order;
123 BOOST_TEST(
CheckOrder(graph, layerA, layerB));
124 BOOST_TEST(
CheckOrder(graph, layerA, layerC));
125 BOOST_TEST(
CheckOrder(graph, layerB, layerD));
126 BOOST_TEST(
CheckOrder(graph, layerC, layerD));
142 BOOST_TEST(
CheckOrder(graph, layerA, layerB));
143 BOOST_TEST(
CheckOrder(graph, layerA, layerC));
144 BOOST_TEST(
CheckOrder(graph, layerB, layerD));
145 BOOST_TEST(
CheckOrder(graph, layerC, layerE));
146 BOOST_TEST(
CheckOrder(graph, layerE, layerD));
164 BOOST_TEST(
CheckOrder(graph, layerA, layerB));
165 BOOST_TEST(
CheckOrder(graph, layerA, layerF));
166 BOOST_TEST(
CheckOrder(graph, layerF, layerC));
167 BOOST_TEST(
CheckOrder(graph, layerB, layerD));
168 BOOST_TEST(
CheckOrder(graph, layerC, layerE));
169 BOOST_TEST(
CheckOrder(graph, layerE, layerD));
177 std::vector<armnn::Layer*> order;
209 BOOST_TEST(
CheckOrder(graph, layerA, layerB));
210 BOOST_TEST(
CheckOrder(graph, layerA, layerC));
211 BOOST_TEST(
CheckOrder(graph, layerB, layerD));
212 BOOST_TEST(
CheckOrder(graph, layerC, layerD));
228 BOOST_TEST(
CheckOrder(graph, layerA, layerB));
229 BOOST_TEST(
CheckOrder(graph, layerA, layerC));
230 BOOST_TEST(
CheckOrder(graph, layerB, layerD));
231 BOOST_TEST(
CheckOrder(graph, layerC, layerE));
232 BOOST_TEST(
CheckOrder(graph, layerE, layerD));
251 BOOST_TEST(
CheckOrder(graph, layerA, layerF));
252 BOOST_TEST(
CheckOrder(graph, layerF, layerB));
253 BOOST_TEST(
CheckOrder(graph, layerF, layerC));
254 BOOST_TEST(
CheckOrder(graph, layerB, layerD));
255 BOOST_TEST(
CheckOrder(graph, layerC, layerE));
256 BOOST_TEST(
CheckOrder(graph, layerE, layerD));
261 using Edge = std::pair<const armnn::Layer*, const armnn::Layer*>;
264 static std::vector<Edge> GetEdgeList(
const armnn::Graph& graph)
266 std::vector<Edge> edges;
268 for (
auto&& srcLayer: graph)
270 const unsigned int numOutputSlots = srcLayer->GetNumOutputSlots();
271 for (
unsigned int s = 0; s < numOutputSlots; ++s)
275 for (
unsigned int c = 0; c < numConnections; ++c)
277 auto inputSlot = boost::polymorphic_downcast<const armnn::InputSlot*>(outputSlot.
GetConnection(c));
278 edges.emplace_back(srcLayer, &inputSlot->GetOwningLayer());
288 std::vector<Edge> origEdges = GetEdgeList(origGraph);
289 std::vector<Edge> newEdges = GetEdgeList(graph);
293 std::vector<Edge> sortedNewEdges = newEdges;
294 std::sort(sortedNewEdges.begin(), sortedNewEdges.end());
296 auto last = std::unique(sortedNewEdges.begin(), sortedNewEdges.end());
297 BOOST_CHECK_MESSAGE(last == sortedNewEdges.end(),
"New graph contains duplicate edges!");
301 while (!newEdges.empty())
303 const Edge edge = std::move(newEdges.back());
307 int originalEdge = -1;
308 for (
unsigned int i = 0; i < origEdges.size(); i++)
310 const Edge& origEdge = origEdges[i];
311 if (origEdge.first->GetNameStr() == edge.first->GetNameStr() &&
312 origEdge.second->GetNameStr() == edge.second->GetNameStr())
318 if (originalEdge != -1)
323 BOOST_TEST(srcLayer);
324 BOOST_TEST(dstLayer);
327 if (srcLayer && dstLayer)
333 origEdges.erase(origEdges.begin() + originalEdge);
342 if (srcLayer ==
nullptr || dstLayer ==
nullptr)
344 BOOST_ERROR(
"At least one of the two ends of a new edge (" << edge.first <<
", " << edge.second <<
") " 345 "introduced after adding copy layers to a graph " 346 "correspond to a layer not known to the graph");
354 if (srcLayerInOrigGraph == dstLayerInOrigGraph)
356 BOOST_ERROR(
"A new edge (" 357 << edge.first->GetName()
359 << edge.second->GetName()
360 <<
") introduced after adding copy " 361 "layers to a graph is invalid. One of the ends should be present in the original " 362 "graph and the other should not, but " 363 << (srcLayerInOrigGraph ?
"both are" :
"none are"));
367 const armnn::Layer* copyLayer = srcLayerInOrigGraph ? dstLayer : srcLayer;
368 const armnn::Layer* nonCopyLayer = srcLayerInOrigGraph ? srcLayer : dstLayer;
371 std::vector<Edge> adjEdges;
372 auto it = newEdges.begin();
373 while (it != newEdges.end())
376 if (copyLayer == (srcLayerInOrigGraph ? newEdge.first : newEdge.second))
378 adjEdges.push_back(newEdge);
381 it = newEdges.erase(it);
389 if (adjEdges.empty())
391 BOOST_ERROR(
"An edge connecting a layer and a copy layer exists, (" << edge.first <<
", " <<
392 edge.second <<
"), but no other edges connecting the copy layer '" << copyLayer->
GetName()
393 <<
"' to other layers could be found");
398 for (
const Edge& adjEdge : adjEdges)
401 const armnn::Layer* adjLayer = srcLayerInOrigGraph ? adjEdge.second : adjEdge.first;
405 BOOST_ERROR(
"An edge (" << adjEdge.first <<
", " << adjEdge.second <<
") is adjacent to an edge " 406 "connecting a layer and a copy layer, (" << edge.first <<
", " << edge.second <<
"), " 407 "but the non-copy layer in the former does not correspond to a layer");
416 const armnn::Layer* origEdgeSrc = srcLayerInOrigGraph ? nonCopyLayer : adjLayer;
417 const armnn::Layer* origEdgeDst = srcLayerInOrigGraph ? adjLayer : nonCopyLayer;
419 auto origEdgeIter = origEdges.begin();
420 for (; origEdgeIter != origEdges.end(); origEdgeIter++)
422 if (origEdgeIter->first->GetNameStr() == origEdgeSrc->
GetNameStr() &&
423 origEdgeIter->second->GetNameStr() == origEdgeDst->
GetNameStr())
429 if (origEdgeIter != origEdges.end())
431 origEdges.erase(origEdgeIter);
435 BOOST_ERROR(
"An edge (" << adjEdge.first <<
", " << adjEdge.second <<
") is adjacent to an " 436 "edge connecting a layer and a copy layer, (" << edge.first <<
", " << edge.second <<
437 "), but there is no edge connecting the layers in the original graph");
444 BOOST_TEST(origEdges.empty(),
"Not all of the edges in the original graph correspond to paths in the new graph");
447 struct CopyLayersFixture
453 void InitialiseTestGraph()
455 using namespace armnn;
458 Layer*
const inputLayer = AddLayer<InputLayer>(0,
"input");
462 Layer*
const convLayer1 = AddLayer<Convolution2dLayer>(convolutionDefaults,
"conv1");
467 Layer*
const convLayer2 = AddLayer<Convolution2dLayer>(convolutionDefaults,
"conv2");
473 Layer*
const concatLayer = AddLayer<ConcatLayer>(concatDefaults,
"concat");
480 Layer*
const actLayer = AddLayer<ActivationLayer>(activationDefaults,
"act");
486 Layer*
const softmaxLayer = AddLayer<SoftmaxLayer>(softmaxDefaults,
"softmax");
491 Layer*
const outputLayer = AddLayer<OutputLayer>(0,
"output");
509 std::map<armnn::BackendId, std::unique_ptr<armnn::IBackendInternal>> m_Backends;
514 template <
typename LayerType,
typename... Args>
519 for (
auto slot = layer->BeginOutputSlots(); slot != layer->EndOutputSlots(); ++slot)
521 slot->SetTensorInfo(m_TensorDesc);
530 InitialiseTestGraph();
532 m_Graph.AddCompatibilityLayers(m_Backends, m_FactoryRegistry);
534 TestGraphAfterAddingCopyLayers(m_Graph, origGraph);
539 InitialiseTestGraph();
540 m_Graph.AddCompatibilityLayers(m_Backends, m_FactoryRegistry);
543 const std::vector<Edge> edges = GetEdgeList(m_Graph);
544 for (
int i = 0; i < 4; ++i)
546 m_Graph.AddCompatibilityLayers(m_Backends, m_FactoryRegistry);
547 const std::vector<Edge> otherEdges = GetEdgeList(m_Graph);
548 BOOST_TEST((edges == otherEdges));
581 std::vector<Edge> edges = GetEdgeList(graph);
583 std::sort(edges.begin(), edges.end());
584 auto last = std::unique(edges.begin(), edges.end());
585 BOOST_CHECK_MESSAGE(last == edges.end(),
"Found duplicated edges after AddCompatibilityLayers()");
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.
void SetEdgeStrategy(unsigned int connectionIndex, EdgeStrategy strategy)
No strategy has been defined. Used internally to verify integrity of optimizations.
CPU Execution: Reference C++ kernels.
armnn::Layer * GetFirstLayerWithName(armnn::Graph &graph, const std::string &name)
bool CheckOrder(const armnn::Graph &graph, const armnn::Layer *first, const armnn::Layer *second)
Checks that first comes before second in the order.
LayerT * AddLayer(Args &&... args)
Adds a new layer, of type LayerType, to the graph constructed with the arguments passed.
A Convolution2dDescriptor for the Convolution2dLayer.
Source backends tensor data can be exported to destination backend tensor without copy...
int Connect(InputSlot &destination)
bool GraphHasNamedLayer(const armnn::Graph &graph, const std::string &name)
This layer represents an activation operation with the specified activation function.
Copyright (c) 2020 ARM Limited.
void SetBackendId(const BackendId &id)
virtual const IInputSlot * GetConnection(unsigned int index) const =0
BOOST_CHECK(profilingService.GetCurrentState()==ProfilingState::WaitingForAck)
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.
An OriginsDescriptor for the ConcatLayer.
const std::string & GetNameStr() const
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(ClassGraph)
An ActivationDescriptor for the ActivationLayer.
const BackendId & GetBackendId() const
This layer represents an addition operation.
BOOST_AUTO_TEST_SUITE_END()
CPU Execution: NEON: ArmCompute.
void SetTensorInfo(const TensorInfo &tensorInfo) override
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
virtual unsigned int GetNumConnections() const =0
const char * GetName() const override
Returns the name of the layer.
Graph & TopologicalSort()
Sorts layers in topological order and return this.
LayerT * InsertNewLayer(InputSlot &insertBefore, Args &&... args)
Inserts a new layer between the output slot currently connected to insertBefore and insertBefore itse...
A SoftmaxDescriptor for the SoftmaxLayer.
void AddCompatibilityLayers(std::map< BackendId, std::unique_ptr< class IBackendInternal >> &backends, TensorHandleFactoryRegistry ®istry)
Modifies the graph in-place, removing edges connecting layers using different compute devices...
BOOST_FIXTURE_TEST_CASE(AddCopyLayers, CopyLayersFixture)