Compute Library
 19.08
NEGEMMConvolutionLayer Class Reference

Basic function to compute the convolution layer. More...

#include <NEGEMMConvolutionLayer.h>

Collaboration diagram for NEGEMMConvolutionLayer:
[legend]

Public Member Functions

 NEGEMMConvolutionLayer (const std::shared_ptr< IMemoryManager > &memory_manager=nullptr)
 Constructor. More...
 
 NEGEMMConvolutionLayer (const NEGEMMConvolutionLayer &)=delete
 Prevent instances of this class from being copied (As this class contains pointers) More...
 
 NEGEMMConvolutionLayer (NEGEMMConvolutionLayer &&)=default
 Default move constructor. More...
 
NEGEMMConvolutionLayeroperator= (const NEGEMMConvolutionLayer &)=delete
 Prevent instances of this class from being copied (As this class contains pointers) More...
 
NEGEMMConvolutionLayeroperator= (NEGEMMConvolutionLayer &&)=default
 Default move assignment operator. More...
 
void configure (const ITensor *input, const ITensor *weights, const ITensor *biases, ITensor *output, const PadStrideInfo &conv_info, const WeightsInfo &weights_info=WeightsInfo(), const Size2D &dilation=Size2D(1U, 1U), const ActivationLayerInfo &act_info=ActivationLayerInfo(), unsigned int num_groups=1)
 Set the input and output tensors. More...
 
void run () override
 Run the kernels contained in the function. More...
 
void prepare () override
 Prepare the function for executing. More...
 
- Public Member Functions inherited from IFunction
virtual ~IFunction ()=default
 Destructor. More...
 

Static Public Member Functions

static Status validate (const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info, const WeightsInfo &weights_info=WeightsInfo(), const Size2D &dilation=Size2D(1U, 1U), const ActivationLayerInfo &act_info=ActivationLayerInfo(), unsigned int num_groups=1)
 Static function to check if given info will lead to a valid configuration of NEGEMMConvolutionLayer. More...
 

Detailed Description

Basic function to compute the convolution layer.

This function calls the following NEON kernels/functions:

  1. NEIm2ColKernel
  2. NEGEMM (if the data type is FP32 or FP16)
  3. NEGEMMLowpMatrixMultiplyCore (if the data type is QASYMM8)
  4. NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPoint (if the data type is QASYMM8)
  5. NEArithmeticAdditionKernel (if biases != nullptr and we have a 1x1 convolution with the NHWC data layout)
  6. NECol2ImKernel (if NCHW data layout)

Definition at line 91 of file NEGEMMConvolutionLayer.h.

Constructor & Destructor Documentation

◆ NEGEMMConvolutionLayer() [1/3]

NEGEMMConvolutionLayer ( const std::shared_ptr< IMemoryManager > &  memory_manager = nullptr)

Constructor.

Definition at line 92 of file NEGEMMConvolutionLayer.cpp.

93  : _memory_group(memory_manager), _reshape_weights(), _im2col_kernel(), _mm_gemm(memory_manager), _mm_gemmlowp(memory_manager), _col2im_kernel(), _activationlayer_function(), _add_bias_kernel(),
94  _reshape_layer(), _original_weights(nullptr), _im2col_output(), _weights_reshaped(), _gemm_output(), _tmp_output(), _data_layout(DataLayout::NCHW), _append_bias(false), _skip_im2col(false),
95  _skip_col2im(false), _is_quantized(false), _is_activationlayer_enabled(false), _is_prepared(false)
96 {
97 }
Num samples, channels, height, width.

References arm_compute::NCHW.

◆ NEGEMMConvolutionLayer() [2/3]

Prevent instances of this class from being copied (As this class contains pointers)

◆ NEGEMMConvolutionLayer() [3/3]

Default move constructor.

Member Function Documentation

◆ configure()

void configure ( const ITensor input,
const ITensor weights,
const ITensor biases,
ITensor output,
const PadStrideInfo conv_info,
const WeightsInfo weights_info = WeightsInfo(),
const Size2D dilation = Size2D(1U, 1U),
const ActivationLayerInfo act_info = ActivationLayerInfo(),
unsigned int  num_groups = 1 
)

Set the input and output tensors.

