blob: 77390cb0a478d4676d4d7eea53982b5cda3f4ecb [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
surmeh01bceff2f2018-03-29 16:29:27 +010061Status OptimizedNetwork::SerializeToDot(std::ostream& stream) const
62{
63 return m_Graph->SerializeToDot(stream);
64}
65
telsoa014fcda012018-03-09 14:13:49 +000066IOptimizedNetworkPtr Optimize(const INetwork& inNetwork, const DeviceSpec& deviceSpec)
67{
68 const Network& network = *boost::polymorphic_downcast<const Network*>(&inNetwork);
69 std::unique_ptr<Graph> graph = std::make_unique<Graph>(network.GetGraph());
70
71 OptimizedNetwork* optNet = new OptimizedNetwork(std::move(graph));
72
surmeh01bceff2f2018-03-29 16:29:27 +010073 Optimizer::Optimize(optNet->GetGraph());
telsoa014fcda012018-03-09 14:13:49 +000074
75 // Infer the tensor infos for all output slots. Throws an exception on failure.
76 optNet->GetGraph().InferTensorInfos();
77
78 // Assign a compute device for all nodes
79 for (auto&& layer : optNet->GetGraph())
80 {
81 DataType dataType = layer->GetDataType();
82
83 // Default to the user-requested compute device from the Runtime
84 layer->SetComputeDevice(deviceSpec.DefaultComputeDevice);
85
86 // If the layer is unsupported by this device, fall back to reference
87 std::string reasonIfUnsupported;
88 if (!IWorkloadFactory::IsLayerSupported(*layer, dataType, reasonIfUnsupported))
89 {
90 BOOST_LOG_TRIVIAL(warning) << "Layer of type " << GetLayerTypeAsCString(layer->GetType()) <<
91 " is not supported on requested backend " << layer->GetComputeDevice() << " (reason: " <<
92 reasonIfUnsupported << "), falling back to CpuRef backend.";
93 layer->SetComputeDevice(Compute::CpuRef);
94 }
95
96 BOOST_ASSERT_MSG(IWorkloadFactory::IsLayerSupported(*layer, dataType, reasonIfUnsupported),
97 "Layer has no valid compute device");
98 }
99
100 optNet->GetGraph().AddCopyLayers();
101
102 return {optNet, &IOptimizedNetwork::Destroy};
103}
104
105Network::Network()
106: m_Graph(std::make_unique<Graph>())
107{
108}
109
110Network::~Network()
111{
112}
113
114IConnectableLayer* Network::AddInputLayer(LayerBindingId id, const char* name)
115{
116 return m_Graph->AddLayer<InputLayer>(id, name);
117}
118
119IConnectableLayer* Network::AddFullyConnectedLayerImpl(const FullyConnectedDescriptor& fullyConnectedDescriptor,
120 const ConstTensor& weights,
121 const ConstTensor* biases,
122 const char* name)
123{
124 if (fullyConnectedDescriptor.m_BiasEnabled && (biases == nullptr))
125 {
126 throw InvalidArgumentException("AddFullyConnectedLayer: biases cannot be NULL");
127 }
128
129 const auto layer = m_Graph->AddLayer<FullyConnectedLayer>(fullyConnectedDescriptor, name);
130
131 layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights);
132
133 if (fullyConnectedDescriptor.m_BiasEnabled)
134 {
135 layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(*biases);
136 }
137
138 return layer;
139}
140
141IConnectableLayer* Network::AddFullyConnectedLayer(const FullyConnectedDescriptor& fullyConnectedDescriptor,
142 const ConstTensor& weights,
143 const char* name)
144{
145 return AddFullyConnectedLayerImpl(fullyConnectedDescriptor, weights, nullptr, name);
146}
147
148IConnectableLayer* Network::AddFullyConnectedLayer(const FullyConnectedDescriptor& fullyConnectedDescriptor,
149 const ConstTensor& weights,
150 const ConstTensor& biases,
151 const char* name)
152{
153 return AddFullyConnectedLayerImpl(fullyConnectedDescriptor, weights, &biases, name);
154}
155
156IConnectableLayer* Network::AddConvolution2dLayerImpl(const Convolution2dDescriptor& convolution2dDescriptor,
157 const ConstTensor& weights,
158 const ConstTensor* biases,
159 const char* name)
160{
161 if (convolution2dDescriptor.m_BiasEnabled && (biases == nullptr))
162 {
163 throw InvalidArgumentException("AddConvolution2dLayer: biases cannot be NULL");
164 }
165
166 const auto layer = m_Graph->AddLayer<Convolution2dLayer>(convolution2dDescriptor, name);
167
168 layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights);
169
170 if (convolution2dDescriptor.m_BiasEnabled)
171 {
172 layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(*biases);
173 }
174
175 return layer;
176}
177
178IConnectableLayer* Network::AddConvolution2dLayer(const Convolution2dDescriptor& convolution2dDescriptor,
179 const ConstTensor& weights,
180 const char* name)
181{
182 return AddConvolution2dLayerImpl(convolution2dDescriptor, weights, nullptr, name);
183}
184IConnectableLayer* Network::AddConvolution2dLayer(const Convolution2dDescriptor& convolution2dDescriptor,
185 const ConstTensor& weights,
186 const ConstTensor& biases,
187 const char* name)
188{
189 return AddConvolution2dLayerImpl(convolution2dDescriptor, weights, &biases, name);
190}
191
192IConnectableLayer* Network::AddDepthwiseConvolution2dLayerImpl(
193 const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
194 const ConstTensor& weights,
195 const ConstTensor* biases,
196 const char* name)
197{
198 if (convolution2dDescriptor.m_BiasEnabled && (biases == nullptr))
199 {
200 throw InvalidArgumentException("AddDepthwiseConvolution2dLayer: biases cannot be NULL");
201 }
202
203 const auto layer = m_Graph->AddLayer<DepthwiseConvolution2dLayer>(convolution2dDescriptor, name);
204
205 layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights);
206
207 if (convolution2dDescriptor.m_BiasEnabled)
208 {
209 layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(*biases);
210 }
211
212 return layer;
213}
214
215IConnectableLayer* Network::AddDepthwiseConvolution2dLayer(
216 const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
217 const ConstTensor& weights,
218 const char* name)
219{
220 return AddDepthwiseConvolution2dLayerImpl(convolution2dDescriptor, weights, nullptr, name);
221}
222IConnectableLayer* Network::AddDepthwiseConvolution2dLayer(
223 const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
224 const ConstTensor& weights,
225 const ConstTensor& biases,
226 const char* name)
227{
228 return AddDepthwiseConvolution2dLayerImpl(convolution2dDescriptor, weights, &biases, name);
229}
230
231IConnectableLayer* Network::AddPermuteLayer(const PermuteDescriptor& permuteDescriptor,
232 const char* name)
233{
234 return m_Graph->AddLayer<PermuteLayer>(permuteDescriptor, name);
235}
236
237IConnectableLayer* Network::AddPooling2dLayer(const Pooling2dDescriptor& pooling2dDescriptor,
238 const char* name)
239{
240 return m_Graph->AddLayer<Pooling2dLayer>(pooling2dDescriptor, name);
241}
242
243IConnectableLayer* Network::AddActivationLayer(const ActivationDescriptor& activationDescriptor,
244 const char* name)
245{
246 return m_Graph->AddLayer<ActivationLayer>(activationDescriptor, name);
247}
248
249IConnectableLayer* Network::AddNormalizationLayer(const NormalizationDescriptor& normalizationDescriptor,
250 const char* name)
251{
252 return m_Graph->AddLayer<NormalizationLayer>(normalizationDescriptor, name);
253}
254
255IConnectableLayer* Network::AddSoftmaxLayer(const SoftmaxDescriptor& softmaxDescriptor,
256 const char* name)
257{
258 return m_Graph->AddLayer<SoftmaxLayer>(softmaxDescriptor, name);
259}
260
261IConnectableLayer* Network::AddSplitterLayer(const ViewsDescriptor& splitterDescriptor,
262 const char* name)
263{
264 return m_Graph->AddLayer<SplitterLayer>(splitterDescriptor, name);
265}
266
267IConnectableLayer* Network::AddMergerLayer(const OriginsDescriptor& mergerDescriptor,
268 const char* name)
269{
270 return m_Graph->AddLayer<MergerLayer>(mergerDescriptor, name);
271}
272
273IConnectableLayer* Network::AddAdditionLayer(const char* name)
274{
275 return m_Graph->AddLayer<AdditionLayer>(name);
276}
277
278IConnectableLayer* Network::AddMultiplicationLayer(const char* name)
279{
280 return m_Graph->AddLayer<MultiplicationLayer>(name);
281}
282
283IConnectableLayer* Network::AddOutputLayer(LayerBindingId id, const char* name)
284{
285 return m_Graph->AddLayer<OutputLayer>(id, name);
286}
287
288IConnectableLayer* Network::AddBatchNormalizationLayer(const BatchNormalizationDescriptor& desc,
289 const ConstTensor& mean,
290 const ConstTensor& variance,
291 const ConstTensor& beta,
292 const ConstTensor& gamma,
293 const char* name)
294{
295 const auto layer = m_Graph->AddLayer<BatchNormalizationLayer>(desc, name);
296
297 layer->m_Mean = std::make_unique<ScopedCpuTensorHandle>(mean);
298 layer->m_Variance = std::make_unique<ScopedCpuTensorHandle>(variance);
299 layer->m_Beta = std::make_unique<ScopedCpuTensorHandle>(beta);
300 layer->m_Gamma = std::make_unique<ScopedCpuTensorHandle>(gamma);
301
302 return layer;
303}
304
305IConnectableLayer* Network::AddResizeBilinearLayer(const ResizeBilinearDescriptor& resizeDescriptor, const char* name)
306{
307 return m_Graph->AddLayer<ResizeBilinearLayer>(resizeDescriptor,name);
308}
309
310IConnectableLayer* Network::AddL2NormalizationLayer(const char* name)
311{
312 return m_Graph->AddLayer<L2NormalizationLayer>(name);
313}
314
315IConnectableLayer* Network::AddConstantLayer(const ConstTensor& input, const char* name)
316{
317 return m_Graph->AddLayer<ConstantLayer>(std::make_shared<ScopedCpuTensorHandle>(input), name);
318}
319
320IConnectableLayer* Network::AddReshapeLayer(const ReshapeDescriptor& reshapeDescriptor, const char* name)
321{
322 return m_Graph->AddLayer<ReshapeLayer>(reshapeDescriptor, name);
323}
324
325IConnectableLayer* Network::AddFloorLayer(const char* name)
326{
327 return m_Graph->AddLayer<FloorLayer>(name);
328}
329
330OptimizedNetwork::OptimizedNetwork(std::unique_ptr<Graph> graph)
331 : m_Graph(std::move(graph))
332{
333}
334
335OptimizedNetwork::~OptimizedNetwork()
336{
337}
338
339} // namespace armnn
340