blob: 9cadbf09ac5a6d58629f6441f11f2efb6cd4c2c7 [file] [log] [blame]
telsoa01c577f2c2018-08-31 09:22:23 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa01c577f2c2018-08-31 09:22:23 +01004//
5
Matthew Benthamd8777392018-10-08 09:38:55 +01006#include "ClDepthwiseConvolutionWorkload.hpp"
telsoa01c577f2c2018-08-31 09:22:23 +01007
8#include "TypeUtils.hpp"
Matthew Benthamd8777392018-10-08 09:38:55 +01009#include "ClWorkloadUtils.hpp"
telsoa01c577f2c2018-08-31 09:22:23 +010010
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000011#include <aclCommon/ArmComputeUtils.hpp>
12#include <aclCommon/ArmComputeTensorUtils.hpp>
13#include <cl/ClTensorHandle.hpp>
14#include <backendsCommon/CpuTensorHandle.hpp>
telsoa01c577f2c2018-08-31 09:22:23 +010015
Matthew Benthamd8777392018-10-08 09:38:55 +010016#include <arm_compute/runtime/CL/functions/CLDepthwiseConvolutionLayer.h>
17
telsoa01c577f2c2018-08-31 09:22:23 +010018namespace armnn
19{
20
21using namespace armcomputetensorutils;
22
23arm_compute::Status ClDepthwiseConvolutionWorkloadValidate(const TensorInfo& input,
24 const TensorInfo& output,
25 const DepthwiseConvolution2dDescriptor& descriptor,
26 const TensorInfo& weights,
David Beck5eec11d2018-10-04 15:43:17 +010027 const Optional<TensorInfo>& biases)
telsoa01c577f2c2018-08-31 09:22:23 +010028{
Nikhil Raja05c2102018-09-25 16:16:13 +010029 const arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout);
30 const arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output, descriptor.m_DataLayout);
31 const arm_compute::TensorInfo aclWeightsInfo = BuildArmComputeTensorInfo(weights, descriptor.m_DataLayout);
telsoa01c577f2c2018-08-31 09:22:23 +010032
33 arm_compute::TensorInfo aclBiasesInfo;
34 arm_compute::TensorInfo *optionalAclBiasesInfo = nullptr;
arovir01a6824102018-08-28 17:40:45 +010035
telsoa01c577f2c2018-08-31 09:22:23 +010036 if (descriptor.m_BiasEnabled)
37 {
David Beck5eec11d2018-10-04 15:43:17 +010038 BOOST_ASSERT(biases.has_value());
arovir01a6824102018-08-28 17:40:45 +010039
David Beck5eec11d2018-10-04 15:43:17 +010040 aclBiasesInfo = BuildArmComputeTensorInfo(biases.value(), descriptor.m_DataLayout);
telsoa01c577f2c2018-08-31 09:22:23 +010041 optionalAclBiasesInfo = &aclBiasesInfo;
42 }
43
44 const arm_compute::PadStrideInfo aclPadStrideInfo = BuildArmComputePadStrideInfo(descriptor);
45 const unsigned int aclDepthMultiplier = weights.GetShape()[0];
46
47 return arm_compute::CLDepthwiseConvolutionLayer::validate(&aclInputInfo,
48 &aclWeightsInfo,
49 optionalAclBiasesInfo,
50 &aclOutputInfo,
51 aclPadStrideInfo,
52 aclDepthMultiplier);
53}
54
Matthew Benthamd8777392018-10-08 09:38:55 +010055ClDepthwiseConvolutionWorkload::ClDepthwiseConvolutionWorkload(
telsoa01c577f2c2018-08-31 09:22:23 +010056 const DepthwiseConvolution2dQueueDescriptor& descriptor,
57 const WorkloadInfo& info)
Matthew Benthamd8777392018-10-08 09:38:55 +010058 : BaseWorkload<DepthwiseConvolution2dQueueDescriptor>(descriptor, info)
telsoa01c577f2c2018-08-31 09:22:23 +010059{
60 auto& weightInfo = m_Data.m_Weight->GetTensorInfo();
61
62 m_KernelTensor = std::make_unique<arm_compute::CLTensor>();
Nikhil Rajcec6b652018-10-12 13:51:57 +010063 BuildArmComputeTensor(*m_KernelTensor, weightInfo, m_Data.m_Parameters.m_DataLayout);
telsoa01c577f2c2018-08-31 09:22:23 +010064
65 if (m_Data.m_Parameters.m_BiasEnabled)
66 {
67 m_BiasTensor = std::make_unique<arm_compute::CLTensor>();
Nikhil Rajcec6b652018-10-12 13:51:57 +010068 BuildArmComputeTensor(*m_BiasTensor, m_Data.m_Bias->GetTensorInfo(), m_Data.m_Parameters.m_DataLayout);
telsoa01c577f2c2018-08-31 09:22:23 +010069 }
70
71 arm_compute::PadStrideInfo padStrideInfo(m_Data.m_Parameters.m_StrideX,
72 m_Data.m_Parameters.m_StrideY,
73 m_Data.m_Parameters.m_PadLeft,
74 m_Data.m_Parameters.m_PadRight,
75 m_Data.m_Parameters.m_PadTop,
76 m_Data.m_Parameters.m_PadBottom,
77 arm_compute::DimensionRoundingType::FLOOR);
78
Matthew Benthamd8777392018-10-08 09:38:55 +010079 std::string name = std::string("ClDepthwiseConvolutionWorkload");
telsoa01c577f2c2018-08-31 09:22:23 +010080 m_Data.ValidateInputsOutputs(name, 1, 1);
81
82 arm_compute::ICLTensor& input = static_cast<IClTensorHandle*>(m_Data.m_Inputs[0])->GetTensor();
83 arm_compute::ICLTensor& output = static_cast<IClTensorHandle*>(m_Data.m_Outputs[0])->GetTensor();
84
Nikhil Rajcec6b652018-10-12 13:51:57 +010085 arm_compute::DataLayout aclDataLayout = ConvertDataLayout(m_Data.m_Parameters.m_DataLayout);
86 input.info()->set_data_layout(aclDataLayout);
87 output.info()->set_data_layout(aclDataLayout);
88
telsoa01c577f2c2018-08-31 09:22:23 +010089 const unsigned int depthMultiplier = weightInfo.GetShape()[0];
90
saoste019c6f3af2018-11-05 12:30:23 +000091 const unsigned int widthIndex = (m_Data.m_Parameters.m_DataLayout == DataLayout::NCHW) ? 3 : 2;
92 const unsigned int heightIndex = (m_Data.m_Parameters.m_DataLayout == DataLayout::NCHW) ? 2 : 1;
93
telsoa01c577f2c2018-08-31 09:22:23 +010094 //Check for optimisation opportunities.
saoste019c6f3af2018-11-05 12:30:23 +000095 bool use3x3Optimisation = (weightInfo.GetShape()[widthIndex] == 3) && (weightInfo.GetShape()[heightIndex] == 3);
telsoa01c577f2c2018-08-31 09:22:23 +010096 if (use3x3Optimisation)
97 {
98 m_DepthwiseConvolutionLayer = std::make_unique<arm_compute::CLDepthwiseConvolutionLayer3x3>();
99 static_cast<arm_compute::CLDepthwiseConvolutionLayer3x3*>(m_DepthwiseConvolutionLayer.get())->configure(
100 &input,
101 m_KernelTensor.get(),
102 m_BiasTensor.get(),
103 &output,
104 padStrideInfo,
105 depthMultiplier);
106 }
107 else
108 {
109 m_DepthwiseConvolutionLayer = std::make_unique<arm_compute::CLDepthwiseConvolutionLayer>();
110 static_cast<arm_compute::CLDepthwiseConvolutionLayer*>(m_DepthwiseConvolutionLayer.get())->configure(
111 &input,
112 m_KernelTensor.get(),
113 m_BiasTensor.get(),
114 &output,
115 padStrideInfo,
116 depthMultiplier);
117 }
118
119 BOOST_ASSERT(m_DepthwiseConvolutionLayer);
Matthew Benthamd8777392018-10-08 09:38:55 +0100120
121 InitializeArmComputeClTensorData(*m_KernelTensor, m_Data.m_Weight);
122
123 if (m_BiasTensor)
124 {
125 InitializeArmComputeClTensorData(*m_BiasTensor, m_Data.m_Bias);
126 }
127
128 m_DepthwiseConvolutionLayer->prepare();
129 FreeUnusedTensors();
telsoa01c577f2c2018-08-31 09:22:23 +0100130}
131
Matthew Benthamd8777392018-10-08 09:38:55 +0100132void ClDepthwiseConvolutionWorkload::FreeUnusedTensors()
telsoa01c577f2c2018-08-31 09:22:23 +0100133{
134 FreeTensorIfUnused(m_KernelTensor);
135 FreeTensorIfUnused(m_BiasTensor);
136}
137
Matthew Benthamd8777392018-10-08 09:38:55 +0100138void ClDepthwiseConvolutionWorkload::Execute() const
139{
140 ARMNN_SCOPED_PROFILING_EVENT_CL("ClDepthwiseConvolutionWorkload_Execute");
141 BOOST_ASSERT(m_DepthwiseConvolutionLayer);
142
Aron Virginas-Tara8e06ed2018-10-19 16:46:15 +0100143 RunClFunction(*m_DepthwiseConvolutionLayer, CHECK_LOCATION());
Matthew Benthamd8777392018-10-08 09:38:55 +0100144}
telsoa01c577f2c2018-08-31 09:22:23 +0100145
146} // namespace armnn