Parameters
[in]inputSource tensor. 3 lower dimensions represent a single input [width, height, IFM], while every optional dimension from 4 and above represent a batch of inputs. Data types supported: QASYMM8/F32.
[in]weightsWeights tensor. Weights are 4D tensor with dimensions [kernel_x, kernel_y, IFM, OFM]. Data type supported: Same as input.
[in]biasesBiases tensor. Shared biases supported. Biases are 1D tensor with dimensions [OFM]. Data type supported: Should match input data type, except for input of QASYMM8 type where biases should be of S32 type.
[out]outputDestination tensor. 3 lower dimensions represent a single output [width, height, OFM], while the rest represent batch of outputs. Data types supported: Same as input.
[in]conv_infoContains padding and stride information described in PadStrideInfo.
[in]weights_infoSpecifies if the weights tensor has been reshaped with NEWeightsReshapeKernel. If this is not part of the fully connected layer the weights tensor has also been transposed with NEGEMMTranspose1xWKernel. Data type supported: Same as input.
[in]dilation(Optional) Dilation, in elements, across x and y. Defaults to (1, 1).
[in]act_info(Optional) Activation layer information in case of a fused activation. Only RELU, BOUNDED_RELU and LU_BOUNDED_RELU supported.
[in]num_groups(Optional) Number of groups when performing a grouped convolution. num_groups != 1 is not supported

Definition at line 241 of file NEGEMMConvolutionLayer.cpp.

