Compute Library
 19.11
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, IWeightsManager *weights_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 144 of file NEGEMMConvolutionLayer.h.

Constructor & Destructor Documentation

◆ NEGEMMConvolutionLayer() [1/3]

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

Constructor.

Definition at line 89 of file NEGEMMConvolutionLayer.cpp.

90  : _memory_group(memory_manager), _weights_manager(weights_manager), _reshape_weights(), _reshape_weights_managed(), _im2col_kernel(), _mm_gemm(memory_manager), _mm_gemmlowp(memory_manager),
91  _col2im_kernel(), _reshape_layer(), _original_weights(nullptr), _im2col_output(), _weights_reshaped(), _gemm_output(), _tmp_output(), _data_layout(DataLayout::NCHW), _skip_im2col(false),
92  _skip_col2im(false), _is_quantized(false), _is_prepared(false)
93 {
94 }
Num samples, channels, height, width.

◆ 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/F16/F32.
[in]weightsWeights tensor. Weights are 4D tensor with dimensions [kernel_x, kernel_y, IFM, OFM]. Data type supported: QASYMM8/QSYMM8_PER_CHANNEL/F16/F32.
[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 235 of file NEGEMMConvolutionLayer.cpp.

237 {
241  weights->info(),
242  biases != nullptr ? biases->info() : nullptr,
243  output->info(),
244  conv_info,
245  weights_info,
246  dilation,
247  act_info,
248  num_groups));
249 
250  const DataType data_type = input->info()->data_type();
251  const DataLayout data_layout = input->info()->data_layout();
255 
256  const unsigned int kernel_width = weights->info()->dimension(idx_width);
257  const unsigned int kernel_height = weights->info()->dimension(idx_height);
258 
259  _is_prepared = weights_info.retain_internal_weights();
260  _original_weights = weights;
261  _is_quantized = is_data_type_quantized_asymmetric(input->info()->data_type());
262  _data_layout = data_layout;
263  _skip_im2col = (data_layout == DataLayout::NHWC && kernel_width == 1 && kernel_height == 1 && conv_info.stride().first == 1 && conv_info.stride().second == 1);
264 
265  const ITensor *gemm_input_to_use = input;
266  ITensor *gemm_output_to_use = output;
267 
268  // Get convolved dimensions
269  unsigned int conv_w = 0;
270  unsigned int conv_h = 0;
271  std::tie(conv_w, conv_h) = scaled_dimensions(input->info()->dimension(idx_width),
272  input->info()->dimension(idx_height),
273  kernel_width,
274  kernel_height,
275  conv_info,
276  dilation);
277 
278  // Check if GEMM3D is supported
280  {
281  _skip_col2im = bool(validate_gemm3d(input->info(), weights->info(), act_info, conv_h, true));
282  // If not supported, we need to perform im2col and col2im (or reshape layer)
283  if(!_skip_col2im)
284  {
285  _skip_im2col = false;
286  }
287  }
288  else
289  {
290  _skip_col2im = false;
291  }
292 
293  // Get parameters from conv_info
294  unsigned int stride_x = 0;
295  unsigned int stride_y = 0;
296  std::tie(stride_x, stride_y) = conv_info.stride();
297 
298  unsigned int mat_weights_cols = weights->info()->dimension(idx_kernels);
299 
300  // _weights_reshaped will be auto configured in the kernel.
301  // Just append biases and do not transpose 1xW as it will be reshaped in NEGEMM
302  const ITensor *weights_to_use = weights;
303 
304  if(_weights_manager && _weights_manager->are_weights_managed(weights))
305  {
306  _reshape_weights_managed.configure(weights, nullptr);
307  weights_to_use = _weights_manager->acquire(weights, &_reshape_weights_managed);
308  }
309  else
310  {
311  _reshape_weights.configure(weights, nullptr, &_weights_reshaped);
312  weights_to_use = &_weights_reshaped;
313  }
314 
315  // Create tensor to store im2col reshaped inputs
316  if(!_skip_im2col)
317  {
318  _memory_group.manage(&_im2col_output);
319 
320  // Configure
321  _im2col_kernel.configure(input, &_im2col_output, Size2D(kernel_width, kernel_height), conv_info, false, dilation);
322 
323  // Update GEMM input
324  gemm_input_to_use = &_im2col_output;
325  }
326 
327  // Create temporary GEMM output tensor in case we cannot skip col2im
328  if(!_skip_col2im)
329  {
330  TensorShape shape_gemm;
331 
332  // Calculate GEMM output shape
333  shape_gemm = _im2col_output.info()->tensor_shape();
334  shape_gemm.set(0, mat_weights_cols);
335  shape_gemm.set(1, conv_w * conv_h);
336 
337  // FIXME: input->clone() doesn't work with subtensors for grouped convolutions.
338  TensorInfo info_gemm(shape_gemm, 1, data_type);
339  info_gemm.set_quantization_info(output->info()->quantization_info()).set_data_layout(input->info()->data_layout());
340  _gemm_output.allocator()->init(info_gemm);
341  _memory_group.manage(&_gemm_output);
342 
343  // Update GEMM output
344  gemm_output_to_use = &_gemm_output;
345  }
346 
347  // Configure GEMM
348  // In case we need to skip col2im, GEMM3D (gemm_3d_depth != 0) must be called in order to avoid reshaping the output matrix
349  const unsigned int gemm_3d_depth = _skip_col2im ? conv_h : 0;
350  configure_mm(gemm_input_to_use, weights_to_use, biases, gemm_output_to_use, act_info, gemm_3d_depth);
351 
352  if(!_skip_im2col)
353  {
354  _im2col_output.allocator()->allocate();
355  }
356 
357  if(!_skip_col2im)
358  {
359  if(_data_layout == DataLayout::NCHW)
360  {
361  // Configure col2im
362  _col2im_kernel.configure(gemm_output_to_use, output, Size2D(conv_w, conv_h));
363  }
364  else
365  {
366  // Configure reshape layer
367  _reshape_layer.configure(gemm_output_to_use, output);
368  }
369  }
370 
371  if(_is_quantized && !_skip_col2im)
372  {
373  _tmp_output.allocator()->allocate();
374  }
375 
376  if(!_skip_col2im || _is_quantized)
377  {
378  _gemm_output.allocator()->allocate();
379  }
380 
381  ARM_COMPUTE_ERROR_ON_MSG((output->info()->dimension(idx_width) != conv_w) || (output->info()->dimension(idx_height) != conv_h),
382  "Output shape does not match the expected one");
383 }
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:41
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:402
size_t dimension(size_t index) const override
Return the size of the requested dimension.
Definition: TensorInfo.h:232
#define ARM_COMPUTE_ERROR_THROW_ON(status)
Definition: Error.h:455
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
void manage(IMemoryManageable *obj) override
Sets a object to be managed by the given memory group.
Definition: MemoryGroup.h:79
bool are_weights_managed(const ITensor *weights)
Check if the weights are managed.
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
virtual const TensorShape & tensor_shape() const =0
Size for each dimension of the tensor.
#define ARM_COMPUTE_ERROR_ON_MSG(cond, msg)
Definition: Error.h:456
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:1044
#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(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:327
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:116
ITensor * acquire(const ITensor *weights, ITransformWeights *weights_transform)
Acquire the requested reshape tensor of the selected weights.

