Compute Library
 22.11
CpuDepthwiseConv2d.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021-2022 Arm Limited.
3  *
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  */
25 
31 #include "src/common/utils/Log.h"
33 
34 namespace arm_compute
35 {
36 namespace cpu
37 {
38 namespace
39 {
40 Status validate_arguments_optimized(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *dst, const ConvolutionInfo &info)
41 {
42  ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src, weights, dst);
44  if(!is_data_type_quantized_per_channel(weights->data_type()))
45  {
47  }
48  ARM_COMPUTE_RETURN_ERROR_ON(src->data_layout() == DataLayout::UNKNOWN);
49  ARM_COMPUTE_RETURN_ERROR_ON(info.dilation.x() < 1 || info.dilation.y() < 1);
50  const size_t idx_w = get_data_layout_dimension_index(src->data_layout(), DataLayoutDimension::WIDTH);
51  const size_t idx_h = get_data_layout_dimension_index(src->data_layout(), DataLayoutDimension::HEIGHT);
52  ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(idx_w) + (weights->dimension(idx_w) - 1) * (info.dilation.x() - 1) > src->dimension(idx_w) + info.pad_stride_info.pad_left() +
53  info.pad_stride_info.pad_right());
54  ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(idx_h) + (weights->dimension(idx_h) - 1) * (info.dilation.y() - 1) > src->dimension(idx_h) + info.pad_stride_info.pad_top() +
55  info.pad_stride_info.pad_bottom());
56 
57  if(biases != nullptr)
58  {
59  const unsigned int channel_idx = get_data_layout_dimension_index(src->data_layout(), DataLayoutDimension::CHANNEL);
60  ARM_COMPUTE_RETURN_ERROR_ON(biases->num_dimensions() > 1);
61  ARM_COMPUTE_RETURN_ERROR_ON(biases->dimension(0) != weights->dimension(channel_idx));
62  }
63 
65 
66  // Validate Activation Layer
67  if(info.act_info.enabled() && !CpuDepthwiseConv2dAssemblyDispatch::is_activation_supported(info.act_info))
68  {
69  ARM_COMPUTE_RETURN_ON_ERROR(CpuActivation::validate(dst, nullptr, info.act_info));
70  }
71  return Status{};
72 }
73 } // namespace
74 
76  const ITensorInfo *weights,
77  const ITensorInfo *biases,
78  ITensorInfo *dst,
79  const ConvolutionInfo &info)
80 {
81  ARM_COMPUTE_ERROR_ON_NULLPTR(src, weights, dst);
82  // Perform validation step
83  ARM_COMPUTE_ERROR_THROW_ON(CpuDepthwiseConv2dOptimizedInternal::validate(src, weights, (biases == nullptr) ? nullptr : biases,
84  dst, info));
85 
86  _is_quantized = is_data_type_quantized_asymmetric(src->data_type());
87  _has_bias = biases != nullptr;
88  _is_nchw = src->data_layout() == DataLayout::NCHW;
89  _permute = _is_nchw;
90  _is_prepared = false;
91  _are_weights_const = weights->are_values_constant();
92 
93  // Configure pipeline
94  _is_activationlayer_enabled = info.act_info.enabled() && !CpuDepthwiseConv2dAssemblyDispatch::is_activation_supported(info.act_info);
95 
96  _dwc_optimized_func = std::make_unique<CpuDepthwiseConv2dAssemblyDispatch>();
97  if(_is_nchw)
98  {
99  _permute_input = std::make_unique<cpu::CpuPermute>();
100  _permute_weights = std::make_unique<cpu::CpuPermute>();
101  _permute_output = std::make_unique<cpu::CpuPermute>();
102 
103  auto input_perm = std::make_unique<TensorInfo>();
104  auto weights_perm = std::make_unique<TensorInfo>();
105  auto output_perm = std::make_unique<TensorInfo>();
106 
107  // Configure the function to transform the input tensor from NCHW -> NHWC
108  _permute_input->configure(src, input_perm.get(), PermutationVector(2U, 0U, 1U));
109  input_perm->set_data_layout(DataLayout::NHWC);
110 
111  // Configure the function to transform the weights tensor from IHW -> HWI
112  _permute_weights->configure(weights, weights_perm.get(), PermutationVector(2U, 0U, 1U));
113  weights_perm->set_data_layout(DataLayout::NHWC);
114 
115  output_perm->set_data_layout(DataLayout::NHWC);
116  output_perm->set_quantization_info(dst->quantization_info());
117 
118  // Configure optimized depthwise
119  _dwc_optimized_func->configure(input_perm.get(), weights_perm.get(), biases, output_perm.get(), info);
120 
121  // Configure the function to transform the convoluted output to ACL's native ordering format NCHW
122  output_perm->set_data_layout(DataLayout::NHWC);
123  _permute_output->configure(output_perm.get(), dst, PermutationVector(1U, 2U, 0U));
124  }
125  else
126  {
127  _dwc_optimized_func->configure(src, weights, biases, dst, info);
128  }
129 
130  // Configure activation
131  if(_is_activationlayer_enabled)
132  {
133  _activationlayer_function = std::make_unique<cpu::CpuActivation>();
134  _activationlayer_function->configure(dst, nullptr, info.act_info);
135  }
136 }
137 
139  const ITensorInfo *weights,
140  const ITensorInfo *biases,
141  const ITensorInfo *dst,
142  const ConvolutionInfo &info)
143 {
144  return validate_arguments_optimized(src, weights, biases, dst, info);
145 }
146 
148 {
149  ARM_COMPUTE_ERROR_ON_MSG(tensors.empty(), "No inputs provided");
150  prepare(tensors);
151 
152  auto bias = tensors.get_const_tensor(TensorType::ACL_SRC_2);
153  auto dst = tensors.get_tensor(TensorType::ACL_DST_0);
154  auto workspace = tensors.get_tensor(TensorType::ACL_INT_3);
155  auto packed_weights = tensors.get_tensor(TensorType::ACL_INT_4);
156 
157  // Permute input
158  if(_permute)
159  {
160  ITensorPack pack;
161  auto src = tensors.get_const_tensor(TensorType::ACL_SRC_0);
162  auto src_perm = tensors.get_tensor(TensorType::ACL_INT_0);
163  pack.add_tensor(TensorType::ACL_SRC, src);
164  pack.add_tensor(TensorType::ACL_DST, src_perm);
165  _permute_input->run(pack);
166  }
167 
168  // Run assembly function
169  if(_is_nchw)
170  {
171  auto src_perm = tensors.get_tensor(TensorType::ACL_INT_0);
172  auto weights_perm = tensors.get_tensor(TensorType::ACL_INT_1);
173  auto dst_perm = tensors.get_tensor(TensorType::ACL_INT_2);
174 
175  ITensorPack pack;
176  pack.add_tensor(TensorType::ACL_SRC_0, src_perm);
177  pack.add_tensor(TensorType::ACL_SRC_1, weights_perm);
178  pack.add_tensor(TensorType::ACL_SRC_2, bias);
179  pack.add_tensor(TensorType::ACL_INT_0, workspace);
180  pack.add_tensor(TensorType::ACL_INT_1, packed_weights);
181  pack.add_tensor(TensorType::ACL_DST, dst_perm);
182  _dwc_optimized_func->run(pack);
183  }
184  else
185  {
186  auto src = tensors.get_tensor(TensorType::ACL_SRC_0);
187  auto weights = tensors.get_tensor(TensorType::ACL_SRC_1);
188  auto dst = tensors.get_tensor(TensorType::ACL_DST);
189 
190  ITensorPack pack;
192  pack.add_tensor(TensorType::ACL_SRC_1, weights);
193  pack.add_tensor(TensorType::ACL_SRC_2, bias);
194  pack.add_tensor(TensorType::ACL_INT_0, workspace);
195  pack.add_tensor(TensorType::ACL_INT_1, packed_weights);
196  pack.add_tensor(TensorType::ACL_DST, dst);
197  _dwc_optimized_func->run(pack);
198  }
199 
200  // Permute output
201  if(_is_nchw)
202  {
203  ITensorPack pack;
204  auto dst_perm = tensors.get_tensor(TensorType::ACL_INT_2);
205  pack.add_tensor(TensorType::ACL_SRC, dst_perm);
206  pack.add_tensor(TensorType::ACL_DST, dst);
207  _permute_output->run(pack);
208  }
209 
210  // Run activation
211  if(_is_activationlayer_enabled)
212  {
213  ITensorPack pack;
214  pack.add_tensor(TensorType::ACL_SRC, dst);
215  pack.add_tensor(TensorType::ACL_DST, dst);
216  _activationlayer_function->run(pack);
217  }
218 }
219 
220 void CpuDepthwiseConv2d::CpuDepthwiseConv2dOptimizedInternal::prepare(ITensorPack &tensors)
221 {
222  // if weights are not constant then we need to repack so that weights
223  // can be updated in-place
224  if(!_are_weights_const)
225  {
226  auto weights = tensors.get_const_tensor(TensorType::ACL_SRC_1);
227  auto bias = tensors.get_const_tensor(TensorType::ACL_SRC_2);
228  auto packed_weights = tensors.get_tensor(TensorType::ACL_INT_4);
229 
230  ITensorPack pack_opt;
231  pack_opt.add_tensor(TensorType::ACL_SRC_1, weights);
232  pack_opt.add_tensor(TensorType::ACL_SRC_2, bias);
233  pack_opt.add_tensor(TensorType::ACL_INT_1, packed_weights);
234 
235  // Prepare optimized function
236  _dwc_optimized_func->prepare(pack_opt);
237 
238  return;
239  }
240 
241  if(!_is_prepared)
242  {
243  auto weights = tensors.get_const_tensor(TensorType::ACL_SRC_1);
244  auto bias = tensors.get_const_tensor(TensorType::ACL_SRC_2);
245  auto packed_weights = tensors.get_tensor(TensorType::ACL_INT_4);
246 
247  // Permute weights
248  if(_permute)
249  {
250  auto permuted_weights = tensors.get_tensor(TensorType::ACL_INT_1);
251 
252  ITensorPack pack;
253  pack.add_tensor(TensorType::ACL_SRC, weights);
254  pack.add_tensor(TensorType::ACL_DST, permuted_weights);
255  _permute_weights->run(pack);
256 
257  weights->mark_as_unused();
258 
259  ITensorPack pack_opt;
260  pack_opt.add_const_tensor(TensorType::ACL_SRC_1, permuted_weights);
261  pack_opt.add_tensor(TensorType::ACL_SRC_2, bias);
262  pack_opt.add_tensor(TensorType::ACL_INT_1, packed_weights);
263 
264  // Prepare optimized function
265  _dwc_optimized_func->prepare(pack_opt);
266  }
267  else
268  {
269  ITensorPack pack_opt;
270  pack_opt.add_tensor(TensorType::ACL_SRC_1, weights);
271  pack_opt.add_tensor(TensorType::ACL_SRC_2, bias);
272  pack_opt.add_tensor(TensorType::ACL_INT_1, packed_weights);
273 
274  // Prepare optimized function
275  _dwc_optimized_func->prepare(pack_opt);
276  }
277 
278  _is_prepared = true;
279  }
280 }
281 
282 void CpuDepthwiseConv2d::CpuDepthwiseConv2dGeneric::configure(ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, ITensorInfo *dst, const ConvolutionInfo &info)
283 {
284  ARM_COMPUTE_ERROR_ON_NULLPTR(src, weights, dst);
285  ARM_COMPUTE_ERROR_THROW_ON(CpuDepthwiseConv2d::validate(src, weights, (biases == nullptr) ? nullptr : biases,
286  dst, info));
287 
288  _is_nchw = src->data_layout() == DataLayout::NCHW;
289  _is_prepared = !_is_nchw;
290 
291  ITensorInfo *input_to_use = src;
292  const ITensorInfo *weights_to_use = weights;
293  ITensorInfo *output_to_use = dst;
294 
295  auto input_perm = std::make_unique<TensorInfo>();
296  auto weights_perm = std::make_unique<TensorInfo>();
297  auto output_perm = std::make_unique<TensorInfo>(dst->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(TensorShape()));
298 
299  if(_is_nchw)
300  {
301  _permute_input = std::make_unique<cpu::CpuPermute>();
302  _permute_weights = std::make_unique<cpu::CpuPermute>();
303 
304  _permute_input->configure(src, input_perm.get(), PermutationVector(2U, 0U, 1U));
305  input_perm->set_data_layout(DataLayout::NHWC);
306  input_to_use = input_perm.get();
307 
308  _permute_weights->configure(weights, weights_perm.get(), PermutationVector(2U, 0U, 1U));
309  weights_perm->set_data_layout(DataLayout::NHWC);
310  weights_to_use = weights_perm.get();
311 
312  output_to_use = output_perm.get();
313  }
314 
315  _depthwise_conv_kernel = std::make_unique<cpu::kernels::CpuDepthwiseConv2dNativeKernel>();
316  _depthwise_conv_kernel->configure(input_to_use, weights_to_use, biases, output_to_use, info);
317 
318  if(_is_nchw)
319  {
320  _permute_output = std::make_unique<cpu::CpuPermute>();
321  _permute_output->configure(output_perm.get(), dst, PermutationVector(1U, 2U, 0U));
322  output_perm->set_data_layout(DataLayout::NHWC);
323  }
324 
325  //Configure Activation Layer
326  _is_activationlayer_enabled = info.act_info.enabled();
327  if(_is_activationlayer_enabled)
328  {
329  _activationlayer_function = std::make_unique<cpu::CpuActivation>();
330  _activationlayer_function->configure(dst, nullptr, info.act_info);
331  }
332 }
333 
334 Status CpuDepthwiseConv2d::CpuDepthwiseConv2dGeneric::validate(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *dst,
335  const ConvolutionInfo &info)
336 {
337  ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src, weights, dst);
338  if(src->data_layout() == DataLayout::NCHW)
339  {
340  TensorShape permuted_input_shape = src->tensor_shape();
341  TensorShape permuted_weights_shape = weights->tensor_shape();
342  TensorShape permuted_output_shape = misc::shape_calculator::compute_depthwise_convolution_shape(*src, *weights, info);
343  permute(permuted_input_shape, PermutationVector(2U, 0U, 1U));
344  permute(permuted_weights_shape, PermutationVector(2U, 0U, 1U));
345  permute(permuted_output_shape, PermutationVector(2U, 0U, 1U));
346 
347  const TensorInfo permuted_input = TensorInfo(src->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(permuted_input_shape).set_data_layout(DataLayout::NHWC));
348  const TensorInfo permuted_weights = TensorInfo(weights->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(permuted_weights_shape).set_data_layout(DataLayout::NHWC));
349  const TensorInfo permuted_output = TensorInfo(dst->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(permuted_output_shape).set_data_layout(DataLayout::NCHW));
350 
351  ARM_COMPUTE_RETURN_ON_ERROR(CpuPermute::validate(src, &permuted_input, PermutationVector(2U, 0U, 1U)));
352  ARM_COMPUTE_RETURN_ON_ERROR(CpuPermute::validate(weights, &permuted_weights, PermutationVector(2U, 0U, 1U)));
353  ARM_COMPUTE_RETURN_ON_ERROR(CpuPermute::validate(&permuted_output, dst, PermutationVector(1U, 2U, 0U)));
354 
355  ARM_COMPUTE_RETURN_ON_ERROR(cpu::kernels::CpuDepthwiseConv2dNativeKernel::validate(&permuted_input, &permuted_weights, biases, &permuted_output, info));
356  }
357  else
358  {
360  }
361 
362  // Validate Activation Layer
363  if(info.act_info.enabled() && !CpuDepthwiseConv2dAssemblyDispatch::is_activation_supported(info.act_info))
364  {
365  ARM_COMPUTE_RETURN_ON_ERROR(CpuActivation::validate(dst, nullptr, info.act_info));
366  }
367 
368  return Status{};
369 }
370 
372 {
373  auto src = tensors.get_const_tensor(TensorType::ACL_SRC_0);
374  auto weights = tensors.get_const_tensor(TensorType::ACL_SRC_1);
375  auto biases = tensors.get_const_tensor(TensorType::ACL_SRC_2);
376  auto dst = tensors.get_tensor(TensorType::ACL_DST_0);
377 
378  if(_is_nchw)
379  {
380  prepare(tensors);
381  auto src_perm = tensors.get_tensor(TensorType::ACL_INT_0);
382  auto weights_perm = tensors.get_tensor(TensorType::ACL_INT_1);
383  auto dst_perm = tensors.get_tensor(TensorType::ACL_INT_2);
384 
385  ITensorPack pack;
386  pack.add_tensor(TensorType::ACL_SRC, src);
387  pack.add_tensor(TensorType::ACL_DST, src_perm);
388  _permute_input->run(pack);
389 
390  ITensorPack pack_depth;
391  pack_depth.add_const_tensor(TensorType::ACL_SRC_0, src_perm);
392  pack_depth.add_const_tensor(TensorType::ACL_SRC_1, weights_perm);
393  pack_depth.add_tensor(TensorType::ACL_SRC_2, biases);
394  pack_depth.add_tensor(TensorType::ACL_DST, dst_perm);
395  NEScheduler::get().schedule_op(_depthwise_conv_kernel.get(), Window::DimY, _depthwise_conv_kernel->window(), pack_depth);
396  }
397  else
398  {
399  ITensorPack pack_depth;
400  pack_depth.add_tensor(TensorType::ACL_SRC_0, src);
401  pack_depth.add_tensor(TensorType::ACL_SRC_1, weights);
402  pack_depth.add_tensor(TensorType::ACL_SRC_2, biases);
403  pack_depth.add_tensor(TensorType::ACL_DST, dst);
404  NEScheduler::get().schedule_op(_depthwise_conv_kernel.get(), Window::DimY, _depthwise_conv_kernel->window(), pack_depth);
405  }
406 
407  if(_is_nchw)
408  {
409  ITensorPack pack;
410  auto dst_perm = tensors.get_tensor(TensorType::ACL_INT_2);
411  pack.add_tensor(TensorType::ACL_SRC, dst_perm);
412  pack.add_tensor(TensorType::ACL_DST, dst);
413  _permute_output->run(pack);
414  }
415 
416  if(_is_activationlayer_enabled)
417  {
418  ITensorPack pack;
419  pack.add_tensor(TensorType::ACL_SRC, dst);
420  pack.add_tensor(TensorType::ACL_DST, dst);
421  _activationlayer_function->run(pack);
422  }
423 }
424 
425 void CpuDepthwiseConv2d::CpuDepthwiseConv2dGeneric::prepare(ITensorPack &tensors)
426 {
427  if(!_is_prepared)
428  {
429  auto weights = tensors.get_const_tensor(TensorType::ACL_SRC_1);
430  auto weights_perm = tensors.get_tensor(TensorType::ACL_INT_1);
431 
432  ARM_COMPUTE_ERROR_ON(!weights->is_used());
433 
434  ITensorPack pack;
435  pack.add_tensor(TensorType::ACL_SRC, weights);
436  pack.add_tensor(TensorType::ACL_DST, weights_perm);
437 
438  _permute_weights->run(pack);
439  weights->mark_as_unused();
440  _is_prepared = true;
441  }
442 }
443 
444 void CpuDepthwiseConv2d::configure(ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, ITensorInfo *dst, const ConvolutionInfo &info)
445 {
446  ARM_COMPUTE_LOG_PARAMS(src, weights, biases, dst, info);
447 
448  _depth_conv_func = get_depthwiseconvolution_function(src, weights, (biases != nullptr) ? biases : nullptr, dst, info);
449  switch(_depth_conv_func)
450  {
452  _func_optimized.configure(src, weights, biases, dst, info);
453  break;
455  _func_generic.configure(src, weights, biases, dst, info);
456  break;
457  default:
458  ARM_COMPUTE_ERROR("Unsupported DepthwiseConvolutionFunction");
459  }
460 }
461 
462 Status CpuDepthwiseConv2d::validate(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *dst, const ConvolutionInfo &info)
463 {
464  DepthwiseConvolutionFunction depth_conv_func = get_depthwiseconvolution_function(src, weights, biases, dst, info);
465  switch(depth_conv_func)
466  {
468  return CpuDepthwiseConv2dOptimizedInternal::validate(src, weights, biases, dst, info);
469  break;
471  return CpuDepthwiseConv2dGeneric::validate(src, weights, biases, dst, info);
472  break;
473  default:
474  ARM_COMPUTE_ERROR("Unsupported DepthwiseConvolutionFunction");
475  }
476 }
477 
479  const ConvolutionInfo &info)
480 {
481  if(bool(CpuDepthwiseConv2dOptimizedInternal::validate(src, weights, biases, dst, info)))
482  {
484  }
485  else
486  {
488  }
489 }
490 
492 {
493  switch(_depth_conv_func)
494  {
496  _func_optimized.run(tensors);
497  break;
499  _func_generic.run(tensors);
500  break;
501  default:
502  ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
503  }
504 }
505 
507 {
508  switch(_depth_conv_func)
509  {
511  _func_optimized.prepare(tensors);
512  break;
514  _func_generic.prepare(tensors);
515  break;
516  default:
517  ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
518  }
519 }
520 } // namespace cpu
521 } // namespace arm_compute
Status validate(const OperatorGraph &op_graph)
Return the validity of op_graph, usually after performing an operation (e.g.
static Status validate(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *dst, const ConvolutionInfo &info)
Static function to check if given info will lead to a valid configuration.
DepthwiseConvolutionFunction
Available DepthwiseConvolutionFunction.
Definition: Types.h:144
TensorShape compute_depthwise_convolution_shape(const ITensorInfo &input, const ITensorInfo &weights, const ConvolutionInfo &info)
Calculate the depthwise convolution output shape of a tensor.
#define ARM_COMPUTE_ERROR(msg)
Print the given message then throw an std::runtime_error.
Definition: Error.h:352
static DepthwiseConvolutionFunction get_depthwiseconvolution_function(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *dst, const ConvolutionInfo &info)
Static function to choose the best depthwise convolution function for CpuDepthwiseConv2d.
void prepare(ITensorPack &tensors) override
Prepare the function for executing.
#define ARM_COMPUTE_RETURN_ON_ERROR(status)
Checks if a status contains an error and returns it.
Definition: Error.h:204
virtual void schedule_op(ICPPKernel *kernel, const Hints &hints, const Window &window, ITensorPack &tensors)=0
Runs the kernel in the same thread as the caller synchronously.
1 channel, 1 F32 per channel
Strides PermutationVector
Permutation vector.
Definition: Types.h:51
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:466
Store the tensor&#39;s metadata.
Definition: ITensorInfo.h:40
#define ARM_COMPUTE_ERROR_THROW_ON(status)
Definition: Error.h:455
Status class.
Definition: Error.h:52
#define ARM_COMPUTE_RETURN_ERROR_ON(cond)
If the condition is true, an error is returned.
Definition: Error.h:296
void run(ITensorPack &tensors) override
Run the kernels contained in the function.
SimpleTensor< float > src
Definition: DFT.cpp:155
Copyright (c) 2017-2022 Arm Limited.
1 channel, 1 F16 per channel
void configure(ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, ITensorInfo *dst, const ConvolutionInfo &info)
Initialize the function&#39;s source, destination, weights and convolution information.
#define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...)
Definition: Validate.h:159
void permute(Dimensions< T > &dimensions, const PermutationVector &perm)
Permutes given Dimensions according to a permutation vector.
Definition: Helpers.h:125
const ITensor * get_const_tensor(int id) const
Get constant tensor of a given id.
Definition: ITensorPack.cpp:54
static bool is_activation_supported(const ActivationLayerInfo &activation)
Checks if activation is supported by the assembly kernels.
bool is_data_type_quantized_per_channel(DataType dt)
Check if a given data type is of per channel type.
Definition: Utils.h:1107
quantized, asymmetric fixed-point 8-bit number unsigned
#define ARM_COMPUTE_ERROR_ON_MSG(cond, msg)
Definition: Error.h:456
static Status validate(const ITensorInfo *src, const ITensorInfo *dst, const PermutationVector &perm)
Static function to check if given info will lead to a valid configuration.
Definition: CpuPermute.cpp:42
Num samples, channels, height, width.
bool is_data_type_quantized_asymmetric(DataType dt)
Check if a given data type is of asymmetric quantized type.
Definition: Utils.h:1052
static constexpr size_t DimY
Alias for dimension 1 also known as Y dimension.
Definition: Window.h:45
ScaleKernelInfo info(interpolation_policy, default_border_mode, PixelValue(), sampling_policy, false)
ITensor * get_tensor(int id)
Get tensor of a given id from the pac.
Definition: ITensorPack.cpp:64
static Status validate(const ITensorInfo *input, const ITensorInfo *output, const ActivationLayerInfo &act_info)
Static function to check if given info will lead to a valid configuration.
size_t get_data_layout_dimension_index(const DataLayout &data_layout, const DataLayoutDimension &data_layout_dimension)
Get the index of the given dimension.
Definition: Helpers.inl:193
#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...)
Definition: Validate.h:541
Num samples, height, width, channels.
#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c,...)
Definition: Validate.h:788
Tensor packing service.
Definition: ITensorPack.h:39
#define ARM_COMPUTE_LOG_PARAMS(...)
#define ARM_COMPUTE_ERROR_ON_NULLPTR(...)
Definition: Validate.h:157
static Status validate(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *dst, const ConvolutionInfo &info)
Static function to check if given info will lead to a valid configuration.
quantized, asymmetric fixed-point 8-bit number signed
im2col_func configure(src_target.info(), dst_target.info(), spatial_kernel, conv_info, has_bias)
static Status validate(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *bias, const ITensorInfo *dst, const ConvolutionInfo &info)
Static function to check if given info will lead to a valid configuration.
void add_tensor(int id, ITensor *tensor)
Add tensor to the pack.
Definition: ITensorPack.cpp:39
static IScheduler & get()
Access the scheduler singleton.
Definition: Scheduler.cpp:94
const int32_t * bias