243 {
244  ARM_COMPUTE_ERROR_ON_NULLPTR(input, weights, output);
247  weights->info(),
248  biases != nullptr ? biases->info() : nullptr,
249  output->info(),
250  conv_info,
251  weights_info,
252  dilation,
253  act_info,
254  num_groups));
255 
256  const DataType data_type = input->info()->data_type();
257  const DataLayout data_layout = input->info()->data_layout();
261 
262  const unsigned int kernel_width = weights->info()->dimension(idx_width);
263  const unsigned int kernel_height = weights->info()->dimension(idx_height);
264 
265  _is_prepared = weights_info.retain_internal_weights();
266  _original_weights = weights;
267  _is_quantized = is_data_type_quantized_asymmetric(input->info()->data_type());
268  _data_layout = data_layout;
269  _skip_im2col = (data_layout == DataLayout::NHWC && kernel_width == 1 && kernel_height == 1 && conv_info.stride().first == 1 && conv_info.stride().second == 1);
270  _append_bias = (biases != nullptr) && (!_is_quantized);
271  _is_activationlayer_enabled = act_info.enabled();
272 
273  const ITensor *gemm_input_to_use = input;
274  ITensor *gemm_output_to_use = output;
275 
276  // Get convolved dimensions
277  unsigned int conv_w = 0;
278  unsigned int conv_h = 0;
279  std::tie(conv_w, conv_h) = scaled_dimensions(input->info()->dimension(idx_width),
280  input->info()->dimension(idx_height),
281  kernel_width,
282  kernel_height,
283  conv_info,
284  dilation);
285 
286  // Check if GEMM3D is supported
288  {
289  _skip_col2im = bool(validate_gemm3d(input->info(), act_info, conv_h, true));
290  // If not supported, we need to perform im2col and col2im (or reshape layer)
291  if(!_skip_col2im)
292  {
293  _skip_im2col = false;
294  }
295  }
296  else
297  {
298  _skip_col2im = false;
299  }
300 
301  const ITensor *biases_to_use = (_append_bias && !_skip_im2col) ? biases : nullptr;
302 
303  // Get parameters from conv_info
304  unsigned int stride_x = 0;
305  unsigned int stride_y = 0;
306  std::tie(stride_x, stride_y) = conv_info.stride();
307 
308  unsigned int mat_weights_cols = weights->info()->dimension(idx_kernels);
309 
310  // _weights_reshaped will be auto configured in the kernel.
311  // Just append biases and do not transpose 1xW as it will be reshaped in NEGEMM
312  _reshape_weights.configure(weights, biases_to_use, &_weights_reshaped);
313 
314  // Create tensor to store im2col reshaped inputs
315  if(!_skip_im2col)
316  {
317  _memory_group.manage(&_im2col_output);
318 
319  // Configure
320  _im2col_kernel.configure(input, &_im2col_output, Size2D(kernel_width, kernel_height), conv_info, _append_bias, dilation);
321 
322  // Update GEMM input
323  gemm_input_to_use = &_im2col_output;
324  }
325  else if(_append_bias)
326  {
327  // Configure add bias kernel
328  _add_bias_kernel.configure(output, biases, output, ConvertPolicy::SATURATE);
329  }
330 
331  // Create temporary GEMM output tensor in case we cannot skip col2im
332  if(!_skip_col2im)
333  {
334  TensorShape shape_gemm;
335 
336  // Calculate GEMM output shape
337  shape_gemm = _im2col_output.info()->tensor_shape();
338  shape_gemm.set(0, mat_weights_cols);
339  shape_gemm.set(1, conv_w * conv_h);
340 
341  // FIXME: input->clone() doesn't work with subtensors for grouped convolutions.
342  TensorInfo info_gemm(shape_gemm, 1, data_type);
343  info_gemm.set_quantization_info(output->info()->quantization_info()).set_data_layout(input->info()->data_layout());
344  _gemm_output.allocator()->init(info_gemm);
345  _memory_group.manage(&_gemm_output);
346 
347  // Update GEMM output
348  gemm_output_to_use = &_gemm_output;
349  }
350 
351  // Configure GEMM
352  // In case we need to skip col2im, GEMM3D (gemm_3d_depth != 0) must be called in order to avoid reshaping the output matrix
353  const unsigned int gemm_3d_depth = _skip_col2im ? conv_h : 0;
354  configure_mm(gemm_input_to_use, &_weights_reshaped, biases, gemm_output_to_use, act_info, gemm_3d_depth);
355 
356  if(!_skip_im2col)
357  {
358  _im2col_output.allocator()->allocate();
359  }
360 
361  if(!_skip_col2im)
362  {
363  if(_data_layout == DataLayout::NCHW)
364  {
365  // Configure col2im
366  _col2im_kernel.configure(gemm_output_to_use, output, Size2D(conv_w, conv_h));
367  }
368  else
369  {
370  // Configure reshape layer
371  _reshape_layer.configure(gemm_output_to_use, output);
372  }
373  }
374 
375  if(_is_quantized && !_skip_col2im)
376  {
377  _tmp_output.allocator()->allocate();
378  }
379 
380  if(!_skip_col2im || _is_quantized)
381  {
382  _gemm_output.allocator()->allocate();
383  }
384 
385  ARM_COMPUTE_ERROR_ON_MSG((output->info()->dimension(idx_width) != conv_w) || (output->info()->dimension(idx_height) != conv_h),
386  "Output shape does not match the expected one");
387 
388  // Configure Activation Layer
389  if(_is_activationlayer_enabled)
390  {
391  _activationlayer_function.configure(output, nullptr, act_info);
392  }
393 
395 }
Shape of a tensor.
Definition: TensorShape.h:39
const DataLayout data_layout
Definition: Im2Col.cpp:146
TensorInfo * info() const override
Interface to be implemented by the child class to return the tensor's metadata.
Definition: CLTensor.cpp:35
void init(const TensorAllocator &allocator, const Coordinates &coords, TensorInfo &sub_info)
Shares the same backing memory with another tensor allocator, while the tensor info might be differen...
virtual size_t dimension(size_t index) const =0
Return the size of the requested dimension.
std::pair< unsigned int, unsigned int > scaled_dimensions(unsigned int width, unsigned int height, unsigned int kernel_width, unsigned int kernel_height, const PadStrideInfo &pad_stride_info, const Size2D &dilation=Size2D(1U, 1U))
Returns expected width and height of output scaled tensor depending on dimensions rounding mode.
Definition: Utils.cpp:387
size_t dimension(size_t index) const override
Return the size of the requested dimension.
Definition: TensorInfo.h:223
virtual DataType data_type() const =0
Data type used for each element of the tensor.
void configure(const ITensor *input1, const ITensor *input2, ITensor *output, ConvertPolicy policy)
Initialise the kernel's input, output and border mode.
#define ARM_COMPUTE_ERROR_THROW_ON(status)
Definition: Error.h:327
Interface for NEON tensor.
Definition: ITensor.h:36
static Status validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info, const WeightsInfo &weights_info=WeightsInfo(), const Size2D &dilation=Size2D(1U, 1U), const ActivationLayerInfo &act_info=ActivationLayerInfo(), unsigned int num_groups=1)
Static function to check if given info will lead to a valid configuration of NEGEMMConvolutionLayer.
void configure(const ITensor *input, ITensor *output, const Size2D &convolved_dims)
Set the input and output of the kernel.
TensorAllocator * allocator()
Return a pointer to the tensor's allocator.
Definition: Tensor.cpp:48
ITensorInfo * info() const override
Interface to be implemented by the child class to return the tensor's metadata.
Definition: Tensor.cpp:33
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:160
void manage(TensorType *obj)
Sets a object to be managed by the given memory group.
virtual const TensorShape & tensor_shape() const =0
Size for each dimension of the tensor.
const unsigned int num_groups
Definition: Im2Col.cpp:148
void allocate() override
Allocate size specified by TensorInfo of CPU memory.
virtual ITensorInfo * info() const =0
Interface to be implemented by the child class to return the tensor's metadata.
virtual QuantizationInfo quantization_info() const =0
Get the quantization settings (scale and offset) of the tensor.
Num samples, channels, height, width.
src_info set_data_layout(data_layout)
bool is_data_type_quantized_asymmetric(DataType dt)
Check if a given data type is of asymmetric quantized type.
Definition: Utils.h:1030
#define ARM_COMPUTE_ERROR_ON_NULLPTR(...)
Definition: Validate.h:161
Class for specifying the size of an image or rectangle.
Definition: Size2D.h:34
Num samples, height, width, channels.
void configure(ITensor *input, ITensor *output, ActivationLayerInfo activation_info)
Set the input and output tensor.
void configure(const ITensor *input, ITensor *output)
Initialise the kernel's inputs and outputs.
void configure(const ITensor *input, ITensor *output, const Size2D &kernel_dims, const PadStrideInfo &conv_info, bool has_bias, const Size2D &dilation=Size2D(1U, 1U), unsigned int num_groups=1)
Set the input and output of the kernel.
TensorShape & set(size_t dimension, size_t value, bool apply_dim_correction=true)
Accessor to set the value of one of the dimensions.
Definition: TensorShape.h:78
Store the tensor's metadata.
Definition: TensorInfo.h:45
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:326
void configure(const ITensor *weights, const ITensor *biases, ITensor *output)
Set the input and output tensors.
DataType
Available data types.
Definition: Types.h:74
DataLayout
[DataLayout enum definition]
Definition: Types.h:114
virtual DataLayout data_layout() const =0
Get the data layout of the tensor.
#define ARM_COMPUTE_ERROR_ON_MSG(cond,...)
Definition: Error.h:328