References IWeightsManager::acquire(), arm_compute::test::validation::act_info, TensorAllocator::allocate(), Tensor::allocator(), IWeightsManager::are_weights_managed(), ARM_COMPUTE_ERROR_ON_MSG, ARM_COMPUTE_ERROR_ON_NULLPTR, ARM_COMPUTE_ERROR_THROW_ON, ARM_COMPUTE_UNUSED, arm_compute::BATCHES, NEReshapeLayer::configure(), NEConvolutionLayerReshapeWeights::configure(), NECol2ImKernel::configure(), NEIm2ColKernel::configure(), NEConvolutionLayerReshapeWeightsTransform::configure(), arm_compute::test::validation::conv_info, arm_compute::test::validation::data_layout, arm_compute::test::validation::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::test::validation::input, arm_compute::is_data_type_quantized_asymmetric(), MemoryGroup::manage(), arm_compute::NCHW, arm_compute::NHWC, arm_compute::test::validation::num_groups, ITensorInfo::quantization_info(), 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 558 of file NEGEMMConvolutionLayer.cpp.

559 {
560  if(!_is_prepared)
561  {
562  if(_weights_manager && _weights_manager->are_weights_managed(_original_weights))
563  {
564  _weights_manager->run(_original_weights, &_reshape_weights_managed);
565  }
566  else
567  {
568  // Run weights reshaping and mark original weights tensor as unused
569  _weights_reshaped.allocator()->allocate();
570  _reshape_weights.run();
571  _original_weights->mark_as_unused();
572  }
573 
574  // Prepare GEMM
575  _is_quantized ? _mm_gemmlowp.prepare() : _mm_gemm.prepare();
576  if(!_weights_reshaped.is_used())
577  {
578  _weights_reshaped.allocator()->free();
579  }
580 
581  _is_prepared = true;
582  }
583 }
void prepare() override
Prepare the function for executing.
bool is_used() const
Flags if the tensor is used or not.
Definition: ITensor.cpp:162
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
bool are_weights_managed(const ITensor *weights)
Check if the weights are managed.
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:335
ITensor * run(const ITensor *weights, ITransformWeights *weights_transform)
Run the reshape function.

