diff options
Diffstat (limited to 'src/armnn/Network.cpp')
-rw-r--r-- | src/armnn/Network.cpp | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/src/armnn/Network.cpp b/src/armnn/Network.cpp new file mode 100644 index 0000000000..4ee68b3c48 --- /dev/null +++ b/src/armnn/Network.cpp @@ -0,0 +1,335 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Network.hpp" +#include "Graph.hpp" +#include "Layer.hpp" +#include "backends/CpuTensorHandle.hpp" +#include "backends/WorkloadFactory.hpp" +#include "Layers.hpp" +#include "Optimizer.hpp" + +#include <armnn/Utils.hpp> + +#include <fcntl.h> +#include <algorithm> +#include <fstream> +#include <memory> + +#include <boost/assert.hpp> +#include <boost/format.hpp> +#include <boost/log/trivial.hpp> +#include <boost/numeric/conversion/converter_policies.hpp> +#include <boost/cast.hpp> + +namespace armnn +{ + +armnn::INetwork* INetwork::CreateRaw() +{ + return new Network(); +} + +armnn::INetworkPtr INetwork::Create() +{ + return INetworkPtr(CreateRaw(), &INetwork::Destroy); +} + +void INetwork::Destroy(INetwork* network) +{ + delete boost::polymorphic_downcast<Network*>(network); +} + +Status Network::PrintGraph() +{ + m_Graph->Print(); + return Status::Success; +} + +void IOptimizedNetwork::Destroy(IOptimizedNetwork* network) +{ + delete boost::polymorphic_downcast<OptimizedNetwork*>(network); +} + +Status OptimizedNetwork::PrintGraph() +{ + m_Graph->Print(); + return Status::Success; +} + +IOptimizedNetworkPtr Optimize(const INetwork& inNetwork, const DeviceSpec& deviceSpec) +{ + const Network& network = *boost::polymorphic_downcast<const Network*>(&inNetwork); + std::unique_ptr<Graph> graph = std::make_unique<Graph>(network.GetGraph()); + + OptimizedNetwork* optNet = new OptimizedNetwork(std::move(graph)); + + Optimizer::Get().Optimize(optNet->GetGraph()); + + // Infer the tensor infos for all output slots. Throws an exception on failure. + optNet->GetGraph().InferTensorInfos(); + + // Assign a compute device for all nodes + for (auto&& layer : optNet->GetGraph()) + { + DataType dataType = layer->GetDataType(); + + // Default to the user-requested compute device from the Runtime + layer->SetComputeDevice(deviceSpec.DefaultComputeDevice); + + // If the layer is unsupported by this device, fall back to reference + std::string reasonIfUnsupported; + if (!IWorkloadFactory::IsLayerSupported(*layer, dataType, reasonIfUnsupported)) + { + BOOST_LOG_TRIVIAL(warning) << "Layer of type " << GetLayerTypeAsCString(layer->GetType()) << + " is not supported on requested backend " << layer->GetComputeDevice() << " (reason: " << + reasonIfUnsupported << "), falling back to CpuRef backend."; + layer->SetComputeDevice(Compute::CpuRef); + } + + BOOST_ASSERT_MSG(IWorkloadFactory::IsLayerSupported(*layer, dataType, reasonIfUnsupported), + "Layer has no valid compute device"); + } + + optNet->GetGraph().AddCopyLayers(); + + return {optNet, &IOptimizedNetwork::Destroy}; +} + +Network::Network() +: m_Graph(std::make_unique<Graph>()) +{ +} + +Network::~Network() +{ +} + +IConnectableLayer* Network::AddInputLayer(LayerBindingId id, const char* name) +{ + return m_Graph->AddLayer<InputLayer>(id, name); +} + +IConnectableLayer* Network::AddFullyConnectedLayerImpl(const FullyConnectedDescriptor& fullyConnectedDescriptor, + const ConstTensor& weights, + const ConstTensor* biases, + const char* name) +{ + if (fullyConnectedDescriptor.m_BiasEnabled && (biases == nullptr)) + { + throw InvalidArgumentException("AddFullyConnectedLayer: biases cannot be NULL"); + } + + const auto layer = m_Graph->AddLayer<FullyConnectedLayer>(fullyConnectedDescriptor, name); + + layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights); + + if (fullyConnectedDescriptor.m_BiasEnabled) + { + layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(*biases); + } + + return layer; +} + +IConnectableLayer* Network::AddFullyConnectedLayer(const FullyConnectedDescriptor& fullyConnectedDescriptor, + const ConstTensor& weights, + const char* name) +{ + return AddFullyConnectedLayerImpl(fullyConnectedDescriptor, weights, nullptr, name); +} + +IConnectableLayer* Network::AddFullyConnectedLayer(const FullyConnectedDescriptor& fullyConnectedDescriptor, + const ConstTensor& weights, + const ConstTensor& biases, + const char* name) +{ + return AddFullyConnectedLayerImpl(fullyConnectedDescriptor, weights, &biases, name); +} + +IConnectableLayer* Network::AddConvolution2dLayerImpl(const Convolution2dDescriptor& convolution2dDescriptor, + const ConstTensor& weights, + const ConstTensor* biases, + const char* name) +{ + if (convolution2dDescriptor.m_BiasEnabled && (biases == nullptr)) + { + throw InvalidArgumentException("AddConvolution2dLayer: biases cannot be NULL"); + } + + const auto layer = m_Graph->AddLayer<Convolution2dLayer>(convolution2dDescriptor, name); + + layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights); + + if (convolution2dDescriptor.m_BiasEnabled) + { + layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(*biases); + } + + return layer; +} + +IConnectableLayer* Network::AddConvolution2dLayer(const Convolution2dDescriptor& convolution2dDescriptor, + const ConstTensor& weights, + const char* name) +{ + return AddConvolution2dLayerImpl(convolution2dDescriptor, weights, nullptr, name); +} +IConnectableLayer* Network::AddConvolution2dLayer(const Convolution2dDescriptor& convolution2dDescriptor, + const ConstTensor& weights, + const ConstTensor& biases, + const char* name) +{ + return AddConvolution2dLayerImpl(convolution2dDescriptor, weights, &biases, name); +} + +IConnectableLayer* Network::AddDepthwiseConvolution2dLayerImpl( + const DepthwiseConvolution2dDescriptor& convolution2dDescriptor, + const ConstTensor& weights, + const ConstTensor* biases, + const char* name) +{ + if (convolution2dDescriptor.m_BiasEnabled && (biases == nullptr)) + { + throw InvalidArgumentException("AddDepthwiseConvolution2dLayer: biases cannot be NULL"); + } + + const auto layer = m_Graph->AddLayer<DepthwiseConvolution2dLayer>(convolution2dDescriptor, name); + + layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights); + + if (convolution2dDescriptor.m_BiasEnabled) + { + layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(*biases); + } + + return layer; +} + +IConnectableLayer* Network::AddDepthwiseConvolution2dLayer( + const DepthwiseConvolution2dDescriptor& convolution2dDescriptor, + const ConstTensor& weights, + const char* name) +{ + return AddDepthwiseConvolution2dLayerImpl(convolution2dDescriptor, weights, nullptr, name); +} +IConnectableLayer* Network::AddDepthwiseConvolution2dLayer( + const DepthwiseConvolution2dDescriptor& convolution2dDescriptor, + const ConstTensor& weights, + const ConstTensor& biases, + const char* name) +{ + return AddDepthwiseConvolution2dLayerImpl(convolution2dDescriptor, weights, &biases, name); +} + +IConnectableLayer* Network::AddPermuteLayer(const PermuteDescriptor& permuteDescriptor, + const char* name) +{ + return m_Graph->AddLayer<PermuteLayer>(permuteDescriptor, name); +} + +IConnectableLayer* Network::AddPooling2dLayer(const Pooling2dDescriptor& pooling2dDescriptor, + const char* name) +{ + return m_Graph->AddLayer<Pooling2dLayer>(pooling2dDescriptor, name); +} + +IConnectableLayer* Network::AddActivationLayer(const ActivationDescriptor& activationDescriptor, + const char* name) +{ + return m_Graph->AddLayer<ActivationLayer>(activationDescriptor, name); +} + +IConnectableLayer* Network::AddNormalizationLayer(const NormalizationDescriptor& normalizationDescriptor, + const char* name) +{ + return m_Graph->AddLayer<NormalizationLayer>(normalizationDescriptor, name); +} + +IConnectableLayer* Network::AddSoftmaxLayer(const SoftmaxDescriptor& softmaxDescriptor, + const char* name) +{ + return m_Graph->AddLayer<SoftmaxLayer>(softmaxDescriptor, name); +} + +IConnectableLayer* Network::AddSplitterLayer(const ViewsDescriptor& splitterDescriptor, + const char* name) +{ + return m_Graph->AddLayer<SplitterLayer>(splitterDescriptor, name); +} + +IConnectableLayer* Network::AddMergerLayer(const OriginsDescriptor& mergerDescriptor, + const char* name) +{ + return m_Graph->AddLayer<MergerLayer>(mergerDescriptor, name); +} + +IConnectableLayer* Network::AddAdditionLayer(const char* name) +{ + return m_Graph->AddLayer<AdditionLayer>(name); +} + +IConnectableLayer* Network::AddMultiplicationLayer(const char* name) +{ + return m_Graph->AddLayer<MultiplicationLayer>(name); +} + +IConnectableLayer* Network::AddOutputLayer(LayerBindingId id, const char* name) +{ + return m_Graph->AddLayer<OutputLayer>(id, name); +} + +IConnectableLayer* Network::AddBatchNormalizationLayer(const BatchNormalizationDescriptor& desc, + const ConstTensor& mean, + const ConstTensor& variance, + const ConstTensor& beta, + const ConstTensor& gamma, + const char* name) +{ + const auto layer = m_Graph->AddLayer<BatchNormalizationLayer>(desc, name); + + layer->m_Mean = std::make_unique<ScopedCpuTensorHandle>(mean); + layer->m_Variance = std::make_unique<ScopedCpuTensorHandle>(variance); + layer->m_Beta = std::make_unique<ScopedCpuTensorHandle>(beta); + layer->m_Gamma = std::make_unique<ScopedCpuTensorHandle>(gamma); + + return layer; +} + +IConnectableLayer* Network::AddResizeBilinearLayer(const ResizeBilinearDescriptor& resizeDescriptor, const char* name) +{ + return m_Graph->AddLayer<ResizeBilinearLayer>(resizeDescriptor,name); +} + +IConnectableLayer* Network::AddL2NormalizationLayer(const char* name) +{ + return m_Graph->AddLayer<L2NormalizationLayer>(name); +} + +IConnectableLayer* Network::AddConstantLayer(const ConstTensor& input, const char* name) +{ + return m_Graph->AddLayer<ConstantLayer>(std::make_shared<ScopedCpuTensorHandle>(input), name); +} + +IConnectableLayer* Network::AddReshapeLayer(const ReshapeDescriptor& reshapeDescriptor, const char* name) +{ + return m_Graph->AddLayer<ReshapeLayer>(reshapeDescriptor, name); +} + +IConnectableLayer* Network::AddFloorLayer(const char* name) +{ + return m_Graph->AddLayer<FloorLayer>(name); +} + +OptimizedNetwork::OptimizedNetwork(std::unique_ptr<Graph> graph) + : m_Graph(std::move(graph)) +{ +} + +OptimizedNetwork::~OptimizedNetwork() +{ +} + +} // namespace armnn + |