References arm_compute::test::validation::act_info, TensorAllocator::allocate(), Tensor::allocator(), ARM_COMPUTE_ERROR_ON_MSG, ARM_COMPUTE_ERROR_ON_NULLPTR, ARM_COMPUTE_ERROR_THROW_ON, ARM_COMPUTE_UNUSED, arm_compute::BATCHES, NEReshapeLayer::configure(), NEActivationLayer::configure(), NEConvolutionLayerReshapeWeights::configure(), NEArithmeticAdditionKernel::configure(), NECol2ImKernel::configure(), NEIm2ColKernel::configure(), arm_compute::test::validation::conv_info, arm_compute::test::validation::data_layout, ITensorInfo::data_layout(), arm_compute::test::validation::data_type, ITensorInfo::data_type(), arm_compute::test::validation::dilation, ITensorInfo::dimension(), TensorInfo::dimension(), arm_compute::get_data_layout_dimension_index(), arm_compute::HEIGHT, ITensor::info(), Tensor::info(), CLTensor::info(), TensorAllocator::init(), arm_compute::is_data_type_quantized_asymmetric(), MemoryGroupBase< TensorType >::manage(), arm_compute::NCHW, arm_compute::NHWC, arm_compute::test::validation::num_groups, ITensorInfo::quantization_info(), arm_compute::SATURATE, arm_compute::scaled_dimensions(), TensorShape::set(), arm_compute::test::validation::set_data_layout(), TensorInfo::set_quantization_info(), ITensorInfo::tensor_shape(), NEGEMMConvolutionLayer::validate(), arm_compute::test::validation::weights, arm_compute::test::validation::weights_info, and arm_compute::WIDTH.

◆ operator=() [1/2]

NEGEMMConvolutionLayer& operator= ( const NEGEMMConvolutionLayer )
delete

Prevent instances of this class from being copied (As this class contains pointers)

◆ operator=() [2/2]

NEGEMMConvolutionLayer& operator= ( NEGEMMConvolutionLayer &&  )
default

Default move assignment operator.

◆ prepare()

void prepare ( )
overridevirtual

Prepare the function for executing.

Any one off pre-processing step required by the function is handled here

Note
Prepare stage might not need all the function's buffers' backing memory to be available in order to execute

Reimplemented from IFunction.

Definition at line 600 of file NEGEMMConvolutionLayer.cpp.