References TensorAllocator::allocate(), Tensor::allocator(), IWeightsManager::are_weights_managed(), TensorAllocator::free(), ITensor::is_used(), ITensor::mark_as_unused(), NEGEMM::prepare(), NEGEMMLowpMatrixMultiplyCore::prepare(), IWeightsManager::run(), 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 519 of file NEGEMMConvolutionLayer.cpp.

520 {
521  prepare();
522 
523  MemoryGroupResourceScope scope_mg(_memory_group);
524 
525  if(!_skip_im2col)
526  {
527  // Run input reshaping
528  unsigned int y_dim = get_data_layout_dimension_index(_data_layout, DataLayoutDimension::HEIGHT);
529  NEScheduler::get().schedule(&_im2col_kernel, y_dim);
530  }
531 
532  // Runs NEGEMM or NEGEMMLowpMatrixMultiplyCore functions
533  if(_is_quantized)
534  {
535  // Run gemmlowp
536  _mm_gemmlowp.run();
537  }
538  else
539  {
540  // Run gemm
541  _mm_gemm.run();
542  }
543 
544  // Reshape output matrix
545  if(!_skip_col2im)
546  {
547  if(_data_layout == DataLayout::NCHW)
548  {
549  NEScheduler::get().schedule(&_col2im_kernel, Window::DimY);
550  }
551  else
552  {
553  _reshape_layer.run();
554  }
555  }
556 }
void run() override final
Run the kernels contained in the function.
void run() override
Run the kernels contained in the function.
Definition: NEGEMM.cpp:285
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:82
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:327
static IScheduler & get()
Access the scheduler singleton.
Definition: Scheduler.cpp:95

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: QASYMM8/QSYMM8_PER_CHANNEL/F16/F32.
[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 385 of file NEGEMMConvolutionLayer.cpp.

387 {
389  ARM_COMPUTE_RETURN_ERROR_ON_MSG(weights_info.are_reshaped(), "Weights already reshaped are not supported!");
393  ARM_COMPUTE_RETURN_ERROR_ON_MSG(num_groups > 1, "Grouping (num_groups != 1) is not supported on NEON");
394 
395  const DataLayout data_layout = input->data_layout();
396  const DataType data_type = input->data_type();
401 
402  const unsigned int kernel_width = weights->dimension(idx_width);
403  const unsigned int kernel_height = weights->dimension(idx_height);
404 
405  TensorInfo im2col_reshaped_info{};
406  TensorInfo info_gemm{};
407  TensorInfo tmp_info{};
408  TensorInfo weights_reshaped_info{};
409  const ITensorInfo *gemm_input_to_use = input;
410  const ITensorInfo *gemm_output_to_use = output;
411  const ITensorInfo *weights_to_use = weights;
412 
413  const bool append_bias = false;
414  const bool is_quantized = is_data_type_quantized_asymmetric(data_type);
415  bool skip_im2col = (data_layout == DataLayout::NHWC && kernel_width == 1 && kernel_height == 1 && conv_info.stride().first == 1 && conv_info.stride().second == 1);
416 
417  // Get convolved dimensions
418  unsigned int conv_w = 0;
419  unsigned int conv_h = 0;
420 
421  std::tie(conv_w, conv_h) = scaled_dimensions(input->dimension(idx_width),
422  input->dimension(idx_height),
423  kernel_width,
424  kernel_height,
425  conv_info,
426  dilation);
427 
428  // Check if GEMM3D is supported
429  bool skip_col2im = false;
431  {
432  skip_col2im = bool(validate_gemm3d(input, weights, act_info, conv_h, true));
433  // If not supported, we need to perform im2col and col2im (or reshape layer)
434  if(!skip_col2im)
435  {
436  skip_im2col = false;
437  }
438  }
439 
440  if(skip_col2im)
441  {
442  // If not supported, we need to perform im2col and col2im (or reshape layer)
443  if(!bool(validate_gemm3d(input, weights, act_info, conv_h, skip_im2col)))
444  {
445  skip_im2col = false;
446  skip_col2im = false;
447  }
448  }
449 
450  ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(idx_channel) != input->dimension(idx_channel));
451  ARM_COMPUTE_RETURN_ERROR_ON(weights->num_dimensions() > 4);
452 
453  // Validate biases
454  if(biases != nullptr)
455  {
456  if(is_quantized)
457  {
459  }
460  else
461  {
463  }
464  ARM_COMPUTE_RETURN_ERROR_ON(biases->dimension(0) != weights->dimension(idx_kernels));
466  }
467 
468  unsigned int mat_weights_cols = weights->dimension(idx_kernels);
469  unsigned int mat_weights_rows = weights->dimension(idx_width) * weights->dimension(idx_height) * weights->dimension(idx_channel);
470 
471  // Output tensor auto inizialization if not yet initialized
473  weights_reshaped_info = TensorInfo(compute_weights_reshaped_shape(*weights, append_bias), 1, data_type);
474  weights_reshaped_info.set_quantization_info(weights->quantization_info());
475  weights_to_use = &weights_reshaped_info;
476 
477  if(!skip_im2col)
478  {
479  // Create tensor info for im2col reshaped inputs
480  // For NEON the batch size is on the fourth dimension
481  // TODO (giaiod01): Auto-initialize the output shape of im2col COMPMID-1482
482  TensorShape shape_im2col = input->tensor_shape();
483  shape_im2col.set(0, mat_weights_rows);
484  shape_im2col.set(1, conv_w * conv_h);
485  shape_im2col.set(2, 1);
486 
487  im2col_reshaped_info = TensorInfo(shape_im2col, 1, data_type);
488  im2col_reshaped_info.set_quantization_info(input->quantization_info());
489 
490  ARM_COMPUTE_RETURN_ON_ERROR(NEIm2ColKernel::validate(input, &im2col_reshaped_info, Size2D(kernel_width, kernel_height), conv_info, append_bias, dilation));
491  gemm_input_to_use = &im2col_reshaped_info;
492  }
493 
494  // Create temporary GEMM output tensor in case we cannot skip col2im
495  if(!skip_col2im)
496  {
497  TensorShape shape_gemm = gemm_input_to_use->tensor_shape();
498  shape_gemm.set(0, mat_weights_cols);
499  shape_gemm.set(1, conv_w * conv_h);
500  info_gemm = TensorInfo(shape_gemm, 1, data_type);
501  }
502  else
503  {
504  info_gemm = TensorInfo(output->tensor_shape(), 1, data_type);
505  }
506  info_gemm.set_quantization_info(output->quantization_info()).set_data_layout(input->data_layout());
507  gemm_output_to_use = &info_gemm;
508  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));
509 
510  // Validate Col2Im/ReshapeLayer
511  if(!skip_col2im && (data_layout == DataLayout::NCHW))
512  {
513  ARM_COMPUTE_RETURN_ON_ERROR(NECol2ImKernel::validate(gemm_output_to_use, output, Size2D(conv_w, conv_h)));
514  }
515 
516  return Status{};
517 }
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
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:402
#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:204
#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c,...)
Definition: Validate.h:792
1 channel, 1 F32 per channel
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:296
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:372
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 unsigned
const unsigned int num_groups
Definition: Im2Col.cpp:148
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:1044
quantized, symmetric per channel fixed-point 8-bit number
#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.
#define ARM_COMPUTE_RETURN_ERROR_ON_MSG(cond, msg)
If the condition is true, an error is returned.
Definition: Error.h:244
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:327
DataType
Available data types.
Definition: Types.h:74
DataLayout
[DataLayout enum definition]
Definition: Types.h:116
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.

References arm_compute::test::validation::act_info, 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, arm_compute::test::validation::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::test::validation::input, 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, arm_compute::QSYMM8_PER_CHANNEL, ITensorInfo::quantization_info(), arm_compute::S32, arm_compute::scaled_dimensions(), TensorShape::set(), arm_compute::test::validation::set_data_layout(), TensorInfo::set_quantization_info(), ITensorInfo::tensor_shape(), NEConvolutionLayerReshapeWeights::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: