blob: ee69088691a568b21216a5fb5831675fe8a908bb [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
David Beck711fa312018-09-24 10:46:38 +01006#include <backends/CpuTensorHandle.hpp>
7#include <backends/aclCommon/ArmComputeTensorUtils.hpp>
8#include <backends/NeonLayerSupport.hpp>
telsoa014fcda012018-03-09 14:13:49 +00009
10#include "NeonConvolution2dBaseWorkload.hpp"
11
David Beck711fa312018-09-24 10:46:38 +010012#include <armnn/Types.hpp>
13#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,
arovir01a6824102018-08-28 17:40:45 +010024 const boost::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 {
arovir01a6824102018-08-28 17:40:45 +010035 BOOST_ASSERT(biases.is_initialized());
36
Francis Murtagh351d13d2018-09-24 15:01:18 +010037 aclBiasesInfo = BuildArmComputeTensorInfo(biases.get(), 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
telsoa01c577f2c2018-08-31 09:22:23 +010050template<armnn::DataType... dataTypes>
51NeonConvolution2dBaseWorkload<dataTypes...>::NeonConvolution2dBaseWorkload(
52 const Convolution2dQueueDescriptor& descriptor, const WorkloadInfo& info,
53 std::shared_ptr<arm_compute::MemoryManagerOnDemand>& memoryManager)
54 : TypedWorkload<Convolution2dQueueDescriptor, dataTypes...>(descriptor, info)
telsoa014fcda012018-03-09 14:13:49 +000055{
56 using arm_compute::NEDirectConvolutionLayer;
telsoa014fcda012018-03-09 14:13:49 +000057
58 ValidateData();
59
telsoa01c577f2c2018-08-31 09:22:23 +010060 // todo: check tensor shapes match.
telsoa014fcda012018-03-09 14:13:49 +000061
62 arm_compute::ITensor& input = boost::polymorphic_downcast<INeonTensorHandle*>(m_Data.m_Inputs[0])->GetTensor();
63 arm_compute::ITensor& output = boost::polymorphic_downcast<INeonTensorHandle*>(m_Data.m_Outputs[0])->GetTensor();
64
telsoa01c577f2c2018-08-31 09:22:23 +010065 m_KernelTensor = std::make_unique<arm_compute::Tensor>();
Francis Murtagh351d13d2018-09-24 15:01:18 +010066 BuildArmComputeTensor(*m_KernelTensor, m_Data.m_Weight->GetTensorInfo(), descriptor.m_DataLayout);
telsoa014fcda012018-03-09 14:13:49 +000067
telsoa014fcda012018-03-09 14:13:49 +000068 if (m_Data.m_Parameters.m_BiasEnabled)
69 {
telsoa01c577f2c2018-08-31 09:22:23 +010070 m_BiasTensor = std::make_unique<arm_compute::Tensor>();
Francis Murtagh351d13d2018-09-24 15:01:18 +010071 BuildArmComputeTensor(*m_BiasTensor, m_Data.m_Bias->GetTensorInfo(), descriptor.m_DataLayout);
telsoa014fcda012018-03-09 14:13:49 +000072 }
73
74 arm_compute::PadStrideInfo padStrideInfo(m_Data.m_Parameters.m_StrideX,
75 m_Data.m_Parameters.m_StrideY,
76 m_Data.m_Parameters.m_PadLeft,
77 m_Data.m_Parameters.m_PadRight,
78 m_Data.m_Parameters.m_PadTop,
79 m_Data.m_Parameters.m_PadBottom,
80 arm_compute::DimensionRoundingType::FLOOR);
81
82 const bool preferDirectConvolution =
83 IsNeonDirectConvolutionPreferred(m_Data.m_Weight->GetTensorInfo(),
84 m_Data.m_Parameters);
85
86 if (preferDirectConvolution)
87 {
surmeh013537c2c2018-05-18 16:31:43 +010088 auto directConvolutionLayer = std::make_unique<arm_compute::NEDirectConvolutionLayer>(memoryManager);
telsoa014fcda012018-03-09 14:13:49 +000089 directConvolutionLayer->configure(&input,
telsoa01c577f2c2018-08-31 09:22:23 +010090 m_KernelTensor.get(),
91 m_BiasTensor.get(),
telsoa014fcda012018-03-09 14:13:49 +000092 &output,
93 padStrideInfo);
94 m_ConvolutionLayer.reset(directConvolutionLayer.release());
95 }
96 else
97 {
surmeh013537c2c2018-05-18 16:31:43 +010098 auto convolutionLayer = std::make_unique<arm_compute::NEConvolutionLayer>(memoryManager);
telsoa014fcda012018-03-09 14:13:49 +000099 convolutionLayer->configure(&input,
telsoa01c577f2c2018-08-31 09:22:23 +0100100 m_KernelTensor.get(),
101 m_BiasTensor.get(),
telsoa014fcda012018-03-09 14:13:49 +0000102 &output,
103 padStrideInfo);
104 m_ConvolutionLayer.reset(convolutionLayer.release());
105 }
106 BOOST_ASSERT(m_ConvolutionLayer);
107
telsoa01c577f2c2018-08-31 09:22:23 +0100108 armnn::DataType dataType = m_Data.m_Weight->GetTensorInfo().GetDataType();
telsoa014fcda012018-03-09 14:13:49 +0000109
telsoa01c577f2c2018-08-31 09:22:23 +0100110 switch (dataType)
111 {
112 case DataType::Float16:
113 {
114 InitialiseArmComputeTensorData(*m_KernelTensor, m_Data.m_Weight->template GetConstTensor<Half>());
115 break;
116 }
117 case DataType::Float32:
118 {
119 InitialiseArmComputeTensorData(*m_KernelTensor, m_Data.m_Weight->template GetConstTensor<float>());
120 break;
121 }
122 case DataType::QuantisedAsymm8:
123 {
124 InitialiseArmComputeTensorData(*m_KernelTensor, m_Data.m_Weight->template GetConstTensor<uint8_t>());
125 break;
126 }
127 default:
128 {
129 BOOST_ASSERT_MSG(false, "Unknown DataType.");
130 }
131 }
telsoa014fcda012018-03-09 14:13:49 +0000132}
133
telsoa01c577f2c2018-08-31 09:22:23 +0100134template<armnn::DataType... dataTypes>
135void NeonConvolution2dBaseWorkload<dataTypes...>::FreeUnusedTensors()
136{
137 FreeTensorIfUnused(m_KernelTensor);
138 FreeTensorIfUnused(m_BiasTensor);
139}
140
141// Generates known implementations for linker.
142template class NeonConvolution2dBaseWorkload<armnn::DataType::Float16, armnn::DataType::Float32>;
143template class NeonConvolution2dBaseWorkload<armnn::DataType::QuantisedAsymm8>;
telsoa014fcda012018-03-09 14:13:49 +0000144
145} //namespace armnn
146