601 {
602  if(!_is_prepared)
603  {
604  ARM_COMPUTE_ERROR_ON(!_original_weights->is_used());
605 
606  // Run weights reshaping and mark original weights tensor as unused
607  _weights_reshaped.allocator()->allocate();
608  _reshape_weights.run();
609  _original_weights->mark_as_unused();
610 
611  // Prepare GEMM
612  _is_quantized ? _mm_gemmlowp.prepare() : _mm_gemm.prepare();
613  if(!_weights_reshaped.is_used())
614  {
615  _weights_reshaped.allocator()->free();
616  }
617 
618  _is_prepared = true;
619  }
620 }
void prepare() override
Prepare the function for executing.
bool is_used() const
Flags if the tensor is used or not.
Definition: ITensor.cpp:162
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:337
TensorAllocator * allocator()
Return a pointer to the tensor's allocator.
Definition: Tensor.cpp:48
void mark_as_unused() const
Marks a tensor as unused.
Definition: ITensor.cpp:167
void allocate() override
Allocate size specified by TensorInfo of CPU memory.
void free() override
Free allocated CPU memory.
void run() override
Run the kernels contained in the function.
void prepare() override
Prepare the function for executing.
Definition: NEGEMM.cpp:273

References TensorAllocator::allocate(), Tensor::allocator(), ARM_COMPUTE_ERROR_ON, TensorAllocator::free(), ITensor::is_used(), ITensor::mark_as_unused(), NEGEMM::prepare(), NEGEMMLowpMatrixMultiplyCore::prepare(), and NEConvolutionLayerReshapeWeights::run().

Referenced by NEGEMMConvolutionLayer::run().

◆ run()

void run ( )
overridevirtual

Run the kernels contained in the function.

For NEON kernels:

  • Multi-threading is used for the kernels which are parallelisable.
  • By default std::thread::hardware_concurrency() threads are used.
Note
CPPScheduler::set_num_threads() can be used to manually set the number of threads

For OpenCL kernels:

  • All the kernels are enqueued on the queue associated with CLScheduler.
  • The queue is then flushed.
Note
The function will not block until the kernels are executed. It is the user's responsibility to wait.
Will call prepare() on first run if hasn't been done

Implements IFunction.

Definition at line 551 of file NEGEMMConvolutionLayer.cpp.

552 {
553  prepare();
554 
555  MemoryGroupResourceScope scope_mg(_memory_group);
556 
557  if(!_skip_im2col)
558  {
559  // Run input reshaping
560  unsigned int y_dim = get_data_layout_dimension_index(_data_layout, DataLayoutDimension::HEIGHT);
561  NEScheduler::get().schedule(&_im2col_kernel, y_dim);
562  }
563 
564  // Runs NEGEMM or NEGEMMLowpMatrixMultiplyCore functions
565  if(_is_quantized)
566  {
567  // Run gemmlowp
568  _mm_gemmlowp.run();
569  }
570  else
571  {
572  // Run gemm
573  _mm_gemm.run();
574  }
575 
576  if(_skip_im2col && _append_bias)
577  {
578  NEScheduler::get().schedule(&_add_bias_kernel, Window::DimY);
579  }
580 
581  // Reshape output matrix
582  if(!_skip_col2im)
583  {
584  if(_data_layout == DataLayout::NCHW)
585  {
586  NEScheduler::get().schedule(&_col2im_kernel, Window::DimY);
587  }
588  else
589  {
590  _reshape_layer.run();
591  }
592  }
593 
594  if(_is_activationlayer_enabled)
595  {
596  _activationlayer_function.run();
597  }
598 }
void run() override final
Run the kernels contained in the function.
void run() override
Run the kernels contained in the function.
Definition: NEGEMM.cpp:239
void run() override
Run the kernels contained in the function.
Num samples, channels, height, width.
static constexpr size_t DimY
Alias for dimension 1 also known as Y dimension.
Definition: Window.h:45
Memory group resources scope handling class.
Definition: IMemoryGroup.h:46
virtual void schedule(ICPPKernel *kernel, const Hints &hints)=0
Runs the kernel in the same thread as the caller synchronously.
void prepare() override
Prepare the function for executing.
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:326
static IScheduler & get()
Access the scheduler singleton.
Definition: Scheduler.cpp:96

References Window::DimY, Scheduler::get(), arm_compute::get_data_layout_dimension_index(), arm_compute::HEIGHT, arm_compute::NCHW, NEGEMMConvolutionLayer::prepare(), INESimpleFunctionNoBorder::run(), NEGEMM::run(), NEGEMMLowpMatrixMultiplyCore::run(), and IScheduler::schedule().

