Release 18.05.01
[platform/upstream/armnn.git] / src / armnn / backends / NeonWorkloads / NeonConvolution2dBaseWorkload.cpp
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // See LICENSE file in the project root for full license information.
4 //
5
6 #include "backends/CpuTensorHandle.hpp"
7 #include "backends/ArmComputeTensorUtils.hpp"
8 #include "backends/NeonLayerSupport.hpp"
9
10 #include "NeonConvolution2dBaseWorkload.hpp"
11
12 namespace armnn
13 {
14
15 using namespace armcomputetensorutils;
16
17 arm_compute::Status NeonConvolution2dWorkloadValidate(const TensorInfo& input,
18     const TensorInfo& output,
19     const Convolution2dDescriptor& descriptor,
20     const TensorInfo& weights,
21     const TensorInfo& biases)
22 {
23     const arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input);
24     const arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output);
25     const arm_compute::TensorInfo aclWeightsInfo = BuildArmComputeTensorInfo(weights);
26     arm_compute::TensorInfo aclBiasesInfo;
27     arm_compute::TensorInfo *optionalAclBiasesInfo = nullptr;
28
29     if (descriptor.m_BiasEnabled)
30     {
31         aclBiasesInfo = BuildArmComputeTensorInfo(biases);
32         optionalAclBiasesInfo = &aclBiasesInfo;
33     }
34
35     arm_compute::PadStrideInfo layerInfo = BuildArmComputePadStrideInfo(descriptor);
36
37     return arm_compute::NEConvolutionLayer::validate(&aclInputInfo,
38                                                      &aclWeightsInfo,
39                                                      optionalAclBiasesInfo,
40                                                      &aclOutputInfo,
41                                                      layerInfo);
42 }
43
44 template<armnn::DataType dataType>
45 NeonConvolution2dBaseWorkload<dataType>::NeonConvolution2dBaseWorkload(const Convolution2dQueueDescriptor& descriptor,
46     const WorkloadInfo& info, std::shared_ptr<arm_compute::MemoryManagerOnDemand>& memoryManager)
47     : TypedWorkload<Convolution2dQueueDescriptor, dataType>(descriptor, info)
48 {
49     using arm_compute::NEDirectConvolutionLayer;
50     using namespace armcomputetensorutils;
51
52     ValidateData();
53
54     // todo: check tensor shapes match
55
56     arm_compute::ITensor& input = boost::polymorphic_downcast<INeonTensorHandle*>(m_Data.m_Inputs[0])->GetTensor();
57     arm_compute::ITensor& output = boost::polymorphic_downcast<INeonTensorHandle*>(m_Data.m_Outputs[0])->GetTensor();
58
59     BuildArmComputeTensor(m_KernelTensor, m_Data.m_Weight->GetTensorInfo());
60
61     arm_compute::Tensor* optionalBiasTensor = nullptr;
62     if (m_Data.m_Parameters.m_BiasEnabled)
63     {
64         BuildArmComputeTensor(m_BiasTensor, m_Data.m_Bias->GetTensorInfo());
65         optionalBiasTensor = &m_BiasTensor;
66     }
67
68     arm_compute::PadStrideInfo padStrideInfo(m_Data.m_Parameters.m_StrideX,
69                                              m_Data.m_Parameters.m_StrideY,
70                                              m_Data.m_Parameters.m_PadLeft,
71                                              m_Data.m_Parameters.m_PadRight,
72                                              m_Data.m_Parameters.m_PadTop,
73                                              m_Data.m_Parameters.m_PadBottom,
74                                              arm_compute::DimensionRoundingType::FLOOR);
75
76     const bool preferDirectConvolution =
77         IsNeonDirectConvolutionPreferred(m_Data.m_Weight->GetTensorInfo(),
78                                          m_Data.m_Parameters);
79
80     if (preferDirectConvolution)
81     {
82         auto directConvolutionLayer = std::make_unique<arm_compute::NEDirectConvolutionLayer>(memoryManager);
83         directConvolutionLayer->configure(&input,
84                                           &m_KernelTensor,
85                                           optionalBiasTensor,
86                                           &output,
87                                           padStrideInfo);
88         m_ConvolutionLayer.reset(directConvolutionLayer.release());
89     }
90     else
91     {
92         auto convolutionLayer = std::make_unique<arm_compute::NEConvolutionLayer>(memoryManager);
93         convolutionLayer->configure(&input,
94                                     &m_KernelTensor,
95                                     optionalBiasTensor,
96                                     &output,
97                                     padStrideInfo);
98         m_ConvolutionLayer.reset(convolutionLayer.release());
99     }
100     BOOST_ASSERT(m_ConvolutionLayer);
101
102     using Type = ResolveType<dataType>;
103
104     InitialiseArmComputeTensorData(m_KernelTensor, m_Data.m_Weight->template GetConstTensor<Type>());
105 }
106
107 // Generate known implementations for linker
108 template class NeonConvolution2dBaseWorkload<DataType::Float32>;
109 template class NeonConvolution2dBaseWorkload<DataType::QuantisedAsymm8>;
110
111 } //namespace armnn
112