blob: 4dabef3bd7f6357a643abe4efab464bf20df8875 [file] [log] [blame]
Michalis Spyrou7362f0d2017-10-18 17:58:22 +01001/*
Ramy Elgammala8db6122023-05-08 03:33:43 +01002 * Copyright (c) 2017-2021, 2023 Arm Limited.
Michalis Spyrou7362f0d2017-10-18 17:58:22 +01003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
Giorgio Arena04a8f8c2017-11-23 11:45:24 +000024#include "arm_compute/runtime/NEON/functions/NEDepthwiseConvolutionLayer.h"
Michalis Spyrou7362f0d2017-10-18 17:58:22 +010025
Giorgio Arenad93e2632019-10-15 11:09:33 +010026#include "arm_compute/core/utils/misc/InfoHelpers.h"
Georgios Pinitasd05dce42018-01-22 16:29:17 +000027#include "arm_compute/core/utils/misc/ShapeCalculator.h"
Georgios Pinitasf72f9362018-01-12 16:29:45 +000028#include "arm_compute/core/utils/quantization/AsymmHelpers.h"
Michalis Spyrou7362f0d2017-10-18 17:58:22 +010029#include "arm_compute/runtime/NEON/NEScheduler.h"
ramelg01cbbb0382021-09-17 17:36:57 +010030#include "src/common/utils/Log.h"
Georgios Pinitas7891a732021-08-20 21:39:25 +010031#include "src/cpu/operators/CpuDepthwiseConv2d.h"
Georgios Pinitas47d39dc2019-03-11 14:03:23 +000032
Georgios Pinitasd05dce42018-01-22 16:29:17 +000033using namespace arm_compute::misc;
Georgios Pinitas4074c992018-01-30 18:13:46 +000034using namespace arm_compute::misc::shape_calculator;
Michalis Spyrou7362f0d2017-10-18 17:58:22 +010035
Georgios Pinitas47d39dc2019-03-11 14:03:23 +000036namespace arm_compute
37{
Michalis Spyrouebcebf12020-10-21 00:04:14 +010038NEDepthwiseConvolutionLayer::~NEDepthwiseConvolutionLayer() = default;
39
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010040struct NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::Impl
41{
42 ITensor *src{ nullptr }; // SRC_0
43 ITensor *dst{ nullptr }; // DST_0
44 const ITensor *weights
45 {
46 nullptr
47 }; // SRC_1
48 const ITensor *biases
49 {
50 nullptr
Manuel Bottinib4bb6a02021-05-24 16:01:32 +010051 }; // SRC_2
52 Tensor permuted_input{}; // INT_0
53 Tensor permuted_weights{}; // INT_1
54 Tensor permuted_output{}; // INT_2
55 Tensor workspace{}; // INT_3
56 Tensor packed_weights{}; // INT_4
57 std::shared_ptr<cpu::CpuDepthwiseConv2d> op{ nullptr };
58 bool is_prepared{ false };
59 bool permute{ false };
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010060};
61
Manuel Bottini05069f02019-09-26 17:18:26 +010062NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::NEDepthwiseConvolutionLayerOptimizedInternal(std::shared_ptr<IMemoryManager> memory_manager)
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010063 : _memory_group(memory_manager), _impl(std::make_unique<Impl>())
Manuel Bottini05069f02019-09-26 17:18:26 +010064{
65}
66
Georgios Pinitas7d0adc62020-09-04 15:25:24 +010067void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::configure(ITensor *input,
68 const ITensor *weights,
69 const ITensor *biases,
70 ITensor *output, const PadStrideInfo &conv_info,
71 unsigned int depth_multiplier,
72 const ActivationLayerInfo &act_info,
73 const Size2D &dilation)
Manuel Bottini05069f02019-09-26 17:18:26 +010074{
Georgios Pinitas7d0adc62020-09-04 15:25:24 +010075 ARM_COMPUTE_ERROR_ON_NULLPTR(input, weights, output);
Manuel Bottini05069f02019-09-26 17:18:26 +010076
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010077 bool is_nhwc = input->info()->data_layout() == DataLayout::NCHW;
78 _impl->src = input;
79 _impl->weights = weights;
80 _impl->biases = biases;
81 _impl->dst = output;
82 _impl->permute = is_nhwc;
83
Manuel Bottinib4bb6a02021-05-24 16:01:32 +010084 _impl->op = std::make_unique<cpu::CpuDepthwiseConv2d>();
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010085 ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
86 _impl->op->configure(_impl->src->info(), _impl->weights->info(), _impl->biases == nullptr ? nullptr : _impl->biases->info(),
87 _impl->dst->info(), info);
Manuel Bottini05069f02019-09-26 17:18:26 +010088
Georgios Pinitas7d0adc62020-09-04 15:25:24 +010089 // Configure pipeline
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010090 ActivationLayerInfo act_info_to_use = ActivationLayerInfo();
91 const bool is_relu = arm_compute::utils::info_helpers::is_relu(act_info);
92 const bool is_relu6 = arm_compute::utils::info_helpers::is_relu6(act_info);
93 bool is_activationlayer_enabled = act_info.enabled() && !(is_relu || is_relu6);
94
95 if(!is_activationlayer_enabled)
Manuel Bottini05069f02019-09-26 17:18:26 +010096 {
97 act_info_to_use = act_info;
98 }
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010099 info = ConvolutionInfo{ conv_info, depth_multiplier, act_info_to_use, dilation };
Manuel Bottini05069f02019-09-26 17:18:26 +0100100
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100101 auto dwc_optimized_func = std::make_unique<cpu::CpuDepthwiseConv2dAssemblyDispatch>();
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100102
103 if(is_nhwc)
Manuel Bottini05069f02019-09-26 17:18:26 +0100104 {
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100105 auto permute_input = std::make_unique<cpu::CpuPermute>();
106 auto permute_weights = std::make_unique<cpu::CpuPermute>();
107 auto permute_output = std::make_unique<cpu::CpuPermute>();
108
109 _memory_group.manage(&_impl->permuted_input);
110 _memory_group.manage(&_impl->permuted_weights);
111 _memory_group.manage(&_impl->permuted_output);
Manuel Bottini05069f02019-09-26 17:18:26 +0100112
113 // Configure the function to transform the input tensor from NCHW -> NHWC
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100114 permute_input->configure(input->info(), _impl->permuted_input.info(), PermutationVector(2U, 0U, 1U));
115 _impl->permuted_input.info()->set_data_layout(DataLayout::NHWC);
Manuel Bottini05069f02019-09-26 17:18:26 +0100116
117 // Configure the function to transform the weights tensor from IHW -> HWI
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100118 permute_weights->configure(weights->info(), _impl->permuted_weights.info(), PermutationVector(2U, 0U, 1U));
119 _impl->permuted_weights.info()->set_data_layout(DataLayout::NHWC);
Manuel Bottini05069f02019-09-26 17:18:26 +0100120
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100121 _impl->permuted_output.info()->set_data_layout(DataLayout::NHWC);
122 _impl->permuted_output.info()->set_quantization_info(output->info()->quantization_info());
Manuel Bottini05069f02019-09-26 17:18:26 +0100123
124 // Configure optimized depthwise
Michalis Spyroua7a74362021-04-23 10:32:48 +0100125 dwc_optimized_func->configure(_impl->permuted_input.info(), _impl->permuted_weights.info(), biases == nullptr ? nullptr : biases->info(), _impl->permuted_output.info(), info);
Manuel Bottini05069f02019-09-26 17:18:26 +0100126
127 // Configure the function to transform the convoluted output to ACL's native ordering format NCHW
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100128 _impl->permuted_output.info()->set_data_layout(DataLayout::NHWC);
129 permute_output->configure(_impl->permuted_output.info(), output->info(), PermutationVector(1U, 2U, 0U));
Manuel Bottini05069f02019-09-26 17:18:26 +0100130
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100131 _impl->permuted_input.allocator()->allocate();
132 _impl->permuted_output.allocator()->allocate();
Manuel Bottini05069f02019-09-26 17:18:26 +0100133 }
134 else
135 {
Michalis Spyroua7a74362021-04-23 10:32:48 +0100136 dwc_optimized_func->configure(_impl->src->info(), _impl->weights->info(), biases == nullptr ? nullptr : biases->info(), _impl->dst->info(), info);
Manuel Bottini05069f02019-09-26 17:18:26 +0100137 }
Manuel Bottini05069f02019-09-26 17:18:26 +0100138
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100139 // Allocate memory based on the internal memory requirements
140 experimental::MemoryRequirements mem_req = dwc_optimized_func->workspace();
Michele Di Giorgiod02d5ed2021-01-22 09:47:04 +0000141 _impl->workspace.allocator()->init(TensorInfo(TensorShape{ mem_req[0].size + mem_req[0].alignment }, 1, DataType::S8), mem_req[0].alignment);
142 _impl->packed_weights.allocator()->init(TensorInfo(TensorShape{ mem_req[1].size + mem_req[1].alignment }, 1, DataType::S8), mem_req[1].alignment);
143 _memory_group.manage(&_impl->workspace);
144 _memory_group.manage(&_impl->packed_weights);
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100145 _impl->workspace.allocator()->allocate();
146 _impl->packed_weights.allocator()->allocate();
Manuel Bottini05069f02019-09-26 17:18:26 +0100147}
148
149Status NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::validate(const ITensorInfo *input,
150 const ITensorInfo *weights,
151 const ITensorInfo *biases,
152 const ITensorInfo *output,
153 const PadStrideInfo &conv_info,
154 unsigned int depth_multiplier,
155 const ActivationLayerInfo &act_info,
156 const Size2D &dilation)
157{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100158 ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100159 return cpu::CpuDepthwiseConv2d::validate(input, weights, biases, output, info);
Manuel Bottini05069f02019-09-26 17:18:26 +0100160}
161
Manuel Bottini05069f02019-09-26 17:18:26 +0100162void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::run()
Georgios Pinitas30271c72019-06-24 14:56:34 +0100163{
164 prepare();
Georgios Pinitas30271c72019-06-24 14:56:34 +0100165 MemoryGroupResourceScope scope_mg(_memory_group);
166
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100167 ITensorPack pack;
168 pack.add_tensor(TensorType::ACL_SRC_0, _impl->src);
169 pack.add_tensor(TensorType::ACL_SRC_1, _impl->weights);
170 pack.add_tensor(TensorType::ACL_SRC_2, _impl->biases);
171 pack.add_tensor(TensorType::ACL_INT_0, &_impl->permuted_input);
172 pack.add_tensor(TensorType::ACL_INT_1, &_impl->permuted_weights);
173 pack.add_tensor(TensorType::ACL_INT_2, &_impl->permuted_output);
174 pack.add_tensor(TensorType::ACL_INT_3, &_impl->workspace);
175 pack.add_tensor(TensorType::ACL_INT_4, &_impl->packed_weights);
176 pack.add_tensor(TensorType::ACL_DST_0, _impl->dst);
Georgios Pinitas30271c72019-06-24 14:56:34 +0100177
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100178 _impl->op->run(pack);
Georgios Pinitas30271c72019-06-24 14:56:34 +0100179}
180
Manuel Bottini05069f02019-09-26 17:18:26 +0100181void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::prepare()
Georgios Pinitas30271c72019-06-24 14:56:34 +0100182{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100183 if(!_impl->is_prepared)
Georgios Pinitas30271c72019-06-24 14:56:34 +0100184 {
185 // Permute weights
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100186 if(_impl->permute)
Georgios Pinitas30271c72019-06-24 14:56:34 +0100187 {
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100188 _impl->permuted_weights.allocator()->allocate();
Georgios Pinitas30271c72019-06-24 14:56:34 +0100189 }
190
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100191 if(!_impl->permuted_weights.is_used())
Georgios Pinitas30271c72019-06-24 14:56:34 +0100192 {
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100193 _impl->permuted_weights.allocator()->free();
Georgios Pinitas30271c72019-06-24 14:56:34 +0100194 }
195
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100196 _impl->is_prepared = true;
Georgios Pinitas30271c72019-06-24 14:56:34 +0100197 }
198}
199
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100200struct NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::Impl
201{
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100202 Tensor permuted_input{};
203 Tensor permuted_weights{};
204 Tensor permuted_output{};
205 bool is_prepared{ false };
206 bool is_nchw{ false };
207 bool is_activationlayer_enabled{ false };
208 const ITensor *weights{ nullptr };
209 const ITensor *biases{ nullptr };
210 const ITensor *src{ nullptr };
211 ITensor *dst{ nullptr };
212 std::shared_ptr<cpu::CpuDepthwiseConv2d> op{ nullptr };
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100213};
214
Manuel Bottini05069f02019-09-26 17:18:26 +0100215NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::NEDepthwiseConvolutionLayerGeneric()
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100216 : _impl(std::make_unique<Impl>())
Michalis Spyroub7b31532017-11-23 12:10:21 +0000217{
218}
219
Manuel Bottini05069f02019-09-26 17:18:26 +0100220void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::configure(ITensor *input, const ITensor *weights, const ITensor *biases, ITensor *output, const PadStrideInfo &conv_info,
221 unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
Michalis Spyroub7b31532017-11-23 12:10:21 +0000222{
Michele Di Giorgioff271922019-07-17 15:59:32 +0100223 ARM_COMPUTE_ERROR_ON_NULLPTR(input, weights, output);
Michalis Spyroub7b31532017-11-23 12:10:21 +0000224
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100225 const ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100226 _impl->op = std::make_unique<cpu::CpuDepthwiseConv2d>();
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100227 _impl->op->configure(input->info(), weights->info(), biases == nullptr ? nullptr : biases->info(), output->info(), info);
228
229 _impl->src = input;
230 _impl->dst = output;
231 _impl->weights = weights;
232 _impl->biases = biases;
233 _impl->is_nchw = input->info()->data_layout() == DataLayout::NCHW;
234 _impl->is_prepared = !_impl->is_nchw;
Giorgio Arena26b22162018-08-13 15:49:49 +0100235
Giorgio Arenad93e2632019-10-15 11:09:33 +0100236 ITensor *input_to_use = input;
237 const ITensor *weights_to_use = weights;
238 ITensor *output_to_use = output;
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100239 if(_impl->is_nchw)
Giorgio Arena26b22162018-08-13 15:49:49 +0100240 {
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100241 auto permute_input = std::make_unique<cpu::CpuPermute>();
242 auto permute_weights = std::make_unique<cpu::CpuPermute>();
Giorgio Arena26b22162018-08-13 15:49:49 +0100243
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100244 permute_input->configure(input->info(), _impl->permuted_input.info(), PermutationVector(2U, 0U, 1U));
245 _impl->permuted_input.info()->set_data_layout(DataLayout::NHWC);
246 input_to_use = &_impl->permuted_input;
Giorgio Arena44f55722019-07-12 14:49:49 +0100247
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100248 permute_weights->configure(weights->info(), _impl->permuted_weights.info(), PermutationVector(2U, 0U, 1U));
249 _impl->permuted_weights.info()->set_data_layout(DataLayout::NHWC);
250 weights_to_use = &_impl->permuted_weights;
Giorgio Arena44f55722019-07-12 14:49:49 +0100251
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100252 _impl->permuted_output.allocator()->init(output->info()->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(TensorShape()));
253 output_to_use = &_impl->permuted_output;
Giorgio Arena26b22162018-08-13 15:49:49 +0100254 }
255
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100256 auto depthwise_conv_kernel = std::make_unique<cpu::kernels::CpuDepthwiseConv2dNativeKernel>();
Michalis Spyrou32944492021-04-20 15:20:31 +0100257 depthwise_conv_kernel->configure(input_to_use->info(), weights_to_use->info(), biases == nullptr ? nullptr : biases->info(), output_to_use->info(), info);
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100258
259 if(_impl->is_nchw)
Georgios Pinitas60e98252018-10-22 16:17:20 +0100260 {
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100261 auto permute_output = std::make_unique<cpu::CpuPermute>();
262 permute_output->configure(_impl->permuted_output.info(), output->info(), PermutationVector(1U, 2U, 0U));
263 _impl->permuted_output.info()->set_data_layout(DataLayout::NHWC);
264
265 _impl->permuted_input.allocator()->allocate();
266 _impl->permuted_weights.allocator()->allocate();
267 _impl->permuted_output.allocator()->allocate();
Georgios Pinitas60e98252018-10-22 16:17:20 +0100268 }
Michalis Spyroub7b31532017-11-23 12:10:21 +0000269}
270
Manuel Bottini05069f02019-09-26 17:18:26 +0100271Status NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output,
272 const PadStrideInfo &conv_info,
273 unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
Abe Mbise7784c832018-05-31 16:48:41 +0100274{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100275 ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100276 return cpu::CpuDepthwiseConv2d::validate(input, weights, biases, output, info);
Abe Mbise7784c832018-05-31 16:48:41 +0100277}
278
Manuel Bottini05069f02019-09-26 17:18:26 +0100279void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::run()
Michalis Spyroub7b31532017-11-23 12:10:21 +0000280{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100281 ITensorPack pack;
282 pack.add_tensor(TensorType::ACL_SRC_0, _impl->src);
283 pack.add_tensor(TensorType::ACL_SRC_1, _impl->weights);
284 pack.add_tensor(TensorType::ACL_SRC_2, _impl->biases);
285 pack.add_tensor(TensorType::ACL_INT_0, &_impl->permuted_input);
286 pack.add_tensor(TensorType::ACL_INT_1, &_impl->permuted_weights);
287 pack.add_tensor(TensorType::ACL_INT_2, &_impl->permuted_output);
288 pack.add_tensor(TensorType::ACL_DST_0, _impl->dst);
Giorgio Arenad93e2632019-10-15 11:09:33 +0100289
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100290 _impl->op->run(pack);
Georgios Pinitas72219332018-06-05 14:56:06 +0100291}
Manuel Bottini05069f02019-09-26 17:18:26 +0100292
293NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayer(std::shared_ptr<IMemoryManager> memory_manager)
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100294 : _memory_group(std::move(memory_manager)), _impl(std::make_unique<Impl>())
Manuel Bottini05069f02019-09-26 17:18:26 +0100295{
296}
297
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100298#ifndef DOXYGEN_SKIP_THIS
299struct NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayer::Impl
300{
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100301 DepthwiseConvolutionFunction depth_conv_func{ DepthwiseConvolutionFunction::OPTIMIZED };
302 NEDepthwiseConvolutionLayerOptimizedInternal func_optimized{ nullptr };
303 NEDepthwiseConvolutionLayerGeneric func_generic{};
304 std::shared_ptr<cpu::CpuDepthwiseConv2d> op{ nullptr };
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100305};
306#endif // DOXYGEN_SKIP_THIS
307
Manuel Bottini05069f02019-09-26 17:18:26 +0100308void NEDepthwiseConvolutionLayer::configure(ITensor *input, const ITensor *weights, const ITensor *biases, ITensor *output, const PadStrideInfo &conv_info, unsigned int depth_multiplier,
309 const ActivationLayerInfo &act_info, const Size2D &dilation)
310{
Jakub Sujaked9eb302023-05-11 13:15:46 +0100311 ARM_COMPUTE_ERROR_ON_NULLPTR(input, weights, output);
Ramy Elgammala8db6122023-05-08 03:33:43 +0100312
ramelg01cbbb0382021-09-17 17:36:57 +0100313 ARM_COMPUTE_LOG_PARAMS(input, weights, output, conv_info, depth_multiplier, biases, act_info, dilation);
Ramy Elgammala8db6122023-05-08 03:33:43 +0100314 ARM_COMPUTE_ERROR_THROW_ON(NEDepthwiseConvolutionLayer::validate(input->info(), weights->info(), (biases == nullptr) ? nullptr : biases->info(),
315 output->info(), conv_info, depth_multiplier, act_info, dilation));
ramelg01cbbb0382021-09-17 17:36:57 +0100316
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100317 const ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100318 _impl->op = std::make_shared<cpu::CpuDepthwiseConv2d>();
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100319 _impl->depth_conv_func = _impl->op->get_depthwiseconvolution_function(input->info(), weights->info(), (biases != nullptr) ? biases->info() : nullptr, output->info(),
320 info);
321 switch(_impl->depth_conv_func)
Manuel Bottini05069f02019-09-26 17:18:26 +0100322 {
323 case DepthwiseConvolutionFunction::OPTIMIZED:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100324 _impl->func_optimized.configure(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
Manuel Bottini05069f02019-09-26 17:18:26 +0100325 break;
326 case DepthwiseConvolutionFunction::GENERIC:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100327 _impl->func_generic.configure(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
Manuel Bottini05069f02019-09-26 17:18:26 +0100328 break;
329 default:
330 ARM_COMPUTE_ERROR("Unsupported DepthwiseConvolutionFunction");
331 }
332}
333
334Status NEDepthwiseConvolutionLayer::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info,
335 unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
336{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100337 ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100338 return cpu::CpuDepthwiseConv2d::validate(input, weights, biases, output, info);
Manuel Bottini05069f02019-09-26 17:18:26 +0100339}
340
341void NEDepthwiseConvolutionLayer::run()
342{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100343 switch(_impl->depth_conv_func)
Manuel Bottini05069f02019-09-26 17:18:26 +0100344 {
345 case DepthwiseConvolutionFunction::OPTIMIZED:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100346 _impl->func_optimized.run();
Manuel Bottini05069f02019-09-26 17:18:26 +0100347 break;
348 case DepthwiseConvolutionFunction::GENERIC:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100349 _impl->func_generic.run();
Manuel Bottini05069f02019-09-26 17:18:26 +0100350 break;
351 default:
352 ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
353 }
354}
355
356void NEDepthwiseConvolutionLayer::prepare()
357{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100358 switch(_impl->depth_conv_func)
Manuel Bottini05069f02019-09-26 17:18:26 +0100359 {
360 case DepthwiseConvolutionFunction::OPTIMIZED:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100361 _impl->func_optimized.prepare();
Manuel Bottini05069f02019-09-26 17:18:26 +0100362 break;
363 case DepthwiseConvolutionFunction::GENERIC:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100364 _impl->func_generic.prepare();
Manuel Bottini05069f02019-09-26 17:18:26 +0100365 break;
366 default:
367 ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
368 }
369}
Georgios Pinitas47d39dc2019-03-11 14:03:23 +0000370} // namespace arm_compute