David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 1 | // |
| 2 | // Copyright © 2017 Arm Ltd. All rights reserved. |
| 3 | // SPDX-License-Identifier: MIT |
| 4 | // |
| 5 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 6 | #include "SubgraphView.hpp" |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 7 | #include "Graph.hpp" |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 8 | |
| 9 | #include <boost/numeric/conversion/cast.hpp> |
| 10 | |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 11 | #include <utility> |
| 12 | |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 13 | namespace armnn |
| 14 | { |
| 15 | |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 16 | namespace |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 17 | { |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 18 | |
| 19 | template <class C> |
| 20 | void AssertIfNullsOrDuplicates(const C& container, const std::string& errorMessage) |
| 21 | { |
| 22 | using T = typename C::value_type; |
| 23 | std::unordered_set<T> duplicateSet; |
| 24 | std::for_each(container.begin(), container.end(), [&duplicateSet, &errorMessage](const T& i) |
| 25 | { |
| 26 | // Ignore unused for release builds |
| 27 | boost::ignore_unused(errorMessage); |
| 28 | |
| 29 | // Check if the item is valid |
| 30 | BOOST_ASSERT_MSG(i, errorMessage.c_str()); |
| 31 | |
| 32 | // Check if a duplicate has been found |
| 33 | BOOST_ASSERT_MSG(duplicateSet.find(i) == duplicateSet.end(), errorMessage.c_str()); |
| 34 | |
| 35 | duplicateSet.insert(i); |
| 36 | }); |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 37 | } |
| 38 | |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 39 | } // anonymous namespace |
| 40 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 41 | SubgraphView::SubgraphView(Graph& graph) |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 42 | : m_InputSlots{} |
| 43 | , m_OutputSlots{} |
| 44 | , m_Layers(graph.begin(), graph.end()) |
| 45 | , m_ParentGraph(&graph) |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 46 | { |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 47 | CheckSubgraph(); |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 48 | } |
| 49 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 50 | SubgraphView::SubgraphView(Graph* parentGraph, InputSlots&& inputs, OutputSlots&& outputs, Layers&& layers) |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 51 | : m_InputSlots{inputs} |
| 52 | , m_OutputSlots{outputs} |
| 53 | , m_Layers{layers} |
| 54 | , m_ParentGraph(parentGraph) |
| 55 | { |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 56 | CheckSubgraph(); |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 57 | } |
| 58 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 59 | SubgraphView::SubgraphView(const SubgraphView& referenceSubgraph, |
| 60 | InputSlots&& inputs, |
| 61 | OutputSlots&& outputs, |
| 62 | Layers&& layers) |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 63 | : m_InputSlots{inputs} |
| 64 | , m_OutputSlots{outputs} |
| 65 | , m_Layers{layers} |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 66 | , m_ParentGraph(referenceSubgraph.m_ParentGraph) |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 67 | { |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 68 | CheckSubgraph(); |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 69 | } |
| 70 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 71 | SubgraphView::SubgraphView(const SubgraphView& subgraph) |
| 72 | : m_InputSlots(subgraph.m_InputSlots.begin(), subgraph.m_InputSlots.end()) |
| 73 | , m_OutputSlots(subgraph.m_OutputSlots.begin(), subgraph.m_OutputSlots.end()) |
| 74 | , m_Layers(subgraph.m_Layers.begin(), subgraph.m_Layers.end()) |
| 75 | , m_ParentGraph(subgraph.m_ParentGraph) |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 76 | { |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 77 | CheckSubgraph(); |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 78 | } |
| 79 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 80 | SubgraphView::SubgraphView(SubgraphView&& subgraph) |
| 81 | : m_InputSlots(std::move(subgraph.m_InputSlots)) |
| 82 | , m_OutputSlots(std::move(subgraph.m_OutputSlots)) |
| 83 | , m_Layers(std::move(subgraph.m_Layers)) |
| 84 | , m_ParentGraph(std::exchange(subgraph.m_ParentGraph, nullptr)) |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 85 | { |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 86 | CheckSubgraph(); |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 87 | } |
| 88 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 89 | SubgraphView::SubgraphView(const SubgraphView& referenceSubgraph, IConnectableLayer* layer) |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 90 | : m_InputSlots{} |
| 91 | , m_OutputSlots{} |
| 92 | , m_Layers{boost::polymorphic_downcast<Layer*>(layer)} |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 93 | , m_ParentGraph(referenceSubgraph.m_ParentGraph) |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 94 | { |
| 95 | unsigned int numInputSlots = layer->GetNumInputSlots(); |
| 96 | m_InputSlots.resize(numInputSlots); |
| 97 | for (unsigned int i = 0; i < numInputSlots; i++) |
| 98 | { |
| 99 | m_InputSlots.at(i) = boost::polymorphic_downcast<InputSlot*>(&(layer->GetInputSlot(i))); |
| 100 | } |
| 101 | |
| 102 | unsigned int numOutputSlots = layer->GetNumOutputSlots(); |
| 103 | m_OutputSlots.resize(numOutputSlots); |
| 104 | for (unsigned int i = 0; i < numOutputSlots; i++) |
| 105 | { |
| 106 | m_OutputSlots.at(i) = boost::polymorphic_downcast<OutputSlot*>(&(layer->GetOutputSlot(i))); |
| 107 | } |
| 108 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 109 | CheckSubgraph(); |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 110 | } |
| 111 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 112 | void SubgraphView::CheckSubgraph() |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 113 | { |
| 114 | // Check that the sub-graph has a valid parent graph |
| 115 | BOOST_ASSERT_MSG(m_ParentGraph, "Sub-graphs must have a parent graph"); |
| 116 | |
| 117 | // Check for invalid or duplicate input slots |
| 118 | AssertIfNullsOrDuplicates(m_InputSlots, "Sub-graphs cannot contain null or duplicate input slots"); |
| 119 | |
| 120 | // Check for invalid or duplicate output slots |
| 121 | AssertIfNullsOrDuplicates(m_OutputSlots, "Sub-graphs cannot contain null or duplicate output slots"); |
| 122 | |
| 123 | // Check for invalid or duplicate layers |
| 124 | AssertIfNullsOrDuplicates(m_Layers, "Sub-graphs cannot contain null or duplicate layers"); |
| 125 | |
| 126 | // Check that all the layers of the sub-graph belong to the parent graph |
| 127 | std::for_each(m_Layers.begin(), m_Layers.end(), [&](const Layer* l) |
| 128 | { |
| 129 | BOOST_ASSERT_MSG(std::find(m_ParentGraph->begin(), m_ParentGraph->end(), l) != m_ParentGraph->end(), |
| 130 | "Sub-graph layer is not a member of the parent graph"); |
| 131 | }); |
| 132 | } |
| 133 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 134 | void SubgraphView::Update(Graph &graph) |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 135 | { |
| 136 | m_InputSlots.clear(); |
| 137 | m_OutputSlots.clear(); |
| 138 | m_Layers.assign(graph.begin(), graph.end()); |
| 139 | m_ParentGraph = &graph; |
| 140 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 141 | CheckSubgraph(); |
Matteo Martincigh | adddddb | 2019-01-24 14:06:23 +0000 | [diff] [blame] | 142 | } |
| 143 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 144 | const SubgraphView::InputSlots& SubgraphView::GetInputSlots() const |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 145 | { |
| 146 | return m_InputSlots; |
| 147 | } |
| 148 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 149 | const SubgraphView::OutputSlots& SubgraphView::GetOutputSlots() const |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 150 | { |
| 151 | return m_OutputSlots; |
| 152 | } |
| 153 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 154 | const InputSlot* SubgraphView::GetInputSlot(unsigned int index) const |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 155 | { |
| 156 | return m_InputSlots.at(index); |
| 157 | } |
| 158 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 159 | InputSlot* SubgraphView::GetInputSlot(unsigned int index) |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 160 | { |
| 161 | return m_InputSlots.at(index); |
| 162 | } |
| 163 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 164 | const OutputSlot* SubgraphView::GetOutputSlot(unsigned int index) const |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 165 | { |
| 166 | return m_OutputSlots.at(index); |
| 167 | } |
| 168 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 169 | OutputSlot* SubgraphView::GetOutputSlot(unsigned int index) |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 170 | { |
| 171 | return m_OutputSlots.at(index); |
| 172 | } |
| 173 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 174 | unsigned int SubgraphView::GetNumInputSlots() const |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 175 | { |
| 176 | return boost::numeric_cast<unsigned int>(m_InputSlots.size()); |
| 177 | } |
| 178 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 179 | unsigned int SubgraphView::GetNumOutputSlots() const |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 180 | { |
| 181 | return boost::numeric_cast<unsigned int>(m_OutputSlots.size()); |
| 182 | } |
| 183 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 184 | const SubgraphView::Layers & SubgraphView::GetLayers() const |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 185 | { |
| 186 | return m_Layers; |
| 187 | } |
| 188 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 189 | SubgraphView::Layers::iterator SubgraphView::begin() |
Matteo Martincigh | 4912402 | 2019-01-11 13:25:59 +0000 | [diff] [blame] | 190 | { |
| 191 | return m_Layers.begin(); |
| 192 | } |
| 193 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 194 | SubgraphView::Iterator SubgraphView::end() |
Matteo Martincigh | 4912402 | 2019-01-11 13:25:59 +0000 | [diff] [blame] | 195 | { |
| 196 | return m_Layers.end(); |
| 197 | } |
| 198 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 199 | SubgraphView::ConstIterator SubgraphView::begin() const |
Matteo Martincigh | 4912402 | 2019-01-11 13:25:59 +0000 | [diff] [blame] | 200 | { |
| 201 | return m_Layers.begin(); |
| 202 | } |
| 203 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 204 | SubgraphView::ConstIterator SubgraphView::end() const |
Matteo Martincigh | 4912402 | 2019-01-11 13:25:59 +0000 | [diff] [blame] | 205 | { |
| 206 | return m_Layers.end(); |
| 207 | } |
| 208 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 209 | SubgraphView::ConstIterator SubgraphView::cbegin() const |
Matteo Martincigh | 4912402 | 2019-01-11 13:25:59 +0000 | [diff] [blame] | 210 | { |
| 211 | return begin(); |
| 212 | } |
| 213 | |
Derek Lamberti | ff05cc5 | 2019-04-26 13:05:17 +0100 | [diff] [blame^] | 214 | SubgraphView::ConstIterator SubgraphView::cend() const |
Matteo Martincigh | 4912402 | 2019-01-11 13:25:59 +0000 | [diff] [blame] | 215 | { |
| 216 | return end(); |
| 217 | } |
| 218 | |
David Beck | f98d21a | 2018-10-26 16:03:03 +0100 | [diff] [blame] | 219 | } // namespace armnn |