◆ validate()

Status validate ( const ITensorInfo input,
const ITensorInfo weights,
const ITensorInfo biases,
const ITensorInfo output,
const PadStrideInfo conv_info,
const WeightsInfo weights_info = WeightsInfo(),
const Size2D dilation = Size2D(1U, 1U),
const ActivationLayerInfo act_info = ActivationLayerInfo(),
unsigned int  num_groups = 1 
)
static

Static function to check if given info will lead to a valid configuration of NEGEMMConvolutionLayer.

Parameters
[in]inputSource tensor. 3 lower dimensions represent a single input [width, height, IFM], while every optional dimension from 4 and above represent a batch of inputs. Data types supported: QASYMM8/F16/F32.
[in]weightsWeights tensor. Weights are 4D tensor with dimensions [kernel_x, kernel_y, IFM, OFM]. Data type supported:Same as input.
[in]biasesBiases tensor. Shared biases supported. Biases are 1D tensor with dimensions [OFM]. Data type supported: Should match input data type, except for input of QASYMM8 type where biases should be of S32 type.
[in]outputDestination tensor. 3 lower dimensions represent a single output [width, height, OFM], while the rest represent batch of outputs. Data types supported: Same as input.
[in]conv_infoContains padding and stride information described in PadStrideInfo.
[in]weights_infoSpecifies if the weights tensor has been reshaped with NEWeightsReshapeKernel. If this is not part of the fully connected layer the weights tensor has also been transposed with NEGEMMTranspose1xWKernel. Data type supported: Same as input.
[in]dilation(Optional) Dilation, in elements, across x and y. Defaults to (1, 1).
[in]act_info(Optional) Activation layer information in case of a fused activation. Only RELU, BOUNDED_RELU and LU_BOUNDED_RELU supported.
[in]num_groups(Optional) Number of groups when performing a grouped convolution. num_groups != 1 is not supported
Returns
a status

Definition at line 397 of file NEGEMMConvolutionLayer.cpp.

