blob: 151132f04df17530ac75468a8fb9fd9c0607fa3a [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +01006#include "NeonConvolution2dWorkload.hpp"
7
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +00008#include <backendsCommon/CpuTensorHandle.hpp>
9#include <aclCommon/ArmComputeTensorUtils.hpp>
10#include <neon/NeonLayerSupport.hpp>
telsoa014fcda012018-03-09 14:13:49 +000011
David Beck711fa312018-09-24 10:46:38 +010012#include <armnn/Types.hpp>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000013#include <Half.hpp>
telsoa01c577f2c2018-08-31 09:22:23 +010014
telsoa014fcda012018-03-09 14:13:49 +000015namespace armnn
16{
17
surmeh013537c2c2018-05-18 16:31:43 +010018using namespace armcomputetensorutils;
19
20arm_compute::Status NeonConvolution2dWorkloadValidate(const TensorInfo& input,
21 const TensorInfo& output,
22 const Convolution2dDescriptor& descriptor,
23 const TensorInfo& weights,
David Beck5eec11d2018-10-04 15:43:17 +010024 const Optional<TensorInfo>& biases)
surmeh013537c2c2018-05-18 16:31:43 +010025{
Francis Murtagh351d13d2018-09-24 15:01:18 +010026 const arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout);
27 const arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output, descriptor.m_DataLayout);
28 const arm_compute::TensorInfo aclWeightsInfo = BuildArmComputeTensorInfo(weights, descriptor.m_DataLayout);
arovir01a6824102018-08-28 17:40:45 +010029
surmeh013537c2c2018-05-18 16:31:43 +010030 arm_compute::TensorInfo aclBiasesInfo;
31 arm_compute::TensorInfo *optionalAclBiasesInfo = nullptr;
32
33 if (descriptor.m_BiasEnabled)
34 {
David Beck5eec11d2018-10-04 15:43:17 +010035 BOOST_ASSERT(biases.has_value());
arovir01a6824102018-08-28 17:40:45 +010036
David Beck5eec11d2018-10-04 15:43:17 +010037 aclBiasesInfo = BuildArmComputeTensorInfo(biases.value(), descriptor.m_DataLayout);
surmeh013537c2c2018-05-18 16:31:43 +010038 optionalAclBiasesInfo = &aclBiasesInfo;
39 }
40
41 arm_compute::PadStrideInfo layerInfo = BuildArmComputePadStrideInfo(descriptor);
42
43 return arm_compute::NEConvolutionLayer::validate(&aclInputInfo,
44 &aclWeightsInfo,
45 optionalAclBiasesInfo,
46 &aclOutputInfo,
47 layerInfo);
48}
49
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +010050NeonConvolution2dWorkload::NeonConvolution2dWorkload(
telsoa01c577f2c2018-08-31 09:22:23 +010051 const Convolution2dQueueDescriptor& descriptor, const WorkloadInfo& info,
52 std::shared_ptr<arm_compute::MemoryManagerOnDemand>& memoryManager)
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +010053 : BaseWorkload<Convolution2dQueueDescriptor>(descriptor, info)
telsoa014fcda012018-03-09 14:13:49 +000054{
55 using arm_compute::NEDirectConvolutionLayer;
telsoa014fcda012018-03-09 14:13:49 +000056
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +010057 m_Data.ValidateInputsOutputs("NeonConvolution2dWorkload", 1, 1);
telsoa014fcda012018-03-09 14:13:49 +000058
telsoa01c577f2c2018-08-31 09:22:23 +010059 // todo: check tensor shapes match.
telsoa014fcda012018-03-09 14:13:49 +000060
61 arm_compute::ITensor& input = boost::polymorphic_downcast<INeonTensorHandle*>(m_Data.m_Inputs[0])->GetTensor();
62 arm_compute::ITensor& output = boost::polymorphic_downcast<INeonTensorHandle*>(m_Data.m_Outputs[0])->GetTensor();
63
Francis Murtaghd59116e2018-10-04 16:03:07 +010064 arm_compute::DataLayout aclDataLayout = ConvertDataLayout(m_Data.m_Parameters.m_DataLayout);
65 input.info()->set_data_layout(aclDataLayout);
66 output.info()->set_data_layout(aclDataLayout);
67
telsoa01c577f2c2018-08-31 09:22:23 +010068 m_KernelTensor = std::make_unique<arm_compute::Tensor>();
Francis Murtaghd59116e2018-10-04 16:03:07 +010069 BuildArmComputeTensor(*m_KernelTensor, m_Data.m_Weight->GetTensorInfo(), m_Data.m_Parameters.m_DataLayout);
telsoa014fcda012018-03-09 14:13:49 +000070
telsoa014fcda012018-03-09 14:13:49 +000071 if (m_Data.m_Parameters.m_BiasEnabled)
72 {
telsoa01c577f2c2018-08-31 09:22:23 +010073 m_BiasTensor = std::make_unique<arm_compute::Tensor>();
Francis Murtaghd59116e2018-10-04 16:03:07 +010074 BuildArmComputeTensor(*m_BiasTensor, m_Data.m_Bias->GetTensorInfo(), m_Data.m_Parameters.m_DataLayout);
telsoa014fcda012018-03-09 14:13:49 +000075 }
76
77 arm_compute::PadStrideInfo padStrideInfo(m_Data.m_Parameters.m_StrideX,
78 m_Data.m_Parameters.m_StrideY,
79 m_Data.m_Parameters.m_PadLeft,
80 m_Data.m_Parameters.m_PadRight,
81 m_Data.m_Parameters.m_PadTop,
82 m_Data.m_Parameters.m_PadBottom,
83 arm_compute::DimensionRoundingType::FLOOR);
84
narpra01fca75c32018-11-16 12:38:41 +000085 auto convolutionLayer = std::make_unique<arm_compute::NEConvolutionLayer>(memoryManager);
86 convolutionLayer->configure(&input,
87 m_KernelTensor.get(),
88 m_BiasTensor.get(),
89 &output,
90 padStrideInfo);
91 m_ConvolutionLayer.reset(convolutionLayer.release());
telsoa014fcda012018-03-09 14:13:49 +000092
telsoa014fcda012018-03-09 14:13:49 +000093 BOOST_ASSERT(m_ConvolutionLayer);
94
Nattapat Chaimanowong177d8d22018-10-16 13:21:27 +010095 InitializeArmComputeTensorData(*m_KernelTensor, m_Data.m_Weight);
telsoa014fcda012018-03-09 14:13:49 +000096
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +010097 if (m_Data.m_Parameters.m_BiasEnabled)
98 {
99 InitializeArmComputeTensorData(*m_BiasTensor, m_Data.m_Bias);
100 }
101
102 m_ConvolutionLayer->prepare();
103 FreeUnusedTensors();
telsoa014fcda012018-03-09 14:13:49 +0000104}
105
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +0100106void NeonConvolution2dWorkload::Execute() const
107{
108 ARMNN_SCOPED_PROFILING_EVENT_NEON("NeonConvolution2dWorkload_Execute");
109 m_ConvolutionLayer->run();
110}
111
112void NeonConvolution2dWorkload::FreeUnusedTensors()
telsoa01c577f2c2018-08-31 09:22:23 +0100113{
114 FreeTensorIfUnused(m_KernelTensor);
115 FreeTensorIfUnused(m_BiasTensor);
116}
117
telsoa014fcda012018-03-09 14:13:49 +0000118} //namespace armnn