blob: fb6a2b08da6f7d1c00f8759b4de692d20ea39e05 [file] [log] [blame]
Michalis Spyrou7362f0d2017-10-18 17:58:22 +01001/*
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +01002 * Copyright (c) 2017-2021 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);
Michele Di Giorgioff271922019-07-17 15:59:32 +0100224 ARM_COMPUTE_ERROR_THROW_ON(NEDepthwiseConvolutionLayer::validate(input->info(), weights->info(), (biases == nullptr) ? nullptr : biases->info(),
225 output->info(), conv_info, depth_multiplier, act_info, dilation));
Michalis Spyroub7b31532017-11-23 12:10:21 +0000226
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100227 const ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100228 _impl->op = std::make_unique<cpu::CpuDepthwiseConv2d>();
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100229 _impl->op->configure(input->info(), weights->info(), biases == nullptr ? nullptr : biases->info(), output->info(), info);
230
231 _impl->src = input;
232 _impl->dst = output;
233 _impl->weights = weights;
234 _impl->biases = biases;
235 _impl->is_nchw = input->info()->data_layout() == DataLayout::NCHW;
236 _impl->is_prepared = !_impl->is_nchw;
Giorgio Arena26b22162018-08-13 15:49:49 +0100237
Giorgio Arenad93e2632019-10-15 11:09:33 +0100238 ITensor *input_to_use = input;
239 const ITensor *weights_to_use = weights;
240 ITensor *output_to_use = output;
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100241 if(_impl->is_nchw)
Giorgio Arena26b22162018-08-13 15:49:49 +0100242 {
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100243 auto permute_input = std::make_unique<cpu::CpuPermute>();
244 auto permute_weights = std::make_unique<cpu::CpuPermute>();
Giorgio Arena26b22162018-08-13 15:49:49 +0100245
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100246 permute_input->configure(input->info(), _impl->permuted_input.info(), PermutationVector(2U, 0U, 1U));
247 _impl->permuted_input.info()->set_data_layout(DataLayout::NHWC);
248 input_to_use = &_impl->permuted_input;
Giorgio Arena44f55722019-07-12 14:49:49 +0100249
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100250 permute_weights->configure(weights->info(), _impl->permuted_weights.info(), PermutationVector(2U, 0U, 1U));
251 _impl->permuted_weights.info()->set_data_layout(DataLayout::NHWC);
252 weights_to_use = &_impl->permuted_weights;
Giorgio Arena44f55722019-07-12 14:49:49 +0100253
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100254 _impl->permuted_output.allocator()->init(output->info()->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(TensorShape()));
255 output_to_use = &_impl->permuted_output;
Giorgio Arena26b22162018-08-13 15:49:49 +0100256 }
257
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100258 auto depthwise_conv_kernel = std::make_unique<cpu::kernels::CpuDepthwiseConv2dNativeKernel>();
Michalis Spyrou32944492021-04-20 15:20:31 +0100259 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 +0100260
261 if(_impl->is_nchw)
Georgios Pinitas60e98252018-10-22 16:17:20 +0100262 {
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100263 auto permute_output = std::make_unique<cpu::CpuPermute>();
264 permute_output->configure(_impl->permuted_output.info(), output->info(), PermutationVector(1U, 2U, 0U));
265 _impl->permuted_output.info()->set_data_layout(DataLayout::NHWC);
266
267 _impl->permuted_input.allocator()->allocate();
268 _impl->permuted_weights.allocator()->allocate();
269 _impl->permuted_output.allocator()->allocate();
Georgios Pinitas60e98252018-10-22 16:17:20 +0100270 }
Michalis Spyroub7b31532017-11-23 12:10:21 +0000271}
272
Manuel Bottini05069f02019-09-26 17:18:26 +0100273Status NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output,
274 const PadStrideInfo &conv_info,
275 unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
Abe Mbise7784c832018-05-31 16:48:41 +0100276{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100277 ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100278 return cpu::CpuDepthwiseConv2d::validate(input, weights, biases, output, info);
Abe Mbise7784c832018-05-31 16:48:41 +0100279}
280
Manuel Bottini05069f02019-09-26 17:18:26 +0100281void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::run()
Michalis Spyroub7b31532017-11-23 12:10:21 +0000282{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100283 ITensorPack pack;
284 pack.add_tensor(TensorType::ACL_SRC_0, _impl->src);
285 pack.add_tensor(TensorType::ACL_SRC_1, _impl->weights);
286 pack.add_tensor(TensorType::ACL_SRC_2, _impl->biases);
287 pack.add_tensor(TensorType::ACL_INT_0, &_impl->permuted_input);
288 pack.add_tensor(TensorType::ACL_INT_1, &_impl->permuted_weights);
289 pack.add_tensor(TensorType::ACL_INT_2, &_impl->permuted_output);
290 pack.add_tensor(TensorType::ACL_DST_0, _impl->dst);
Giorgio Arenad93e2632019-10-15 11:09:33 +0100291
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100292 _impl->op->run(pack);
Georgios Pinitas72219332018-06-05 14:56:06 +0100293}
Manuel Bottini05069f02019-09-26 17:18:26 +0100294
295NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayer(std::shared_ptr<IMemoryManager> memory_manager)
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100296 : _memory_group(std::move(memory_manager)), _impl(std::make_unique<Impl>())
Manuel Bottini05069f02019-09-26 17:18:26 +0100297{
298}
299
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100300#ifndef DOXYGEN_SKIP_THIS
301struct NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayer::Impl
302{
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100303 DepthwiseConvolutionFunction depth_conv_func{ DepthwiseConvolutionFunction::OPTIMIZED };
304 NEDepthwiseConvolutionLayerOptimizedInternal func_optimized{ nullptr };
305 NEDepthwiseConvolutionLayerGeneric func_generic{};
306 std::shared_ptr<cpu::CpuDepthwiseConv2d> op{ nullptr };
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100307};
308#endif // DOXYGEN_SKIP_THIS
309
Manuel Bottini05069f02019-09-26 17:18:26 +0100310void NEDepthwiseConvolutionLayer::configure(ITensor *input, const ITensor *weights, const ITensor *biases, ITensor *output, const PadStrideInfo &conv_info, unsigned int depth_multiplier,
311 const ActivationLayerInfo &act_info, const Size2D &dilation)
312{
ramelg01cbbb0382021-09-17 17:36:57 +0100313 ARM_COMPUTE_LOG_PARAMS(input, weights, output, conv_info, depth_multiplier, biases, act_info, dilation);
314
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100315 const ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100316 _impl->op = std::make_shared<cpu::CpuDepthwiseConv2d>();
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100317 _impl->depth_conv_func = _impl->op->get_depthwiseconvolution_function(input->info(), weights->info(), (biases != nullptr) ? biases->info() : nullptr, output->info(),
318 info);
319 switch(_impl->depth_conv_func)
Manuel Bottini05069f02019-09-26 17:18:26 +0100320 {
321 case DepthwiseConvolutionFunction::OPTIMIZED:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100322 _impl->func_optimized.configure(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
Manuel Bottini05069f02019-09-26 17:18:26 +0100323 break;
324 case DepthwiseConvolutionFunction::GENERIC:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100325 _impl->func_generic.configure(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
Manuel Bottini05069f02019-09-26 17:18:26 +0100326 break;
327 default:
328 ARM_COMPUTE_ERROR("Unsupported DepthwiseConvolutionFunction");
329 }
330}
331
332Status NEDepthwiseConvolutionLayer::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info,
333 unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
334{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100335 ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100336 return cpu::CpuDepthwiseConv2d::validate(input, weights, biases, output, info);
Manuel Bottini05069f02019-09-26 17:18:26 +0100337}
338
339void NEDepthwiseConvolutionLayer::run()
340{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100341 switch(_impl->depth_conv_func)
Manuel Bottini05069f02019-09-26 17:18:26 +0100342 {
343 case DepthwiseConvolutionFunction::OPTIMIZED:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100344 _impl->func_optimized.run();
Manuel Bottini05069f02019-09-26 17:18:26 +0100345 break;
346 case DepthwiseConvolutionFunction::GENERIC:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100347 _impl->func_generic.run();
Manuel Bottini05069f02019-09-26 17:18:26 +0100348 break;
349 default:
350 ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
351 }
352}
353
354void NEDepthwiseConvolutionLayer::prepare()
355{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100356 switch(_impl->depth_conv_func)
Manuel Bottini05069f02019-09-26 17:18:26 +0100357 {
358 case DepthwiseConvolutionFunction::OPTIMIZED:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100359 _impl->func_optimized.prepare();
Manuel Bottini05069f02019-09-26 17:18:26 +0100360 break;
361 case DepthwiseConvolutionFunction::GENERIC:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100362 _impl->func_generic.prepare();
Manuel Bottini05069f02019-09-26 17:18:26 +0100363 break;
364 default:
365 ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
366 }
367}
Georgios Pinitas47d39dc2019-03-11 14:03:23 +0000368} // namespace arm_compute