ArmNN
 20.11
NeonFullyConnectedWorkload.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
7 
8 #include "NeonWorkloadUtils.hpp"
9 
12 
14 
16 
17 #include <arm_compute/runtime/NEON/functions/NEFullyConnectedLayer.h>
18 
19 namespace armnn
20 {
21 using namespace armcomputetensorutils;
22 
24  const TensorInfo& output,
25  const TensorInfo& weights,
26  const TensorInfo& biases,
27  const FullyConnectedDescriptor& descriptor,
28  const ActivationDescriptor* activationDescriptor)
29 {
30  if (activationDescriptor)
31  {
32  std::vector<ActivationFunction> activations = {ActivationFunction::ReLu, ActivationFunction::BoundedReLu};
33  if (std::find(activations.begin(), activations.end(), activationDescriptor->m_Function) == activations.end())
34  {
35  return arm_compute::Status{
36  arm_compute::ErrorCode::RUNTIME_ERROR, "NeonFullyConnectedWorkload :Unsupported Activation Function"};
37  }
38  }
39 
40  const arm_compute::TensorInfo aclInput = BuildArmComputeTensorInfo(input);
41  const arm_compute::TensorInfo aclOutput = BuildArmComputeTensorInfo(output);
42  const arm_compute::TensorInfo aclWeights = BuildArmComputeTensorInfo(weights);
43 
44  arm_compute::TensorInfo aclBiases;
45  arm_compute::TensorInfo *optionalAclBiases = nullptr;
46  if (descriptor.m_BiasEnabled)
47  {
48  aclBiases = BuildArmComputeTensorInfo(biases);
49  optionalAclBiases = &aclBiases;
50  }
51 
52  const arm_compute::FullyConnectedLayerInfo fullyConnectedLayerInfo =
53  ConvertFullyConnectedDescriptorToAclFullyConnectedLayerInfo(descriptor, activationDescriptor);
54 
55  return arm_compute::NEFullyConnectedLayer::validate(&aclInput,
56  &aclWeights,
57  optionalAclBiases,
58  &aclOutput,
59  fullyConnectedLayerInfo);
60 }
61 
63  const WorkloadInfo& info, std::shared_ptr<arm_compute::MemoryManagerOnDemand>& memoryManager)
64  : BaseWorkload<FullyConnectedQueueDescriptor>(descriptor, info)
65 {
66  m_Data.ValidateInputsOutputs("NeonFullyConnectedWorkload", 1, 1);
67 
68  arm_compute::ITensor& input = PolymorphicDowncast<IAclTensorHandle*>(m_Data.m_Inputs[0])->GetTensor();
69  arm_compute::ITensor& output = PolymorphicDowncast<IAclTensorHandle*>(m_Data.m_Outputs[0])->GetTensor();
70 
71  m_WeightsTensor = std::make_unique<arm_compute::Tensor>();
72  BuildArmComputeTensor(*m_WeightsTensor, m_Data.m_Weight->GetTensorInfo());
73 
75  {
76  m_BiasesTensor = std::make_unique<arm_compute::Tensor>();
77  BuildArmComputeTensor(*m_BiasesTensor, m_Data.m_Bias->GetTensorInfo());
78  }
79 
80  const arm_compute::ActivationLayerInfo activationInfo = ConvertAdditionalInfoToAclActivationLayerInfo(descriptor);
81 
82  arm_compute::FullyConnectedLayerInfo fc_info =
84 
85  auto layer = std::make_unique<arm_compute::NEFullyConnectedLayer>(memoryManager);
86  layer->configure(&input, m_WeightsTensor.get(), m_BiasesTensor.get(), &output, fc_info);
87  m_FullyConnectedLayer.reset(layer.release());
88 
89  // Allocate
91  {
93  }
94  else
95  {
97  }
98 
99  if (m_BiasesTensor)
100  {
102  {
103  InitializeArmComputeTensorData(*m_BiasesTensor, m_Data.m_Bias);
104  }
105  else
106  {
107  InitializeArmComputeTensorData(*m_BiasesTensor, m_Data.m_Bias);
108  }
109  }
110 
111  // Force Compute Library to perform the necessary copying and reshaping, after which
112  // delete all the input tensors that will no longer be needed
113  m_FullyConnectedLayer->prepare();
114  FreeUnusedTensors();
115 }
116 
118 {
119  ARMNN_SCOPED_PROFILING_EVENT_NEON("NeonFullyConnectedWorkload_Execute");
120  m_FullyConnectedLayer->run();
121 }
122 
123 void NeonFullyConnectedWorkload::FreeUnusedTensors()
124 {
125  FreeTensorIfUnused(m_WeightsTensor);
126  FreeTensorIfUnused(m_BiasesTensor);
127 }
128 
129 } //namespace armnn
const ConstCpuTensorHandle * m_Weight
const FullyConnectedQueueDescriptor m_Data
Definition: Workload.hpp:46
#define ARMNN_SCOPED_PROFILING_EVENT_NEON(name)
arm_compute::ActivationLayerInfo ConvertAdditionalInfoToAclActivationLayerInfo(const QueueDescriptor &queueDescriptor)
NeonFullyConnectedWorkload(const FullyConnectedQueueDescriptor &descriptor, const WorkloadInfo &info, std::shared_ptr< arm_compute::MemoryManagerOnDemand > &memoryManager)
arm_compute::Status NeonFullyConnectedWorkloadValidate(const TensorInfo &input, const TensorInfo &output, const TensorInfo &weights, const TensorInfo &biases, const FullyConnectedDescriptor &descriptor, const ActivationDescriptor *activationDescriptor)
void ValidateInputsOutputs(const std::string &descName, unsigned int numExpectedIn, unsigned int numExpectedOut) const
Copyright (c) 2020 ARM Limited.
DataType GetDataType() const
Definition: Tensor.hpp:194
A FullyConnectedDescriptor for the FullyConnectedLayer.
bool m_BiasEnabled
Enable/disable bias.
arm_compute::FullyConnectedLayerInfo ConvertFullyConnectedDescriptorToAclFullyConnectedLayerInfo(const FullyConnectedDescriptor &fullyConnectedDesc, const ActivationDescriptor *activationDesc)
Status
enumeration
Definition: Types.hpp:26
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:20
min(a, max(b, input)) ReLu1 & ReLu6.
void InitializeArmComputeTensorData(arm_compute::Tensor &tensor, const ConstCpuTensorHandle *handle)
std::vector< ITensorHandle * > m_Outputs
Contains information about inputs and outputs to a layer.
std::vector< ITensorHandle * > m_Inputs
const ConstCpuTensorHandle * m_Bias
ActivationFunction m_Function
The activation function to use (Sigmoid, TanH, Linear, ReLu, BoundedReLu, SoftReLu, LeakyReLu, Abs, Sqrt, Square, Elu).
Definition: Descriptors.hpp:43
const TensorInfo & GetTensorInfo() const