blob: 915a2830bf38ec0439db3251d6e836d7d117bf12 [file] [log] [blame]
Michalis Spyrou7362f0d2017-10-18 17:58:22 +01001/*
Michele Di Giorgiod9eaf612020-07-08 11:12:57 +01002 * Copyright (c) 2017-2020 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"
Georgios Pinitas47d39dc2019-03-11 14:03:23 +000030
Georgios Pinitasd05dce42018-01-22 16:29:17 +000031using namespace arm_compute::misc;
Georgios Pinitas4074c992018-01-30 18:13:46 +000032using namespace arm_compute::misc::shape_calculator;
Michalis Spyrou7362f0d2017-10-18 17:58:22 +010033
Georgios Pinitas47d39dc2019-03-11 14:03:23 +000034namespace arm_compute
35{
Manuel Bottini05069f02019-09-26 17:18:26 +010036namespace
Michalis Spyrou7362f0d2017-10-18 17:58:22 +010037{
Manuel Bottini05069f02019-09-26 17:18:26 +010038Status validate_arguments_optimized(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info,
39 unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
Georgios Pinitas30271c72019-06-24 14:56:34 +010040{
41 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, weights, output);
Michele Di Giorgio13ec5f02020-01-02 12:11:13 +000042 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::F16, DataType::F32);
Giuseppe Rossinif01201a2019-11-06 14:57:49 +000043 if(!is_data_type_quantized_per_channel(weights->data_type()))
44 {
45 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, weights);
46 }
Georgios Pinitas30271c72019-06-24 14:56:34 +010047 ARM_COMPUTE_RETURN_ERROR_ON(input->data_layout() == DataLayout::UNKNOWN);
48 ARM_COMPUTE_RETURN_ERROR_ON(dilation.x() < 1 || dilation.y() < 1);
49 const size_t idx_w = get_data_layout_dimension_index(input->data_layout(), DataLayoutDimension::WIDTH);
50 const size_t idx_h = get_data_layout_dimension_index(input->data_layout(), DataLayoutDimension::HEIGHT);
51 ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(idx_w) + (weights->dimension(idx_w) - 1) * (dilation.x() - 1) > input->dimension(idx_w) + conv_info.pad_left() + conv_info.pad_right());
52 ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(idx_h) + (weights->dimension(idx_h) - 1) * (dilation.y() - 1) > input->dimension(idx_h) + conv_info.pad_top() + conv_info.pad_bottom());
53
54 if(biases != nullptr)
55 {
56 const unsigned int channel_idx = get_data_layout_dimension_index(input->data_layout(), DataLayoutDimension::CHANNEL);
57 ARM_COMPUTE_RETURN_ERROR_ON(biases->num_dimensions() > 1);
58 ARM_COMPUTE_RETURN_ERROR_ON(biases->dimension(0) != weights->dimension(channel_idx));
59 }
60
Georgios Pinitas7d0adc62020-09-04 15:25:24 +010061 ARM_COMPUTE_RETURN_ON_ERROR(NEDepthwiseConvolutionAssemblyDispatch::validate(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation));
Georgios Pinitas30271c72019-06-24 14:56:34 +010062
63 //Validate Activation Layer
64 if(act_info.enabled())
65 {
66 ARM_COMPUTE_RETURN_ON_ERROR(NEActivationLayer::validate(output, nullptr, act_info));
67 }
Georgios Pinitas30271c72019-06-24 14:56:34 +010068 return Status{};
69}
Manuel Bottini05069f02019-09-26 17:18:26 +010070} // namespace
Georgios Pinitas30271c72019-06-24 14:56:34 +010071
Manuel Bottini05069f02019-09-26 17:18:26 +010072NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::NEDepthwiseConvolutionLayerOptimizedInternal(std::shared_ptr<IMemoryManager> memory_manager)
Georgios Pinitas7d0adc62020-09-04 15:25:24 +010073 : _memory_group(memory_manager), _dwc_optimized_func(memory_manager), _output_stage_kernel(), _border_handler(), _permute_input(), _permute_weights(), _permute_output(), _activationlayer_function(),
74 _accumulator(), _permuted_input(), _permuted_weights(), _permuted_output(), _original_weights(nullptr), _has_bias(false), _is_quantized(false), _is_nchw(true), _permute(false),
75 _is_activationlayer_enabled(false), _is_prepared(false)
Manuel Bottini05069f02019-09-26 17:18:26 +010076{
77}
78
Georgios Pinitas7d0adc62020-09-04 15:25:24 +010079void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::configure(ITensor *input,
80 const ITensor *weights,
81 const ITensor *biases,
82 ITensor *output, const PadStrideInfo &conv_info,
83 unsigned int depth_multiplier,
84 const ActivationLayerInfo &act_info,
85 const Size2D &dilation)
Manuel Bottini05069f02019-09-26 17:18:26 +010086{
Georgios Pinitas7d0adc62020-09-04 15:25:24 +010087 ARM_COMPUTE_ERROR_ON_NULLPTR(input, weights, output);
88 // Perform validation step
89 ARM_COMPUTE_ERROR_THROW_ON(NEDepthwiseConvolutionLayerOptimizedInternal::validate(input->info(), weights->info(), (biases == nullptr) ? nullptr : biases->info(),
90 output->info(), conv_info, depth_multiplier, act_info, dilation));
Manuel Bottini05069f02019-09-26 17:18:26 +010091
Georgios Pinitas7d0adc62020-09-04 15:25:24 +010092 _original_weights = weights;
93 _is_quantized = is_data_type_quantized_asymmetric(input->info()->data_type());
94 _has_bias = biases != nullptr;
95 _is_nchw = input->info()->data_layout() == DataLayout::NCHW;
96 _permute = _is_nchw;
97 _is_prepared = false;
98 _is_activationlayer_enabled = act_info.enabled();
Manuel Bottini05069f02019-09-26 17:18:26 +010099
Georgios Pinitas7d0adc62020-09-04 15:25:24 +0100100 // Configure pipeline
Manuel Bottini05069f02019-09-26 17:18:26 +0100101 ActivationLayerInfo act_info_to_use = ActivationLayerInfo();
102 const bool is_relu = arm_compute::utils::info_helpers::is_relu(act_info);
103 const bool is_relu6 = arm_compute::utils::info_helpers::is_relu6(act_info);
104 _is_activationlayer_enabled = act_info.enabled() && !(is_relu || is_relu6);
105 if(!_is_activationlayer_enabled)
106 {
107 act_info_to_use = act_info;
108 }
109
110 if(_is_nchw)
111 {
112 _memory_group.manage(&_permuted_input);
113 _memory_group.manage(&_permuted_output);
114
115 // Configure the function to transform the input tensor from NCHW -> NHWC
116 _permute_input.configure(input, &_permuted_input, PermutationVector(2U, 0U, 1U));
117 _permuted_input.info()->set_data_layout(DataLayout::NHWC);
118
119 // Configure the function to transform the weights tensor from IHW -> HWI
120 _permute_weights.configure(weights, &_permuted_weights, PermutationVector(2U, 0U, 1U));
121 _permuted_weights.info()->set_data_layout(DataLayout::NHWC);
122
123 _permuted_output.info()->set_data_layout(DataLayout::NHWC);
124 _permuted_output.info()->set_quantization_info(output->info()->quantization_info());
125
126 // Configure optimized depthwise
127 _dwc_optimized_func.configure(&_permuted_input, &_permuted_weights, biases, &_permuted_output, conv_info, depth_multiplier, act_info_to_use, dilation);
128
129 // Configure the function to transform the convoluted output to ACL's native ordering format NCHW
130 _permuted_output.info()->set_data_layout(DataLayout::NHWC);
131 _permute_output.configure(&_permuted_output, output, PermutationVector(1U, 2U, 0U));
132
133 // Allocate tensors
134 _permuted_input.allocator()->allocate();
135 _permuted_output.allocator()->allocate();
136 }
137 else
138 {
139 _dwc_optimized_func.configure(input, weights, biases, output, conv_info, depth_multiplier, act_info_to_use, dilation);
140 }
Manuel Bottini05069f02019-09-26 17:18:26 +0100141
142 // Configure activation
143 if(_is_activationlayer_enabled)
144 {
145 _activationlayer_function.configure(output, nullptr, act_info);
146 }
147}
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{
158 return validate_arguments_optimized(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
159}
160
Manuel Bottini05069f02019-09-26 17:18:26 +0100161void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::run()
Georgios Pinitas30271c72019-06-24 14:56:34 +0100162{
163 prepare();
164
165 MemoryGroupResourceScope scope_mg(_memory_group);
166
167 // Permute input
168 if(_permute)
169 {
170 _permute_input.run();
171 }
172
Georgios Pinitas7d0adc62020-09-04 15:25:24 +0100173 // Run assembly function
174 _dwc_optimized_func.run();
175
176 // Permute output
177 if(_is_nchw)
178 {
179 _permute_output.run();
180 }
Georgios Pinitas30271c72019-06-24 14:56:34 +0100181
182 // Run activation
183 if(_is_activationlayer_enabled)
184 {
185 _activationlayer_function.run();
186 }
187}
188
Manuel Bottini05069f02019-09-26 17:18:26 +0100189void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerOptimizedInternal::prepare()
Georgios Pinitas30271c72019-06-24 14:56:34 +0100190{
191 if(!_is_prepared)
192 {
193 // Permute weights
194 if(_permute)
195 {
196 _permuted_weights.allocator()->allocate();
197 _permute_weights.run();
198 _original_weights->mark_as_unused();
199 }
200
201 // Prepare optimized function
Georgios Pinitas7d0adc62020-09-04 15:25:24 +0100202 _dwc_optimized_func.prepare();
203 if(!_permuted_weights.is_used())
Georgios Pinitas30271c72019-06-24 14:56:34 +0100204 {
Georgios Pinitas7d0adc62020-09-04 15:25:24 +0100205 _permuted_weights.allocator()->free();
Georgios Pinitas30271c72019-06-24 14:56:34 +0100206 }
207
208 _is_prepared = true;
209 }
210}
211
Manuel Bottini05069f02019-09-26 17:18:26 +0100212NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::NEDepthwiseConvolutionLayerGeneric()
Giorgio Arenad93e2632019-10-15 11:09:33 +0100213 : _depthwise_conv_kernel(), _fill_border(), _permute_input(), _permute_weights(), _permute_output(), _activationlayer_function(), _permuted_input(), _permuted_weights(), _permuted_output(),
214 _is_prepared(false), _is_nchw(false), _is_activationlayer_enabled(false), _original_weights(nullptr)
Michalis Spyroub7b31532017-11-23 12:10:21 +0000215{
216}
217
Manuel Bottini05069f02019-09-26 17:18:26 +0100218void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::configure(ITensor *input, const ITensor *weights, const ITensor *biases, ITensor *output, const PadStrideInfo &conv_info,
219 unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
Michalis Spyroub7b31532017-11-23 12:10:21 +0000220{
Michele Di Giorgioff271922019-07-17 15:59:32 +0100221 ARM_COMPUTE_ERROR_ON_NULLPTR(input, weights, output);
Michele Di Giorgioff271922019-07-17 15:59:32 +0100222 ARM_COMPUTE_ERROR_THROW_ON(NEDepthwiseConvolutionLayer::validate(input->info(), weights->info(), (biases == nullptr) ? nullptr : biases->info(),
223 output->info(), conv_info, depth_multiplier, act_info, dilation));
Michalis Spyroub7b31532017-11-23 12:10:21 +0000224
Giorgio Arenad93e2632019-10-15 11:09:33 +0100225 _is_nchw = input->info()->data_layout() == DataLayout::NCHW;
226 _is_prepared = !_is_nchw;
Giorgio Arena26b22162018-08-13 15:49:49 +0100227
Giorgio Arenad93e2632019-10-15 11:09:33 +0100228 ITensor *input_to_use = input;
229 const ITensor *weights_to_use = weights;
230 ITensor *output_to_use = output;
231 if(_is_nchw)
Giorgio Arena26b22162018-08-13 15:49:49 +0100232 {
Giorgio Arenad93e2632019-10-15 11:09:33 +0100233 _permute_input.configure(input, &_permuted_input, PermutationVector(2U, 0U, 1U));
234 _permuted_input.info()->set_data_layout(DataLayout::NHWC);
235 input_to_use = &_permuted_input;
Giorgio Arena26b22162018-08-13 15:49:49 +0100236
Giorgio Arenad93e2632019-10-15 11:09:33 +0100237 _permute_weights.configure(weights, &_permuted_weights, PermutationVector(2U, 0U, 1U));
238 _permuted_weights.info()->set_data_layout(DataLayout::NHWC);
239 weights_to_use = &_permuted_weights;
Giorgio Arena44f55722019-07-12 14:49:49 +0100240
Giorgio Arenad93e2632019-10-15 11:09:33 +0100241 _permuted_output.allocator()->init(output->info()->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(TensorShape()));
242 output_to_use = &_permuted_output;
Giorgio Arena26b22162018-08-13 15:49:49 +0100243 }
Giorgio Arenad93e2632019-10-15 11:09:33 +0100244 _original_weights = weights_to_use;
Giorgio Arena44f55722019-07-12 14:49:49 +0100245
Giorgio Arenad93e2632019-10-15 11:09:33 +0100246 _depthwise_conv_kernel.configure(input_to_use, weights_to_use, biases, output_to_use, conv_info, depth_multiplier, dilation);
247 _fill_border.configure(input_to_use, _depthwise_conv_kernel.border_size(), BorderMode::CONSTANT, PixelValue(static_cast<uint64_t>(0), input->info()->data_type(), input->info()->quantization_info()));
248
249 if(_is_nchw)
250 {
251 _permute_output.configure(&_permuted_output, output, PermutationVector(1U, 2U, 0U));
252 _permuted_output.info()->set_data_layout(DataLayout::NHWC);
253
254 _permuted_input.allocator()->allocate();
255 _permuted_weights.allocator()->allocate();
256 _permuted_output.allocator()->allocate();
Giorgio Arena26b22162018-08-13 15:49:49 +0100257 }
258
Georgios Pinitas60e98252018-10-22 16:17:20 +0100259 //Configure Activation Layer
260 _is_activationlayer_enabled = act_info.enabled();
Georgios Pinitas60e98252018-10-22 16:17:20 +0100261 if(_is_activationlayer_enabled)
262 {
263 _activationlayer_function.configure(output, nullptr, act_info);
264 }
Michalis Spyroub7b31532017-11-23 12:10:21 +0000265}
266
Manuel Bottini05069f02019-09-26 17:18:26 +0100267Status NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output,
268 const PadStrideInfo &conv_info,
269 unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
Abe Mbise7784c832018-05-31 16:48:41 +0100270{
271 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, weights, output);
Giorgio Arenad93e2632019-10-15 11:09:33 +0100272 if(input->data_layout() == DataLayout::NCHW)
Giorgio Arena26b22162018-08-13 15:49:49 +0100273 {
Giorgio Arena44f55722019-07-12 14:49:49 +0100274 TensorShape permuted_input_shape = input->tensor_shape();
275 TensorShape permuted_weights_shape = weights->tensor_shape();
Giorgio Arenad93e2632019-10-15 11:09:33 +0100276 TensorShape permuted_output_shape = misc::shape_calculator::compute_depthwise_convolution_shape(*input, *weights, conv_info, depth_multiplier, dilation);
277 permute(permuted_input_shape, PermutationVector(2U, 0U, 1U));
278 permute(permuted_weights_shape, PermutationVector(2U, 0U, 1U));
279 permute(permuted_output_shape, PermutationVector(2U, 0U, 1U));
Giorgio Arena44f55722019-07-12 14:49:49 +0100280
Giorgio Arenad93e2632019-10-15 11:09:33 +0100281 const TensorInfo permuted_input = TensorInfo(input->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(permuted_input_shape).set_data_layout(DataLayout::NHWC));
282 const TensorInfo permuted_weights = TensorInfo(weights->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(permuted_weights_shape).set_data_layout(DataLayout::NHWC));
283 const TensorInfo permuted_output = TensorInfo(output->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(permuted_output_shape).set_data_layout(DataLayout::NCHW));
Giorgio Arena44f55722019-07-12 14:49:49 +0100284
Giorgio Arenad93e2632019-10-15 11:09:33 +0100285 ARM_COMPUTE_RETURN_ON_ERROR(NEPermute::validate(input, &permuted_input, PermutationVector(2U, 0U, 1U)));
286 ARM_COMPUTE_RETURN_ON_ERROR(NEPermute::validate(weights, &permuted_weights, PermutationVector(2U, 0U, 1U)));
287 ARM_COMPUTE_RETURN_ON_ERROR(NEPermute::validate(&permuted_output, output, PermutationVector(1U, 2U, 0U)));
Giorgio Arena44f55722019-07-12 14:49:49 +0100288
Giorgio Arenad93e2632019-10-15 11:09:33 +0100289 ARM_COMPUTE_RETURN_ON_ERROR(NEDepthwiseConvolutionLayerNativeKernel::validate(&permuted_input, &permuted_weights, biases, &permuted_output, conv_info, depth_multiplier, dilation));
Giorgio Arena26b22162018-08-13 15:49:49 +0100290 }
Giorgio Arena44f55722019-07-12 14:49:49 +0100291 else
Giorgio Arena26b22162018-08-13 15:49:49 +0100292 {
Gian Marco Iodicebd9097d2019-07-26 15:31:02 +0100293 ARM_COMPUTE_RETURN_ON_ERROR(NEDepthwiseConvolutionLayerNativeKernel::validate(input, weights, biases, output, conv_info, depth_multiplier, dilation));
Abe Mbise7784c832018-05-31 16:48:41 +0100294 }
295
Georgios Pinitas60e98252018-10-22 16:17:20 +0100296 // Validate Activation Layer
297 if(act_info.enabled())
298 {
299 ARM_COMPUTE_RETURN_ON_ERROR(NEActivationLayer::validate(output, nullptr, act_info));
300 }
301
Abe Mbise7784c832018-05-31 16:48:41 +0100302 return Status{};
303}
304
Manuel Bottini05069f02019-09-26 17:18:26 +0100305void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::run()
Michalis Spyroub7b31532017-11-23 12:10:21 +0000306{
Giorgio Arenad93e2632019-10-15 11:09:33 +0100307 if(_is_nchw)
Giorgio Arena26b22162018-08-13 15:49:49 +0100308 {
Giorgio Arena44f55722019-07-12 14:49:49 +0100309 prepare();
Giorgio Arenad93e2632019-10-15 11:09:33 +0100310 _permute_input.run();
Giorgio Arena26b22162018-08-13 15:49:49 +0100311 }
Giorgio Arenad93e2632019-10-15 11:09:33 +0100312
313 NEScheduler::get().schedule(&_fill_border, Window::DimX);
314 NEScheduler::get().schedule(&_depthwise_conv_kernel, Window::DimY);
315
316 if(_is_nchw)
Georgios Pinitasd05dce42018-01-22 16:29:17 +0000317 {
Giorgio Arenad93e2632019-10-15 11:09:33 +0100318 _permute_output.run();
Giorgio Arena26b22162018-08-13 15:49:49 +0100319 }
Georgios Pinitas60e98252018-10-22 16:17:20 +0100320
321 if(_is_activationlayer_enabled)
322 {
323 _activationlayer_function.run();
324 }
Anthony Barbierfb8dda22018-01-30 09:27:05 +0000325}
Georgios Pinitas72219332018-06-05 14:56:06 +0100326
Manuel Bottini05069f02019-09-26 17:18:26 +0100327void NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayerGeneric::prepare()
Georgios Pinitas72219332018-06-05 14:56:06 +0100328{
Giorgio Arenad93e2632019-10-15 11:09:33 +0100329 if(!_is_prepared)
Georgios Pinitas72219332018-06-05 14:56:06 +0100330 {
331 ARM_COMPUTE_ERROR_ON(!_original_weights->is_used());
332
Giorgio Arenad93e2632019-10-15 11:09:33 +0100333 _permute_weights.run();
Georgios Pinitas72219332018-06-05 14:56:06 +0100334 _original_weights->mark_as_unused();
Georgios Pinitas72219332018-06-05 14:56:06 +0100335 _is_prepared = true;
336 }
337}
Manuel Bottini05069f02019-09-26 17:18:26 +0100338
339NEDepthwiseConvolutionLayer::NEDepthwiseConvolutionLayer(std::shared_ptr<IMemoryManager> memory_manager)
340 : _depth_conv_func(DepthwiseConvolutionFunction::GENERIC), _func_optimized(std::move(memory_manager)), _func_generic()
341{
342}
343
344void NEDepthwiseConvolutionLayer::configure(ITensor *input, const ITensor *weights, const ITensor *biases, ITensor *output, const PadStrideInfo &conv_info, unsigned int depth_multiplier,
345 const ActivationLayerInfo &act_info, const Size2D &dilation)
346{
347 _depth_conv_func = get_depthwiseconvolution_function(input->info(), weights->info(), (biases != nullptr) ? biases->info() : nullptr, output->info(), conv_info, depth_multiplier, act_info, dilation);
348 switch(_depth_conv_func)
349 {
350 case DepthwiseConvolutionFunction::OPTIMIZED:
351 _func_optimized.configure(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
352 break;
353 case DepthwiseConvolutionFunction::GENERIC:
354 _func_generic.configure(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
355 break;
356 default:
357 ARM_COMPUTE_ERROR("Unsupported DepthwiseConvolutionFunction");
358 }
359}
360
361Status NEDepthwiseConvolutionLayer::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info,
362 unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
363{
364 DepthwiseConvolutionFunction depth_conv_func = get_depthwiseconvolution_function(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
365 switch(depth_conv_func)
366 {
367 case DepthwiseConvolutionFunction::OPTIMIZED:
Manuel Bottini387259a2020-05-21 17:14:36 +0100368 return NEDepthwiseConvolutionLayerOptimizedInternal::validate(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
Manuel Bottini05069f02019-09-26 17:18:26 +0100369 break;
370 case DepthwiseConvolutionFunction::GENERIC:
371 return NEDepthwiseConvolutionLayerGeneric::validate(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
372 break;
373 default:
374 ARM_COMPUTE_ERROR("Unsupported DepthwiseConvolutionFunction");
375 }
376}
377
378DepthwiseConvolutionFunction NEDepthwiseConvolutionLayer::get_depthwiseconvolution_function(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output,
379 const PadStrideInfo &conv_info,
380 unsigned int depth_multiplier, ActivationLayerInfo act_info, const Size2D &dilation)
381{
Manuel Bottini387259a2020-05-21 17:14:36 +0100382 if(bool(NEDepthwiseConvolutionLayerOptimizedInternal::validate(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation)))
Manuel Bottini05069f02019-09-26 17:18:26 +0100383 {
384 return DepthwiseConvolutionFunction::OPTIMIZED;
385 }
386 else
387 {
388 return DepthwiseConvolutionFunction::GENERIC;
389 }
390}
391
392void NEDepthwiseConvolutionLayer::run()
393{
394 switch(_depth_conv_func)
395 {
396 case DepthwiseConvolutionFunction::OPTIMIZED:
397 _func_optimized.run();
398 break;
399 case DepthwiseConvolutionFunction::GENERIC:
400 _func_generic.run();
401 break;
402 default:
403 ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
404 }
405}
406
407void NEDepthwiseConvolutionLayer::prepare()
408{
409 switch(_depth_conv_func)
410 {
411 case DepthwiseConvolutionFunction::OPTIMIZED:
412 _func_optimized.prepare();
413 break;
414 case DepthwiseConvolutionFunction::GENERIC:
415 _func_generic.prepare();
416 break;
417 default:
418 ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
419 }
420}
Georgios Pinitas47d39dc2019-03-11 14:03:23 +0000421} // namespace arm_compute