blob: daa5fd5ab906506418bb25e9f7e5a73a86dacf51 [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"
Manuel Bottinib4bb6a02021-05-24 16:01:32 +010030#include "src/runtime/cpu/operators/CpuDepthwiseConv2d.h"
Georgios Pinitas47d39dc2019-03-11 14:03:23 +000031
Georgios Pinitasd05dce42018-01-22 16:29:17 +000032using namespace arm_compute::misc;
Georgios Pinitas4074c992018-01-30 18:13:46 +000033using namespace arm_compute::misc::shape_calculator;
Michalis Spyrou7362f0d2017-10-18 17:58:22 +010034
Georgios Pinitas47d39dc2019-03-11 14:03:23 +000035namespace arm_compute
36{
Michalis Spyrouebcebf12020-10-21 00:04:14 +010037NEDepthwiseConvolutionLayer::~NEDepthwiseConvolutionLayer() = default;
38
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010039struct NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::Impl
40{
41 ITensor *src{ nullptr }; // SRC_0
42 ITensor *dst{ nullptr }; // DST_0
43 const ITensor *weights
44 {
45 nullptr
46 }; // SRC_1
47 const ITensor *biases
48 {
49 nullptr
Manuel Bottinib4bb6a02021-05-24 16:01:32 +010050 }; // SRC_2
51 Tensor permuted_input{}; // INT_0
52 Tensor permuted_weights{}; // INT_1
53 Tensor permuted_output{}; // INT_2
54 Tensor workspace{}; // INT_3
55 Tensor packed_weights{}; // INT_4
56 std::shared_ptr<cpu::CpuDepthwiseConv2d> op{ nullptr };
57 bool is_prepared{ false };
58 bool permute{ false };
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010059};
60
Manuel Bottini05069f02019-09-26 17:18:26 +010061NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::NEDepthwiseConvolutionLayerOptimizedInternal(std::shared_ptr<IMemoryManager> memory_manager)
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010062 : _memory_group(memory_manager), _impl(std::make_unique<Impl>())
Manuel Bottini05069f02019-09-26 17:18:26 +010063{
64}
65
Georgios Pinitas7d0adc62020-09-04 15:25:24 +010066void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::configure(ITensor *input,
67 const ITensor *weights,
68 const ITensor *biases,
69 ITensor *output, const PadStrideInfo &conv_info,
70 unsigned int depth_multiplier,
71 const ActivationLayerInfo &act_info,
72 const Size2D &dilation)
Manuel Bottini05069f02019-09-26 17:18:26 +010073{
Georgios Pinitas7d0adc62020-09-04 15:25:24 +010074 ARM_COMPUTE_ERROR_ON_NULLPTR(input, weights, output);
Manuel Bottini05069f02019-09-26 17:18:26 +010075
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010076 bool is_nhwc = input->info()->data_layout() == DataLayout::NCHW;
77 _impl->src = input;
78 _impl->weights = weights;
79 _impl->biases = biases;
80 _impl->dst = output;
81 _impl->permute = is_nhwc;
82
Manuel Bottinib4bb6a02021-05-24 16:01:32 +010083 _impl->op = std::make_unique<cpu::CpuDepthwiseConv2d>();
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010084 ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
85 _impl->op->configure(_impl->src->info(), _impl->weights->info(), _impl->biases == nullptr ? nullptr : _impl->biases->info(),
86 _impl->dst->info(), info);
Manuel Bottini05069f02019-09-26 17:18:26 +010087
Georgios Pinitas7d0adc62020-09-04 15:25:24 +010088 // Configure pipeline
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010089 ActivationLayerInfo act_info_to_use = ActivationLayerInfo();
90 const bool is_relu = arm_compute::utils::info_helpers::is_relu(act_info);
91 const bool is_relu6 = arm_compute::utils::info_helpers::is_relu6(act_info);
92 bool is_activationlayer_enabled = act_info.enabled() && !(is_relu || is_relu6);
93
94 if(!is_activationlayer_enabled)
Manuel Bottini05069f02019-09-26 17:18:26 +010095 {
96 act_info_to_use = act_info;
97 }
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010098 info = ConvolutionInfo{ conv_info, depth_multiplier, act_info_to_use, dilation };
Manuel Bottini05069f02019-09-26 17:18:26 +010099
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100100 auto dwc_optimized_func = std::make_unique<cpu::CpuDepthwiseConv2dAssemblyDispatch>();
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100101
102 if(is_nhwc)
Manuel Bottini05069f02019-09-26 17:18:26 +0100103 {
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100104 auto permute_input = std::make_unique<cpu::CpuPermute>();
105 auto permute_weights = std::make_unique<cpu::CpuPermute>();
106 auto permute_output = std::make_unique<cpu::CpuPermute>();
107
108 _memory_group.manage(&_impl->permuted_input);
109 _memory_group.manage(&_impl->permuted_weights);
110 _memory_group.manage(&_impl->permuted_output);
Manuel Bottini05069f02019-09-26 17:18:26 +0100111
112 // Configure the function to transform the input tensor from NCHW -> NHWC
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100113 permute_input->configure(input->info(), _impl->permuted_input.info(), PermutationVector(2U, 0U, 1U));
114 _impl->permuted_input.info()->set_data_layout(DataLayout::NHWC);
Manuel Bottini05069f02019-09-26 17:18:26 +0100115
116 // Configure the function to transform the weights tensor from IHW -> HWI
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100117 permute_weights->configure(weights->info(), _impl->permuted_weights.info(), PermutationVector(2U, 0U, 1U));
118 _impl->permuted_weights.info()->set_data_layout(DataLayout::NHWC);
Manuel Bottini05069f02019-09-26 17:18:26 +0100119
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100120 _impl->permuted_output.info()->set_data_layout(DataLayout::NHWC);
121 _impl->permuted_output.info()->set_quantization_info(output->info()->quantization_info());
Manuel Bottini05069f02019-09-26 17:18:26 +0100122
123 // Configure optimized depthwise
Michalis Spyroua7a74362021-04-23 10:32:48 +0100124 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 +0100125
126 // Configure the function to transform the convoluted output to ACL's native ordering format NCHW
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100127 _impl->permuted_output.info()->set_data_layout(DataLayout::NHWC);
128 permute_output->configure(_impl->permuted_output.info(), output->info(), PermutationVector(1U, 2U, 0U));
Manuel Bottini05069f02019-09-26 17:18:26 +0100129
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100130 _impl->permuted_input.allocator()->allocate();
131 _impl->permuted_output.allocator()->allocate();
Manuel Bottini05069f02019-09-26 17:18:26 +0100132 }
133 else
134 {
Michalis Spyroua7a74362021-04-23 10:32:48 +0100135 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 +0100136 }
Manuel Bottini05069f02019-09-26 17:18:26 +0100137
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100138 // Allocate memory based on the internal memory requirements
139 experimental::MemoryRequirements mem_req = dwc_optimized_func->workspace();
Michele Di Giorgiod02d5ed2021-01-22 09:47:04 +0000140 _impl->workspace.allocator()->init(TensorInfo(TensorShape{ mem_req[0].size + mem_req[0].alignment }, 1, DataType::S8), mem_req[0].alignment);
141 _impl->packed_weights.allocator()->init(TensorInfo(TensorShape{ mem_req[1].size + mem_req[1].alignment }, 1, DataType::S8), mem_req[1].alignment);
142 _memory_group.manage(&_impl->workspace);
143 _memory_group.manage(&_impl->packed_weights);
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100144 _impl->workspace.allocator()->allocate();
145 _impl->packed_weights.allocator()->allocate();
Manuel Bottini05069f02019-09-26 17:18:26 +0100146}
147
148Status NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::validate(const ITensorInfo *input,
149 const ITensorInfo *weights,
150 const ITensorInfo *biases,
151 const ITensorInfo *output,
152 const PadStrideInfo &conv_info,
153 unsigned int depth_multiplier,
154 const ActivationLayerInfo &act_info,
155 const Size2D &dilation)
156{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100157 ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100158 return cpu::CpuDepthwiseConv2d::validate(input, weights, biases, output, info);
Manuel Bottini05069f02019-09-26 17:18:26 +0100159}
160
Manuel Bottini05069f02019-09-26 17:18:26 +0100161void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::run()
Georgios Pinitas30271c72019-06-24 14:56:34 +0100162{
163 prepare();
Georgios Pinitas30271c72019-06-24 14:56:34 +0100164 MemoryGroupResourceScope scope_mg(_memory_group);
165
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100166 ITensorPack pack;
167 pack.add_tensor(TensorType::ACL_SRC_0, _impl->src);
168 pack.add_tensor(TensorType::ACL_SRC_1, _impl->weights);
169 pack.add_tensor(TensorType::ACL_SRC_2, _impl->biases);
170 pack.add_tensor(TensorType::ACL_INT_0, &_impl->permuted_input);
171 pack.add_tensor(TensorType::ACL_INT_1, &_impl->permuted_weights);
172 pack.add_tensor(TensorType::ACL_INT_2, &_impl->permuted_output);
173 pack.add_tensor(TensorType::ACL_INT_3, &_impl->workspace);
174 pack.add_tensor(TensorType::ACL_INT_4, &_impl->packed_weights);
175 pack.add_tensor(TensorType::ACL_DST_0, _impl->dst);
Georgios Pinitas30271c72019-06-24 14:56:34 +0100176
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100177 _impl->op->run(pack);
Georgios Pinitas30271c72019-06-24 14:56:34 +0100178}
179
Manuel Bottini05069f02019-09-26 17:18:26 +0100180void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::prepare()
Georgios Pinitas30271c72019-06-24 14:56:34 +0100181{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100182 if(!_impl->is_prepared)
Georgios Pinitas30271c72019-06-24 14:56:34 +0100183 {
184 // Permute weights
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100185 if(_impl->permute)
Georgios Pinitas30271c72019-06-24 14:56:34 +0100186 {
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100187 _impl->permuted_weights.allocator()->allocate();
Georgios Pinitas30271c72019-06-24 14:56:34 +0100188 }
189
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100190 if(!_impl->permuted_weights.is_used())
Georgios Pinitas30271c72019-06-24 14:56:34 +0100191 {
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100192 _impl->permuted_weights.allocator()->free();
Georgios Pinitas30271c72019-06-24 14:56:34 +0100193 }
194
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100195 _impl->is_prepared = true;
Georgios Pinitas30271c72019-06-24 14:56:34 +0100196 }
197}
198
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100199struct NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::Impl
200{
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100201 Tensor permuted_input{};
202 Tensor permuted_weights{};
203 Tensor permuted_output{};
204 bool is_prepared{ false };
205 bool is_nchw{ false };
206 bool is_activationlayer_enabled{ false };
207 const ITensor *weights{ nullptr };
208 const ITensor *biases{ nullptr };
209 const ITensor *src{ nullptr };
210 ITensor *dst{ nullptr };
211 std::shared_ptr<cpu::CpuDepthwiseConv2d> op{ nullptr };
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100212};
213
Manuel Bottini05069f02019-09-26 17:18:26 +0100214NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::NEDepthwiseConvolutionLayerGeneric()
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100215 : _impl(std::make_unique<Impl>())
Michalis Spyroub7b31532017-11-23 12:10:21 +0000216{
217}
218
Manuel Bottini05069f02019-09-26 17:18:26 +0100219void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::configure(ITensor *input, const ITensor *weights, const ITensor *biases, ITensor *output, const PadStrideInfo &conv_info,
220 unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
Michalis Spyroub7b31532017-11-23 12:10:21 +0000221{
Michele Di Giorgioff271922019-07-17 15:59:32 +0100222 ARM_COMPUTE_ERROR_ON_NULLPTR(input, weights, output);
Michele Di Giorgioff271922019-07-17 15:59:32 +0100223 ARM_COMPUTE_ERROR_THROW_ON(NEDepthwiseConvolutionLayer::validate(input->info(), weights->info(), (biases == nullptr) ? nullptr : biases->info(),
224 output->info(), conv_info, depth_multiplier, act_info, dilation));
Michalis Spyroub7b31532017-11-23 12:10:21 +0000225
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100226 const ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100227 _impl->op = std::make_unique<cpu::CpuDepthwiseConv2d>();
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100228 _impl->op->configure(input->info(), weights->info(), biases == nullptr ? nullptr : biases->info(), output->info(), info);
229
230 _impl->src = input;
231 _impl->dst = output;
232 _impl->weights = weights;
233 _impl->biases = biases;
234 _impl->is_nchw = input->info()->data_layout() == DataLayout::NCHW;
235 _impl->is_prepared = !_impl->is_nchw;
Giorgio Arena26b22162018-08-13 15:49:49 +0100236
Giorgio Arenad93e2632019-10-15 11:09:33 +0100237 ITensor *input_to_use = input;
238 const ITensor *weights_to_use = weights;
239 ITensor *output_to_use = output;
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100240 if(_impl->is_nchw)
Giorgio Arena26b22162018-08-13 15:49:49 +0100241 {
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100242 auto permute_input = std::make_unique<cpu::CpuPermute>();
243 auto permute_weights = std::make_unique<cpu::CpuPermute>();
Giorgio Arena26b22162018-08-13 15:49:49 +0100244
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100245 permute_input->configure(input->info(), _impl->permuted_input.info(), PermutationVector(2U, 0U, 1U));
246 _impl->permuted_input.info()->set_data_layout(DataLayout::NHWC);
247 input_to_use = &_impl->permuted_input;
Giorgio Arena44f55722019-07-12 14:49:49 +0100248
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100249 permute_weights->configure(weights->info(), _impl->permuted_weights.info(), PermutationVector(2U, 0U, 1U));
250 _impl->permuted_weights.info()->set_data_layout(DataLayout::NHWC);
251 weights_to_use = &_impl->permuted_weights;
Giorgio Arena44f55722019-07-12 14:49:49 +0100252
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100253 _impl->permuted_output.allocator()->init(output->info()->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(TensorShape()));
254 output_to_use = &_impl->permuted_output;
Giorgio Arena26b22162018-08-13 15:49:49 +0100255 }
256
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100257 auto depthwise_conv_kernel = std::make_unique<cpu::kernels::CpuDepthwiseConv2dNativeKernel>();
Michalis Spyrou32944492021-04-20 15:20:31 +0100258 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 +0100259
260 if(_impl->is_nchw)
Georgios Pinitas60e98252018-10-22 16:17:20 +0100261 {
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100262 auto permute_output = std::make_unique<cpu::CpuPermute>();
263 permute_output->configure(_impl->permuted_output.info(), output->info(), PermutationVector(1U, 2U, 0U));
264 _impl->permuted_output.info()->set_data_layout(DataLayout::NHWC);
265
266 _impl->permuted_input.allocator()->allocate();
267 _impl->permuted_weights.allocator()->allocate();
268 _impl->permuted_output.allocator()->allocate();
Georgios Pinitas60e98252018-10-22 16:17:20 +0100269 }
Michalis Spyroub7b31532017-11-23 12:10:21 +0000270}
271
Manuel Bottini05069f02019-09-26 17:18:26 +0100272Status NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output,
273 const PadStrideInfo &conv_info,
274 unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
Abe Mbise7784c832018-05-31 16:48:41 +0100275{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100276 ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100277 return cpu::CpuDepthwiseConv2d::validate(input, weights, biases, output, info);
Abe Mbise7784c832018-05-31 16:48:41 +0100278}
279
Manuel Bottini05069f02019-09-26 17:18:26 +0100280void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::run()
Michalis Spyroub7b31532017-11-23 12:10:21 +0000281{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100282 ITensorPack pack;
283 pack.add_tensor(TensorType::ACL_SRC_0, _impl->src);
284 pack.add_tensor(TensorType::ACL_SRC_1, _impl->weights);
285 pack.add_tensor(TensorType::ACL_SRC_2, _impl->biases);
286 pack.add_tensor(TensorType::ACL_INT_0, &_impl->permuted_input);
287 pack.add_tensor(TensorType::ACL_INT_1, &_impl->permuted_weights);
288 pack.add_tensor(TensorType::ACL_INT_2, &_impl->permuted_output);
289 pack.add_tensor(TensorType::ACL_DST_0, _impl->dst);
Giorgio Arenad93e2632019-10-15 11:09:33 +0100290
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100291 _impl->op->run(pack);
Georgios Pinitas72219332018-06-05 14:56:06 +0100292}
Manuel Bottini05069f02019-09-26 17:18:26 +0100293
294NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayer(std::shared_ptr<IMemoryManager> memory_manager)
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100295 : _memory_group(std::move(memory_manager)), _impl(std::make_unique<Impl>())
Manuel Bottini05069f02019-09-26 17:18:26 +0100296{
297}
298
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100299#ifndef DOXYGEN_SKIP_THIS
300struct NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayer::Impl
301{
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100302 DepthwiseConvolutionFunction depth_conv_func{ DepthwiseConvolutionFunction::OPTIMIZED };
303 NEDepthwiseConvolutionLayerOptimizedInternal func_optimized{ nullptr };
304 NEDepthwiseConvolutionLayerGeneric func_generic{};
305 std::shared_ptr<cpu::CpuDepthwiseConv2d> op{ nullptr };
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100306};
307#endif // DOXYGEN_SKIP_THIS
308
Manuel Bottini05069f02019-09-26 17:18:26 +0100309void NEDepthwiseConvolutionLayer::configure(ITensor *input, const ITensor *weights, const ITensor *biases, ITensor *output, const PadStrideInfo &conv_info, unsigned int depth_multiplier,
310 const ActivationLayerInfo &act_info, const Size2D &dilation)
311{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100312 const ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100313 _impl->op = std::make_shared<cpu::CpuDepthwiseConv2d>();
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100314 _impl->depth_conv_func = _impl->op->get_depthwiseconvolution_function(input->info(), weights->info(), (biases != nullptr) ? biases->info() : nullptr, output->info(),
315 info);
316 switch(_impl->depth_conv_func)
Manuel Bottini05069f02019-09-26 17:18:26 +0100317 {
318 case DepthwiseConvolutionFunction::OPTIMIZED:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100319 _impl->func_optimized.configure(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
Manuel Bottini05069f02019-09-26 17:18:26 +0100320 break;
321 case DepthwiseConvolutionFunction::GENERIC:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100322 _impl->func_generic.configure(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
Manuel Bottini05069f02019-09-26 17:18:26 +0100323 break;
324 default:
325 ARM_COMPUTE_ERROR("Unsupported DepthwiseConvolutionFunction");
326 }
327}
328
329Status NEDepthwiseConvolutionLayer::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info,
330 unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
331{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100332 ConvolutionInfo info{ conv_info, depth_multiplier, act_info, dilation };
Manuel Bottinib4bb6a02021-05-24 16:01:32 +0100333 return cpu::CpuDepthwiseConv2d::validate(input, weights, biases, output, info);
Manuel Bottini05069f02019-09-26 17:18:26 +0100334}
335
336void NEDepthwiseConvolutionLayer::run()
337{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100338 switch(_impl->depth_conv_func)
Manuel Bottini05069f02019-09-26 17:18:26 +0100339 {
340 case DepthwiseConvolutionFunction::OPTIMIZED:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100341 _impl->func_optimized.run();
Manuel Bottini05069f02019-09-26 17:18:26 +0100342 break;
343 case DepthwiseConvolutionFunction::GENERIC:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100344 _impl->func_generic.run();
Manuel Bottini05069f02019-09-26 17:18:26 +0100345 break;
346 default:
347 ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
348 }
349}
350
351void NEDepthwiseConvolutionLayer::prepare()
352{
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100353 switch(_impl->depth_conv_func)
Manuel Bottini05069f02019-09-26 17:18:26 +0100354 {
355 case DepthwiseConvolutionFunction::OPTIMIZED:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100356 _impl->func_optimized.prepare();
Manuel Bottini05069f02019-09-26 17:18:26 +0100357 break;
358 case DepthwiseConvolutionFunction::GENERIC:
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100359 _impl->func_generic.prepare();
Manuel Bottini05069f02019-09-26 17:18:26 +0100360 break;
361 default:
362 ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
363 }
364}
Georgios Pinitas47d39dc2019-03-11 14:03:23 +0000365} // namespace arm_compute