399 {
401  ARM_COMPUTE_RETURN_ERROR_ON_MSG(weights_info.are_reshaped(), "Weights already reshaped are not supported!");
405  ARM_COMPUTE_RETURN_ERROR_ON_MSG(num_groups > 1, "Grouping (num_groups != 1) is not supported on NEON");
406 
407  const DataLayout data_layout = input->data_layout();
408  const DataType data_type = input->data_type();
413 
414  const unsigned int kernel_width = weights->dimension(idx_width);
415  const unsigned int kernel_height = weights->dimension(idx_height);
416 
417  TensorInfo im2col_reshaped_info{};
418  TensorInfo info_gemm{};
419  TensorInfo tmp_info{};
420  TensorInfo weights_reshaped_info{};
421  const ITensorInfo *gemm_input_to_use = input;
422  const ITensorInfo *gemm_output_to_use = output;
423  const ITensorInfo *weights_to_use = weights;
424 
425  const bool is_quantized = is_data_type_quantized_asymmetric(data_type);
426  const bool append_bias = (biases != nullptr) && (!is_quantized);
427  bool skip_im2col = (data_layout == DataLayout::NHWC && kernel_width == 1 && kernel_height == 1 && conv_info.stride().first == 1 && conv_info.stride().second == 1);
428  bool is_activation_enabled = act_info.enabled();
429 
430  // Get convolved dimensions
431  unsigned int conv_w = 0;
432  unsigned int conv_h = 0;
433 
434  std::tie(conv_w, conv_h) = scaled_dimensions(input->dimension(idx_width),
435  input->dimension(idx_height),
436  kernel_width,
437  kernel_height,
438  conv_info,
439  dilation);
440 
441  // Check if GEMM3D is supported
442  bool skip_col2im = false;
444  {
445  skip_col2im = bool(validate_gemm3d(input, act_info, conv_h, true));
446  // If not supported, we need to perform im2col and col2im (or reshape layer)
447  if(!skip_col2im)
448  {
449  skip_im2col = false;
450  }
451  }
452 
453  if(skip_col2im)
454  {
455  // If not supported, we need to perform im2col and col2im (or reshape layer)
456  if(!bool(validate_gemm3d(input, act_info, conv_h, skip_im2col)))
457  {
458  skip_im2col = false;
459  skip_col2im = false;
460  }
461  }
462 
463  const unsigned bias_element = (append_bias && !skip_im2col) ? 1 : 0;
464  const ITensorInfo *biases_to_use = (append_bias && !skip_im2col) ? biases : nullptr;
465 
466  ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(idx_channel) != input->dimension(idx_channel));
467  ARM_COMPUTE_RETURN_ERROR_ON(weights->num_dimensions() > 4);
468 
469  // Validate biases
470  if(biases != nullptr)
471  {
472  if(is_quantized)
473  {
475  }
476  else
477  {
479  }
480  ARM_COMPUTE_RETURN_ERROR_ON(biases->dimension(0) != weights->dimension(idx_kernels));
482  }
483 
484  if(act_info.enabled())
485  {
487  }
488 
489  unsigned int mat_weights_cols = weights->dimension(idx_kernels);
490  unsigned int mat_weights_rows = weights->dimension(idx_width) * weights->dimension(idx_height) * weights->dimension(idx_channel) + bias_element;
491 
492  // Output tensor auto inizialization if not yet initialized
494  weights_reshaped_info = TensorInfo(compute_weights_reshaped_shape(*weights, (append_bias && !skip_im2col)), 1, data_type);
495  weights_reshaped_info.set_quantization_info(weights->quantization_info());
496  weights_to_use = &weights_reshaped_info;
497 
498  if(!skip_im2col)
499  {
500  // Create tensor info for im2col reshaped inputs
501  // For NEON the batch size is on the fourth dimension
502  // TODO (giaiod01): Auto-initialize the output shape of im2col COMPMID-1482
503  TensorShape shape_im2col = input->tensor_shape();
504  shape_im2col.set(0, mat_weights_rows);
505  shape_im2col.set(1, conv_w * conv_h);
506  shape_im2col.set(2, 1);
507 
508  im2col_reshaped_info = TensorInfo(shape_im2col, 1, data_type);
509  im2col_reshaped_info.set_quantization_info(input->quantization_info());
510 
511  ARM_COMPUTE_RETURN_ON_ERROR(NEIm2ColKernel::validate(input, &im2col_reshaped_info, Size2D(kernel_width, kernel_height), conv_info, append_bias, dilation));
512  gemm_input_to_use = &im2col_reshaped_info;
513  }
514  else if(append_bias)
515  {
516  // Validate add bias kernel
518  }
519 
520  // Create temporary GEMM output tensor in case we cannot skip col2im
521  if(!skip_col2im)
522  {
523  TensorShape shape_gemm = gemm_input_to_use->tensor_shape();
524  shape_gemm.set(0, mat_weights_cols);
525  shape_gemm.set(1, conv_w * conv_h);
526  info_gemm = TensorInfo(shape_gemm, 1, data_type);
527  }
528  else
529  {
530  info_gemm = TensorInfo(output->tensor_shape(), 1, data_type);
531  }
533  gemm_output_to_use = &info_gemm;
534  ARM_COMPUTE_RETURN_ON_ERROR(validate_mm(gemm_input_to_use, weights_to_use, biases, gemm_output_to_use, act_info, skip_col2im ? conv_h : 0, skip_im2col));
535 
536  // Validate Col2Im/ReshapeLayer
537  if(!skip_col2im && (data_layout == DataLayout::NCHW))
538  {
539  ARM_COMPUTE_RETURN_ON_ERROR(NECol2ImKernel::validate(gemm_output_to_use, output, Size2D(conv_w, conv_h)));
540  }
541 
542  //Validate Activation Layer
543  if(is_activation_enabled)
544  {
546  }
547 
548  return Status{};
549 }
virtual size_t num_dimensions() const =0
The number of dimensions of the tensor (rank)
Shape of a tensor.
Definition: TensorShape.h:39
const DataLayout data_layout
Definition: Im2Col.cpp:146
static Status validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, ConvertPolicy policy)
Static function to check if given info will lead to a valid configuration of NEArithmeticAdditionKern...
virtual size_t dimension(size_t index) const =0
Return the size of the requested dimension.
std::pair< unsigned int, unsigned int > scaled_dimensions(unsigned int width, unsigned int height, unsigned int kernel_width, unsigned int kernel_height, const PadStrideInfo &pad_stride_info, const Size2D &dilation=Size2D(1U, 1U))
Returns expected width and height of output scaled tensor depending on dimensions rounding mode.
Definition: Utils.cpp:387
#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(...)
Definition: Validate.h:494
#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...)
Definition: Validate.h:545
#define ARM_COMPUTE_RETURN_ON_ERROR(status)
Checks if a status contains an error and returns it.
Definition: Error.h:193
virtual DataType data_type() const =0
Data type used for each element of the tensor.
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 of NEActivationLayer.
#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c,...)
Definition: Validate.h:791
1 channel, 1 F32 per channel
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:337
Store the tensor's metadata.
Definition: ITensorInfo.h:40
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:244
1 channel, 1 F16 per channel
ITensorInfo & set_quantization_info(const QuantizationInfo &quantization_info) override
Set the quantization settings (scale and offset) of the tensor.
Definition: TensorInfo.cpp:364
1 channel, 1 S32 per channel
static Status validate(const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output)
Static function to check if given info will lead to a valid configuration of NEConvolutionLayerReshap...
virtual const TensorShape & tensor_shape() const =0
Size for each dimension of the tensor.
quantized, asymmetric fixed-point 8-bit number
const unsigned int num_groups
Definition: Im2Col.cpp:148
#define ARM_COMPUTE_RETURN_ERROR_ON_MSG(cond,...)
If the condition is true, an error is returned.
Definition: Error.h:214
static Status validate(const ITensorInfo *input, const ITensorInfo *output, const Size2D &convolved_dims)
Static function to check if given info will lead to a valid configuration of NECol2ImKernel.
virtual QuantizationInfo quantization_info() const =0
Get the quantization settings (scale and offset) of the tensor.
Num samples, channels, height, width.
src_info set_data_layout(data_layout)
bool is_data_type_quantized_asymmetric(DataType dt)
Check if a given data type is of asymmetric quantized type.
Definition: Utils.h:1030
#define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...)
Definition: Validate.h:163
TensorShape compute_weights_reshaped_shape(const ITensorInfo &weights, bool has_bias=false, unsigned int num_groups=1)
Calculate the reshaped shape of the weights.
Class for specifying the size of an image or rectangle.
Definition: Size2D.h:34
Num samples, height, width, channels.
TensorShape & set(size_t dimension, size_t value, bool apply_dim_correction=true)
Accessor to set the value of one of the dimensions.
Definition: TensorShape.h:78
Store the tensor's metadata.
Definition: TensorInfo.h:45
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:326
DataType
Available data types.
Definition: Types.h:74
DataLayout
[DataLayout enum definition]
Definition: Types.h:114
static Status validate(const ITensorInfo *input, const ITensorInfo *output, const Size2D &kernel_dims, const PadStrideInfo &conv_info, bool has_bias, const Size2D &dilation=Size2D(1U, 1U), unsigned int num_groups=1)
Static function to check if given info will lead to a valid configuration of NEIm2ColKernel.
virtual DataLayout data_layout() const =0
Get the data layout of the tensor.

