blob: 4ee68b3c48d5fd59073316a58cdab1667f038a23 [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// See LICENSE file in the project root for full license information.
4//
5#include "Network.hpp"
6#include "Graph.hpp"
7#include "Layer.hpp"
8#include "backends/CpuTensorHandle.hpp"
9#include "backends/WorkloadFactory.hpp"
10#include "Layers.hpp"
11#include "Optimizer.hpp"
12
13#include <armnn/Utils.hpp>
14
15#include <fcntl.h>
16#include <algorithm>
17#include <fstream>
18#include <memory>
19
20#include <boost/assert.hpp>
21#include <boost/format.hpp>
22#include <boost/log/trivial.hpp>
23#include <boost/numeric/conversion/converter_policies.hpp>
24#include <boost/cast.hpp>
25
26namespace armnn
27{
28
29armnn::INetwork* INetwork::CreateRaw()
30{
31 return new Network();
32}
33
34armnn::INetworkPtr INetwork::Create()
35{
36 return INetworkPtr(CreateRaw(), &INetwork::Destroy);
37}
38
39void INetwork::Destroy(INetwork* network)
40{
41 delete boost::polymorphic_downcast<Network*>(network);
42}
43
44Status Network::PrintGraph()
45{
46 m_Graph->Print();
47 return Status::Success;
48}
49
50void IOptimizedNetwork::Destroy(IOptimizedNetwork* network)
51{
52 delete boost::polymorphic_downcast<OptimizedNetwork*>(network);
53}
54
55Status OptimizedNetwork::PrintGraph()
56{
57 m_Graph->Print();
58 return Status::Success;
59}
60
61IOptimizedNetworkPtr Optimize(const INetwork& inNetwork, const DeviceSpec& deviceSpec)
62{
63 const Network& network = *boost::polymorphic_downcast<const Network*>(&inNetwork);
64 std::unique_ptr<Graph> graph = std::make_unique<Graph>(network.GetGraph());
65
66 OptimizedNetwork* optNet = new OptimizedNetwork(std::move(graph));
67
68 Optimizer::Get().Optimize(optNet->GetGraph());
69
70 // Infer the tensor infos for all output slots. Throws an exception on failure.
71 optNet->GetGraph().InferTensorInfos();
72
73 // Assign a compute device for all nodes
74 for (auto&& layer : optNet->GetGraph())
75 {
76 DataType dataType = layer->GetDataType();
77
78 // Default to the user-requested compute device from the Runtime
79 layer->SetComputeDevice(deviceSpec.DefaultComputeDevice);
80
81 // If the layer is unsupported by this device, fall back to reference
82 std::string reasonIfUnsupported;
83 if (!IWorkloadFactory::IsLayerSupported(*layer, dataType, reasonIfUnsupported))
84 {
85 BOOST_LOG_TRIVIAL(warning) << "Layer of type " << GetLayerTypeAsCString(layer->GetType()) <<
86 " is not supported on requested backend " << layer->GetComputeDevice() << " (reason: " <<
87 reasonIfUnsupported << "), falling back to CpuRef backend.";
88 layer->SetComputeDevice(Compute::CpuRef);
89 }
90
91 BOOST_ASSERT_MSG(IWorkloadFactory::IsLayerSupported(*layer, dataType, reasonIfUnsupported),
92 "Layer has no valid compute device");
93 }
94
95 optNet->GetGraph().AddCopyLayers();
96
97 return {optNet, &IOptimizedNetwork::Destroy};
98}
99
100Network::Network()
101: m_Graph(std::make_unique<Graph>())
102{
103}
104
105Network::~Network()
106{
107}
108
109IConnectableLayer* Network::AddInputLayer(LayerBindingId id, const char* name)
110{
111 return m_Graph->AddLayer<InputLayer>(id, name);
112}
113
114IConnectableLayer* Network::AddFullyConnectedLayerImpl(const FullyConnectedDescriptor& fullyConnectedDescriptor,
115 const ConstTensor& weights,
116 const ConstTensor* biases,
117 const char* name)
118{
119 if (fullyConnectedDescriptor.m_BiasEnabled && (biases == nullptr))
120 {
121 throw InvalidArgumentException("AddFullyConnectedLayer: biases cannot be NULL");
122 }
123
124 const auto layer = m_Graph->AddLayer<FullyConnectedLayer>(fullyConnectedDescriptor, name);
125
126 layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights);
127
128 if (fullyConnectedDescriptor.m_BiasEnabled)
129 {
130 layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(*biases);
131 }
132
133 return layer;
134}
135
136IConnectableLayer* Network::AddFullyConnectedLayer(const FullyConnectedDescriptor& fullyConnectedDescriptor,
137 const ConstTensor& weights,
138 const char* name)
139{
140 return AddFullyConnectedLayerImpl(fullyConnectedDescriptor, weights, nullptr, name);
141}
142
143IConnectableLayer* Network::AddFullyConnectedLayer(const FullyConnectedDescriptor& fullyConnectedDescriptor,
144 const ConstTensor& weights,
145 const ConstTensor& biases,
146 const char* name)
147{
148 return AddFullyConnectedLayerImpl(fullyConnectedDescriptor, weights, &biases, name);
149}
150
151IConnectableLayer* Network::AddConvolution2dLayerImpl(const Convolution2dDescriptor& convolution2dDescriptor,
152 const ConstTensor& weights,
153 const ConstTensor* biases,
154 const char* name)
155{
156 if (convolution2dDescriptor.m_BiasEnabled && (biases == nullptr))
157 {
158 throw InvalidArgumentException("AddConvolution2dLayer: biases cannot be NULL");
159 }
160
161 const auto layer = m_Graph->AddLayer<Convolution2dLayer>(convolution2dDescriptor, name);
162
163 layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights);
164
165 if (convolution2dDescriptor.m_BiasEnabled)
166 {
167 layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(*biases);
168 }
169
170 return layer;
171}
172
173IConnectableLayer* Network::AddConvolution2dLayer(const Convolution2dDescriptor& convolution2dDescriptor,
174 const ConstTensor& weights,
175 const char* name)
176{
177 return AddConvolution2dLayerImpl(convolution2dDescriptor, weights, nullptr, name);
178}
179IConnectableLayer* Network::AddConvolution2dLayer(const Convolution2dDescriptor& convolution2dDescriptor,
180 const ConstTensor& weights,
181 const ConstTensor& biases,
182 const char* name)
183{
184 return AddConvolution2dLayerImpl(convolution2dDescriptor, weights, &biases, name);
185}
186
187IConnectableLayer* Network::AddDepthwiseConvolution2dLayerImpl(
188 const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
189 const ConstTensor& weights,
190 const ConstTensor* biases,
191 const char* name)
192{
193 if (convolution2dDescriptor.m_BiasEnabled && (biases == nullptr))
194 {
195 throw InvalidArgumentException("AddDepthwiseConvolution2dLayer: biases cannot be NULL");
196 }
197
198 const auto layer = m_Graph->AddLayer<DepthwiseConvolution2dLayer>(convolution2dDescriptor, name);
199
200 layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights);
201
202 if (convolution2dDescriptor.m_BiasEnabled)
203 {
204 layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(*biases);
205 }
206
207 return layer;
208}
209
210IConnectableLayer* Network::AddDepthwiseConvolution2dLayer(
211 const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
212 const ConstTensor& weights,
213 const char* name)
214{
215 return AddDepthwiseConvolution2dLayerImpl(convolution2dDescriptor, weights, nullptr, name);
216}
217IConnectableLayer* Network::AddDepthwiseConvolution2dLayer(
218 const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
219 const ConstTensor& weights,
220 const ConstTensor& biases,
221 const char* name)
222{
223 return AddDepthwiseConvolution2dLayerImpl(convolution2dDescriptor, weights, &biases, name);
224}
225
226IConnectableLayer* Network::AddPermuteLayer(const PermuteDescriptor& permuteDescriptor,
227 const char* name)
228{
229 return m_Graph->AddLayer<PermuteLayer>(permuteDescriptor, name);
230}
231
232IConnectableLayer* Network::AddPooling2dLayer(const Pooling2dDescriptor& pooling2dDescriptor,
233 const char* name)
234{
235 return m_Graph->AddLayer<Pooling2dLayer>(pooling2dDescriptor, name);
236}
237
238IConnectableLayer* Network::AddActivationLayer(const ActivationDescriptor& activationDescriptor,
239 const char* name)
240{
241 return m_Graph->AddLayer<ActivationLayer>(activationDescriptor, name);
242}
243
244IConnectableLayer* Network::AddNormalizationLayer(const NormalizationDescriptor& normalizationDescriptor,
245 const char* name)
246{
247 return m_Graph->AddLayer<NormalizationLayer>(normalizationDescriptor, name);
248}
249
250IConnectableLayer* Network::AddSoftmaxLayer(const SoftmaxDescriptor& softmaxDescriptor,
251 const char* name)
252{
253 return m_Graph->AddLayer<SoftmaxLayer>(softmaxDescriptor, name);
254}
255
256IConnectableLayer* Network::AddSplitterLayer(const ViewsDescriptor& splitterDescriptor,
257 const char* name)
258{
259 return m_Graph->AddLayer<SplitterLayer>(splitterDescriptor, name);
260}
261
262IConnectableLayer* Network::AddMergerLayer(const OriginsDescriptor& mergerDescriptor,
263 const char* name)
264{
265 return m_Graph->AddLayer<MergerLayer>(mergerDescriptor, name);
266}
267
268IConnectableLayer* Network::AddAdditionLayer(const char* name)
269{
270 return m_Graph->AddLayer<AdditionLayer>(name);
271}
272
273IConnectableLayer* Network::AddMultiplicationLayer(const char* name)
274{
275 return m_Graph->AddLayer<MultiplicationLayer>(name);
276}
277
278IConnectableLayer* Network::AddOutputLayer(LayerBindingId id, const char* name)
279{
280 return m_Graph->AddLayer<OutputLayer>(id, name);
281}
282
283IConnectableLayer* Network::AddBatchNormalizationLayer(const BatchNormalizationDescriptor& desc,
284 const ConstTensor& mean,
285 const ConstTensor& variance,
286 const ConstTensor& beta,
287 const ConstTensor& gamma,
288 const char* name)
289{
290 const auto layer = m_Graph->AddLayer<BatchNormalizationLayer>(desc, name);
291
292 layer->m_Mean = std::make_unique<ScopedCpuTensorHandle>(mean);
293 layer->m_Variance = std::make_unique<ScopedCpuTensorHandle>(variance);
294 layer->m_Beta = std::make_unique<ScopedCpuTensorHandle>(beta);
295 layer->m_Gamma = std::make_unique<ScopedCpuTensorHandle>(gamma);
296
297 return layer;
298}
299
300IConnectableLayer* Network::AddResizeBilinearLayer(const ResizeBilinearDescriptor& resizeDescriptor, const char* name)
301{
302 return m_Graph->AddLayer<ResizeBilinearLayer>(resizeDescriptor,name);
303}
304
305IConnectableLayer* Network::AddL2NormalizationLayer(const char* name)
306{
307 return m_Graph->AddLayer<L2NormalizationLayer>(name);
308}
309
310IConnectableLayer* Network::AddConstantLayer(const ConstTensor& input, const char* name)
311{
312 return m_Graph->AddLayer<ConstantLayer>(std::make_shared<ScopedCpuTensorHandle>(input), name);
313}
314
315IConnectableLayer* Network::AddReshapeLayer(const ReshapeDescriptor& reshapeDescriptor, const char* name)
316{
317 return m_Graph->AddLayer<ReshapeLayer>(reshapeDescriptor, name);
318}
319
320IConnectableLayer* Network::AddFloorLayer(const char* name)
321{
322 return m_Graph->AddLayer<FloorLayer>(name);
323}
324
325OptimizedNetwork::OptimizedNetwork(std::unique_ptr<Graph> graph)
326 : m_Graph(std::move(graph))
327{
328}
329
330OptimizedNetwork::~OptimizedNetwork()
331{
332}
333
334} // namespace armnn
335