2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // See LICENSE file in the project root for full license information.
6 #include "backends/CpuTensorHandle.hpp"
7 #include "backends/ArmComputeTensorUtils.hpp"
8 #include "backends/NeonLayerSupport.hpp"
10 #include "NeonConvolution2dBaseWorkload.hpp"
15 using namespace armcomputetensorutils;
17 arm_compute::Status NeonConvolution2dWorkloadValidate(const TensorInfo& input,
18 const TensorInfo& output,
19 const Convolution2dDescriptor& descriptor,
20 const TensorInfo& weights,
21 const TensorInfo& biases)
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;
29 if (descriptor.m_BiasEnabled)
31 aclBiasesInfo = BuildArmComputeTensorInfo(biases);
32 optionalAclBiasesInfo = &aclBiasesInfo;
35 arm_compute::PadStrideInfo layerInfo = BuildArmComputePadStrideInfo(descriptor);
37 return arm_compute::NEConvolutionLayer::validate(&aclInputInfo,
39 optionalAclBiasesInfo,
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)
49 using arm_compute::NEDirectConvolutionLayer;
50 using namespace armcomputetensorutils;
54 // todo: check tensor shapes match
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();
59 BuildArmComputeTensor(m_KernelTensor, m_Data.m_Weight->GetTensorInfo());
61 arm_compute::Tensor* optionalBiasTensor = nullptr;
62 if (m_Data.m_Parameters.m_BiasEnabled)
64 BuildArmComputeTensor(m_BiasTensor, m_Data.m_Bias->GetTensorInfo());
65 optionalBiasTensor = &m_BiasTensor;
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);
76 const bool preferDirectConvolution =
77 IsNeonDirectConvolutionPreferred(m_Data.m_Weight->GetTensorInfo(),
80 if (preferDirectConvolution)
82 auto directConvolutionLayer = std::make_unique<arm_compute::NEDirectConvolutionLayer>(memoryManager);
83 directConvolutionLayer->configure(&input,
88 m_ConvolutionLayer.reset(directConvolutionLayer.release());
92 auto convolutionLayer = std::make_unique<arm_compute::NEConvolutionLayer>(memoryManager);
93 convolutionLayer->configure(&input,
98 m_ConvolutionLayer.reset(convolutionLayer.release());
100 BOOST_ASSERT(m_ConvolutionLayer);
102 using Type = ResolveType<dataType>;
104 InitialiseArmComputeTensorData(m_KernelTensor, m_Data.m_Weight->template GetConstTensor<Type>());
107 // Generate known implementations for linker
108 template class NeonConvolution2dBaseWorkload<DataType::Float32>;
109 template class NeonConvolution2dBaseWorkload<DataType::QuantisedAsymm8>;