References arm_compute::test::validation::act_info, ARM_COMPUTE_ERROR_ON, ARM_COMPUTE_RETURN_ERROR_ON, ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN, ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT, ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES, ARM_COMPUTE_RETURN_ERROR_ON_MSG, ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR, ARM_COMPUTE_RETURN_ON_ERROR, arm_compute::BATCHES, arm_compute::CHANNEL, arm_compute::misc::shape_calculator::compute_weights_reshaped_shape(), arm_compute::test::validation::conv_info, arm_compute::test::validation::data_layout, ITensorInfo::data_layout(), arm_compute::test::validation::data_type, ITensorInfo::data_type(), arm_compute::test::validation::dilation, ITensorInfo::dimension(), arm_compute::F16, arm_compute::F32, arm_compute::get_data_layout_dimension_index(), arm_compute::HEIGHT, arm_compute::is_data_type_quantized_asymmetric(), arm_compute::NCHW, arm_compute::NHWC, ITensorInfo::num_dimensions(), arm_compute::test::validation::num_groups, arm_compute::QASYMM8, ITensorInfo::quantization_info(), arm_compute::S32, arm_compute::SATURATE, arm_compute::scaled_dimensions(), TensorShape::set(), arm_compute::test::validation::set_data_layout(), TensorInfo::set_quantization_info(), ITensorInfo::tensor_shape(), NEActivationLayer::validate(), NEConvolutionLayerReshapeWeights::validate(), NEArithmeticAdditionKernel::validate(), NECol2ImKernel::validate(), NEIm2ColKernel::validate(), arm_compute::test::validation::weights, arm_compute::test::validation::weights_info, and arm_compute::WIDTH.

Referenced by NEGEMMConvolutionLayer::configure(), and NEConvolutionLayer::validate().


The documentation for this class was generated from the following files: