Compute Library
 22.05
CpuFullyConnected Class Reference

Basic function to compute a Fully Connected layer. More...

#include <CpuFullyConnected.h>

Collaboration diagram for CpuFullyConnected:
[legend]

Public Member Functions

 CpuFullyConnected ()
 Constructor. More...
 
 ~CpuFullyConnected ()
 Destructor. More...
 
void configure (const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, ITensorInfo *dst, FullyConnectedLayerInfo fc_info=FullyConnectedLayerInfo())
 Set the input and output tensors. More...
 
void run (ITensorPack &tensors) override
 Run the kernels contained in the function. More...
 
void prepare (ITensorPack &tensors) override
 Prepare the function for executing. More...
 
experimental::MemoryRequirements workspace () const override
 Return the memory requirements required by the workspace. More...
 
- Public Member Functions inherited from INEOperator
 INEOperator (IRuntimeContext *ctx=nullptr)
 Constructor. More...
 
 INEOperator (const INEOperator &)=delete
 Prevent instances of this class from being copied (As this class contains pointers) More...
 
 INEOperator (INEOperator &&)=default
 Default move constructor. More...
 
INEOperatoroperator= (const INEOperator &)=delete
 Prevent instances of this class from being copied (As this class contains pointers) More...
 
INEOperatoroperator= (INEOperator &&)=default
 Default move assignment operator. More...
 
 ~INEOperator ()
 Default destructor. More...
 
- Public Member Functions inherited from IOperator
virtual ~IOperator ()=default
 Destructor. More...
 

Static Public Member Functions

static Status validate (const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *dst, FullyConnectedLayerInfo fc_info=FullyConnectedLayerInfo())
 Static function to check if given info will lead to a valid configuration of CpuFullyConnected. More...
 

Detailed Description

Basic function to compute a Fully Connected layer.

This function calls the following kernels:

  1. kernels::CpuIm2ColKernel (called when the input comes from a convolutional layer)
  2. kernels::CpuTransposeKernel (if are_weights_reshaped is set to false and transpose_weights is set to true ) (called once)
  3. CpuGemm or CpuGemmLowpMatrixMultiplyCore (if quantized asymmetric)
  4. kernels::CpuGemmMatrixAdditionKernel or CpuGemmLowpOutputStage (if quantized asymmetric) (if biases is not equal to nullptr)
Note
The fully connected layer accepts "weights" tensors only with 2 dimensions.

Definition at line 54 of file CpuFullyConnected.h.

Constructor & Destructor Documentation

◆ CpuFullyConnected()

Constructor.

Definition at line 148 of file CpuFullyConnected.cpp.

149  : _flatten(nullptr),
150  _convert_weights(nullptr),
151  _transpose_weights(nullptr),
152  _mm_gemm(nullptr),
153  _mm_gemmlowp(nullptr),
154  _flattened_src(),
155  _converted_weights(),
156  _reshaped_weights(),
157  _trans_weights(),
158  _trans_weights_idx(AuxTensorIdx::Count),
159  _aux_mem(Count),
160  _needs_weights_conversion(false),
161  _needs_weights_reshape(false),
162  _is_fc_after_conv(false),
163  _is_quantized_asymmetric(false),
164  _is_prepared(false),
165  _enable_fast_math(false)
166 
167 {
168 }

◆ ~CpuFullyConnected()

~CpuFullyConnected ( )
default

Destructor.

Member Function Documentation

◆ configure()

void configure ( const ITensorInfo src,
const ITensorInfo weights,
const ITensorInfo biases,
ITensorInfo dst,
FullyConnectedLayerInfo  fc_info = FullyConnectedLayerInfo() 
)

Set the input and output tensors.

Valid data layouts:

  • NHWC
  • NCHW

Valid data type configurations:

src0 src1 src2 dst
F16 F16 F16 F16
F32 F32 F32 F32
QASYMM8 QASYMM8 S32 QASYMM8
QASYMM8_SIGNED QASYMM8_SIGNED S32 QASYMM8_SIGNED
Parameters
[in]srcSource tensor info. Data type supported: QASYMM8/QASYMM8_SIGNED/F16/F32.
[in]weightsWeights tensor info. The weights must be 2 dimensional. If this function is called after a Convolution Layer, the (transposed) weights will have as many rows as the product of the first 3 input's dimensions. If it is called after another FullyConnected Layer, the (transposed) weights will have as many rows as the input's first dimension. Data type supported: Same as src.
[in]biasesBias tensor info. Can be nullptr. Data type supported: Same as weights, S32 if weights is QASYMM8/QASYMM8_SIGNED.
[out]dstDestination tensor info. Its shape should be equal to the output of a matrix multiplication between:
  • The output of im2col on the input and the (transposed) 2D weights, if the function is called after a Convolution Layer
  • The input tensor and the (transposed) 2D weights, if the function is called after another FullyConnected Layer. Data type supported: Same as src.
[in]fc_info(Optional) Fully connected layer additional info

Definition at line 231 of file CpuFullyConnected.cpp.

References FullyConnectedLayerInfo::activation_info, ITensorInfo::are_values_constant(), FullyConnectedLayerInfo::are_weights_reshaped, ARM_COMPUTE_ERROR_ON_NULLPTR, ARM_COMPUTE_ERROR_THROW_ON, ARM_COMPUTE_LOG_PARAMS, Dimensions< T >::cbegin(), Dimensions< T >::cend(), ITensorInfo::data_layout(), ITensorInfo::data_type(), ITensorInfo::dimension(), FullyConnectedLayerInfo::enable_fast_math, arm_compute::is_data_type_quantized_asymmetric(), ITensorInfo::num_dimensions(), Dimensions< size_t >::num_max_dimensions, arm_compute::offset_int_vec(), arm_compute::experimental::Prepare, FullyConnectedLayerInfo::retain_internal_weights, ITensorInfo::tensor_shape(), TensorInfo::total_size(), FullyConnectedLayerInfo::transpose_weights, CpuFullyConnected::validate(), and FullyConnectedLayerInfo::weights_trained_layout.

233 {
234  // Perform validate step
237  weights,
238  biases != nullptr ? biases : nullptr,
239  dst,
240  fc_info));
241  ARM_COMPUTE_LOG_PARAMS(src, weights, biases, dst, fc_info);
242 
243  _needs_weights_conversion = false;
244  _needs_weights_reshape = fc_info.transpose_weights ? !fc_info.are_weights_reshaped : false;
245  _needs_weights_reshape = _needs_weights_reshape && !fc_info.retain_internal_weights;
246  _is_fc_after_conv = true;
247  _is_quantized_asymmetric = is_data_type_quantized_asymmetric(src->data_type());
248  _is_prepared = false;
249  _trans_weights_idx = AuxTensorIdx::Count;
250  _enable_fast_math = fc_info.enable_fast_math;
251 
252  // With the Fully Connected layer we can have 4 different cases:
253  // 1) Convolution layer -> Fully Connected layer without batches
254  // 2) Fully Connected layer -> Fully Connected layer without batches
255  // 3) Convolution layer -> Fully Connected layer with batches
256  // 4) Fully Connected layer -> Fully Connected layer with batches
257 
258  const ITensorInfo *weights_to_use = weights;
259 
260  // Check if we have a fully connected layer with batches
261  const bool is_batched_fc_layer = dst->dimension(1) > 1;
262  if(is_batched_fc_layer)
263  {
264  _is_fc_after_conv = (TensorShape::num_max_dimensions >= 4) && (std::equal(src->tensor_shape().cbegin() + 3,
265  src->tensor_shape().cend(),
266  dst->tensor_shape().cbegin() + 1));
267  }
268  else
269  {
270  _is_fc_after_conv = src->num_dimensions() > 1;
271  }
272 
273  // Reshape weights if needed
274  if(_needs_weights_reshape)
275  {
276  // Reshape the weights
277  _transpose_weights = std::make_unique<kernels::CpuTransposeKernel>();
278  _transpose_weights->configure(weights, &_reshaped_weights);
279  weights_to_use = &_reshaped_weights;
280  _trans_weights_idx = AuxTensorIdx::TransposedWeights;
281  }
282 
283  // Convert weights if needed
284  if(_is_fc_after_conv && (src->data_layout() != fc_info.weights_trained_layout))
285  {
286  // Convert weights
287  _convert_weights = std::make_unique<CpuConvertFullyConnectedWeights>();
288  _convert_weights->configure(weights_to_use,
289  &_converted_weights,
290  src->tensor_shape(),
291  fc_info.weights_trained_layout);
292 
293  weights_to_use = &_converted_weights;
294  _needs_weights_conversion = true;
295  _trans_weights_idx = AuxTensorIdx::ConvertedWeights;
296  }
297 
298  if(_is_fc_after_conv)
299  {
300  // Fully Connected layer after a Convolution Layer without batches
301  configure_conv_fc(src, weights_to_use, biases, dst, fc_info.activation_info);
302  }
303  else
304  {
305  // Fully Connected layer after a Fully Connected Layer without batches
306  configure_fc_fc(src, weights_to_use, biases, dst, fc_info.activation_info);
307  }
308 
309  // Retain the tensorinfo with the weights to use
310  if(_needs_weights_reshape || _needs_weights_conversion)
311  {
312  _trans_weights = *weights_to_use;
313  }
314 
315  // Set auxiliary memory requirements
316  auto gemm_mem_req = (_is_quantized_asymmetric) ? _mm_gemmlowp->workspace() : _mm_gemm->workspace();
317  for(unsigned int i = 0; i < gemm_mem_req.size(); ++i)
318  {
319  _aux_mem[i] = gemm_mem_req[i];
320  }
321 
322  if(_aux_mem[Pretranspose].size > 0)
323  {
324  // Release permuted weights at the end of prepare as they are further transposed by the assembly dispatch
325  // Do not release them if biases are dynamic and data type is quantized, since the weights tensor will be used for biases offset calculation
326  _aux_mem[TransposedWeights] = MemoryInfo(offset_int_vec(TransposedWeights), (_is_quantized_asymmetric
327  && biases && !(biases->are_values_constant())) ?
328  MemoryLifetime::Persistent :
330  _reshaped_weights.total_size());
331  _aux_mem[ConvertedWeights] = MemoryInfo(offset_int_vec(ConvertedWeights), MemoryLifetime::Prepare, _converted_weights.total_size());
332  }
333  else
334  {
335  _aux_mem[TransposedWeights] = MemoryInfo(offset_int_vec(TransposedWeights), _needs_weights_conversion ? MemoryLifetime::Prepare : MemoryLifetime::Persistent, _reshaped_weights.total_size());
336  _aux_mem[ConvertedWeights] = MemoryInfo(offset_int_vec(ConvertedWeights), MemoryLifetime::Persistent, _converted_weights.total_size());
337  }
338  _aux_mem[FlattenedSrc] = MemoryInfo(offset_int_vec(FlattenedSrc), MemoryLifetime::Temporary, _flattened_src.total_size());
339 }
#define ARM_COMPUTE_ERROR_THROW_ON(status)
Definition: Error.h:455
SimpleTensor< float > src
Definition: DFT.cpp:155
size_t total_size() const override
Returns the total size of the tensor in bytes.
Definition: TensorInfo.h:250
bool is_data_type_quantized_asymmetric(DataType dt)
Check if a given data type is of asymmetric quantized type.
Definition: Utils.h:1052
static Status validate(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *dst, FullyConnectedLayerInfo fc_info=FullyConnectedLayerInfo())
Static function to check if given info will lead to a valid configuration of CpuFullyConnected.
#define ARM_COMPUTE_LOG_PARAMS(...)
#define ARM_COMPUTE_ERROR_ON_NULLPTR(...)
Definition: Validate.h:157
int offset_int_vec(int offset)
Definition: MemoryHelpers.h:38
static constexpr size_t num_max_dimensions
Number of dimensions the tensor has.
Definition: Dimensions.h:46

◆ prepare()

void prepare ( ITensorPack constants)
overridevirtual

Prepare the function for executing.

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

Parameters
[in]constantsVector that contains the constants tensors.
Note
Prepare stage might not need all the function's buffers' backing memory to be available in order to execute

Reimplemented from INEOperator.

Definition at line 467 of file CpuFullyConnected.cpp.

References arm_compute::ACL_DST, arm_compute::ACL_SRC, arm_compute::ACL_SRC_1, ITensorPack::add_const_tensor(), Window::DimY, Scheduler::get(), CpuAuxTensorHandler::get(), ITensorPack::get_const_tensor(), ITensor::mark_as_unused(), arm_compute::offset_int_vec(), and IScheduler::schedule_op().

Referenced by CpuFullyConnected::run().

468 {
469  if(!_is_prepared)
470  {
471  auto weights = tensors.get_const_tensor(ACL_SRC_1);
472 
473  CpuAuxTensorHandler reshaped_weights(offset_int_vec(TransposedWeights), _reshaped_weights, tensors, false);
474  CpuAuxTensorHandler converted_weights(offset_int_vec(ConvertedWeights), _converted_weights, tensors, false);
475 
476  // Pointer to current weights
477  const ITensor *cur_weights = weights;
478 
479  // Reshape of the weights (happens only once)
480  if(_needs_weights_reshape)
481  {
482  // Run reshape weights kernel and mark weights as unused
483  ITensorPack transpose_pack{ { ACL_SRC, weights }, { ACL_DST, reshaped_weights.get() } };
484  NEScheduler::get().schedule_op(_transpose_weights.get(), Window::DimY, _transpose_weights->window(), transpose_pack);
485 
486  cur_weights->mark_as_unused();
487  cur_weights = reshaped_weights.get();
488  }
489 
490  // Convert weights if needed (happens only once)
491  if(_needs_weights_conversion)
492  {
493  ITensorPack convert_pack{ { ACL_SRC, cur_weights }, { ACL_DST, converted_weights.get() } };
494  _convert_weights->run(convert_pack);
495 
496  cur_weights->mark_as_unused();
497  cur_weights = converted_weights.get();
498  }
499 
500  ITensorPack gemm_pack = tensors;
501  gemm_pack.add_const_tensor(ACL_SRC_1, cur_weights);
502 
503  // Prepare GEMM prepare and release unused weights
504  if(!_is_quantized_asymmetric)
505  {
506  _mm_gemm->prepare(gemm_pack);
507  }
508  else
509  {
510  _mm_gemmlowp->prepare(gemm_pack);
511  }
512 
513  _is_prepared = true;
514  }
515 }
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.
static constexpr size_t DimY
Alias for dimension 1 also known as Y dimension.
Definition: Window.h:45
int offset_int_vec(int offset)
Definition: MemoryHelpers.h:38
static IScheduler & get()
Access the scheduler singleton.
Definition: Scheduler.cpp:94

◆ run()

void run ( ITensorPack tensors)
overridevirtual

Run the kernels contained in the function.

Parameters
[in]tensorsVector that contains the tensors to operate on.

Reimplemented from INEOperator.

Definition at line 433 of file CpuFullyConnected.cpp.

References arm_compute::ACL_DST, arm_compute::ACL_SRC, arm_compute::ACL_SRC_0, arm_compute::ACL_SRC_1, ITensorPack::add_const_tensor(), CpuAuxTensorHandler::get(), ITensorPack::get_const_tensor(), arm_compute::offset_int_vec(), CpuFullyConnected::prepare(), and arm_compute::test::validation::src.

434 {
435  prepare(tensors);
436 
437  auto src = tensors.get_const_tensor(ACL_SRC_0);
438 
439  CpuAuxTensorHandler flattened_src(offset_int_vec(FlattenedSrc), _flattened_src, tensors, false);
440  CpuAuxTensorHandler transformed_wei(offset_int_vec(_trans_weights_idx), _trans_weights, tensors, false);
441 
442  // Linearize src if it comes from a convolutional layer
443  if(_is_fc_after_conv)
444  {
445  ITensorPack flatten_pack{ { ACL_SRC, src }, { ACL_DST, flattened_src.get() } };
446  _flatten->run(flatten_pack);
447  }
448 
449  ITensorPack gemm_pack = tensors;
450  gemm_pack.add_const_tensor(ACL_SRC_0, (_is_fc_after_conv) ? flattened_src.get() : src);
451  if(_needs_weights_reshape || _needs_weights_conversion)
452  {
453  gemm_pack.add_const_tensor(ACL_SRC_1, transformed_wei.get());
454  }
455 
456  // Run matrix multiply
457  if(_is_quantized_asymmetric)
458  {
459  _mm_gemmlowp->run(gemm_pack);
460  }
461  else
462  {
463  _mm_gemm->run(gemm_pack);
464  }
465 }
void prepare(ITensorPack &tensors) override
Prepare the function for executing.
SimpleTensor< float > src
Definition: DFT.cpp:155
int offset_int_vec(int offset)
Definition: MemoryHelpers.h:38

◆ validate()

Status validate ( const ITensorInfo src,
const ITensorInfo weights,
const ITensorInfo biases,
const ITensorInfo dst,
FullyConnectedLayerInfo  fc_info = FullyConnectedLayerInfo() 
)
static

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

Similar to CpuFullyConnected

Returns
a status

Definition at line 341 of file CpuFullyConnected.cpp.

References ActivationLayerInfo::activation(), FullyConnectedLayerInfo::activation_info, ITensorInfo::are_values_constant(), FullyConnectedLayerInfo::are_weights_reshaped, ARM_COMPUTE_RETURN_ERROR_ON, ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN, ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES, ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR, ARM_COMPUTE_RETURN_ON_ERROR, ARM_COMPUTE_UNUSED, ActivationLayerInfo::BOUNDED_RELU, Dimensions< T >::cbegin(), Dimensions< T >::cend(), ICloneable< T >::clone(), arm_compute::misc::shape_calculator::compute_flatten_shape(), arm_compute::misc::shape_calculator::compute_transposed_shape(), ITensorInfo::data_layout(), ITensorInfo::data_type(), ITensorInfo::dimension(), FullyConnectedLayerInfo::enable_fast_math, ActivationLayerInfo::enabled(), arm_compute::F16, arm_compute::F32, arm_compute::is_data_type_quantized(), ActivationLayerInfo::LU_BOUNDED_RELU, ITensorInfo::num_dimensions(), Dimensions< size_t >::num_max_dimensions, arm_compute::QASYMM8, arm_compute::QASYMM8_SIGNED, ActivationLayerInfo::RELU, FullyConnectedLayerInfo::retain_internal_weights, arm_compute::S32, arm_compute::test::validation::src, ITensorInfo::tensor_shape(), FullyConnectedLayerInfo::transpose_weights, CpuConvertFullyConnectedWeights::validate(), CpuTransposeKernel::validate(), CpuFlatten::validate(), and FullyConnectedLayerInfo::weights_trained_layout.

Referenced by CpuFullyConnected::configure(), and NEFullyConnectedLayer::validate().

343 {
344  ARM_COMPUTE_UNUSED(fc_info.retain_internal_weights);
348  ARM_COMPUTE_RETURN_ERROR_ON(weights->num_dimensions() > 2);
349  ARM_COMPUTE_RETURN_ERROR_ON(fc_info.activation_info.enabled() && is_data_type_quantized(src->data_type()) && fc_info.activation_info.activation() != ActivationLayerInfo::ActivationFunction::RELU
350  && fc_info.activation_info.activation() != ActivationLayerInfo::ActivationFunction::BOUNDED_RELU && fc_info.activation_info.activation() != ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU);
351  ARM_COMPUTE_RETURN_ERROR_ON(!weights->are_values_constant() && (!fc_info.are_weights_reshaped || fc_info.transpose_weights));
352 
353  bool weights_reshaped = fc_info.transpose_weights ? fc_info.are_weights_reshaped : true;
354  bool is_fc_after_conv = true;
355 
356  const ITensorInfo &flatten_src = TensorInfo(src->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(compute_flatten_shape(src)));
357  const ITensorInfo &reshaped_weights = TensorInfo(weights->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(compute_transposed_shape(*weights)));
358  const ITensorInfo &converted_weights = weights_reshaped ? TensorInfo(weights->clone()->set_is_resizable(true).reset_padding()) : TensorInfo(*reshaped_weights.clone());
359 
360  // With the Fully Connected layer we can have 4 different cases:
361  // 1) Convolution layer -> Fully Connected layer without batches
362  // 2) Fully Connected layer -> Fully Connected layer without batches
363  // 3) Convolution layer -> Fully Connected layer with batches
364  // 4) Fully Connected layer -> Fully Connected layer with batches
365 
366  const ITensorInfo *src_to_use = src;
367  const ITensorInfo *weights_to_use = weights;
368 
369  // Check if we have a fully connected layer with batches
370  const bool is_batched_fc_layer = dst->dimension(1) > 1;
371 
372  if(biases != nullptr)
373  {
374  ARM_COMPUTE_RETURN_ERROR_ON(biases->num_dimensions() > 1);
375  if(is_data_type_quantized(src->data_type()))
376  {
378  }
379  else
380  {
382  }
383  }
384 
385  if(is_batched_fc_layer)
386  {
387  is_fc_after_conv = (TensorShape::num_max_dimensions >= 4) && (std::equal(src->tensor_shape().cbegin() + 3,
388  src->tensor_shape().cend(),
389  dst->tensor_shape().cbegin() + 1));
390  }
391  else
392  {
393  is_fc_after_conv = src->num_dimensions() > 1;
394  }
395 
396  if(!weights_reshaped)
397  {
398  // Validate reshape weights kernel
400  weights_to_use = &reshaped_weights;
401  }
402 
403  if(is_fc_after_conv && (src->data_layout() != fc_info.weights_trained_layout))
404  {
405  // Validate convert weights kernel
407  &converted_weights,
408  src->tensor_shape(),
409  fc_info.weights_trained_layout));
410  weights_to_use = &converted_weights;
411  }
412 
413  if(is_fc_after_conv)
414  {
415  // Fully Connected layer after a Convolution Layer without batches
416  ARM_COMPUTE_RETURN_ERROR_ON((weights_to_use->dimension(1) != (src->dimension(0) * src->dimension(1) * src->dimension(2))));
417 
418  // Validate flatten kernel
420  src_to_use = &flatten_src;
421  }
422  else
423  {
424  // Fully Connected layer after a Fully Connected Layer without batches
425  ARM_COMPUTE_RETURN_ERROR_ON(src->dimension(0) != weights_to_use->dimension(1));
426  }
427  // Validate matrix multiply kernel
428  ARM_COMPUTE_RETURN_ON_ERROR(validate_mm(src_to_use, weights_to_use, biases, dst, fc_info.activation_info, fc_info.enable_fast_math));
429 
430  return Status{};
431 }
bool is_data_type_quantized(DataType dt)
Check if a given data type is of quantized type.
Definition: Utils.h:1030
#define ARM_COMPUTE_RETURN_ON_ERROR(status)
Checks if a status contains an error and returns it.
Definition: Error.h:204
1 channel, 1 F32 per channel
#define ARM_COMPUTE_RETURN_ERROR_ON(cond)
If the condition is true, an error is returned.
Definition: Error.h:296
SimpleTensor< float > src
Definition: DFT.cpp:155
1 channel, 1 F16 per channel
static Status validate(const ITensorInfo *src, const ITensorInfo *dst)
Static function to check if given info will lead to a valid configuration.
Definition: CpuFlatten.cpp:42
TensorShape compute_transposed_shape(const ITensorInfo &input)
Calculate the transposed shape of a tensor.
#define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...)
Definition: Validate.h:159
1 channel, 1 S32 per channel
TensorShape compute_flatten_shape(const ITensorInfo *input)
Calculate the flattened output shape of a tensor.
static Status validate(const ITensorInfo *src, const ITensorInfo *dst, const TensorShape &original_src_shape, DataLayout data_layout)
Static function to check if given info will lead to a valid configuration.
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
static Status validate(const ITensorInfo *src, const ITensorInfo *dst)
Static function to check if given info will lead to a valid configuration.
quantized, asymmetric fixed-point 8-bit number unsigned
#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...)
Definition: Validate.h:541
#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c,...)
Definition: Validate.h:788
quantized, asymmetric fixed-point 8-bit number signed
static constexpr size_t num_max_dimensions
Number of dimensions the tensor has.
Definition: Dimensions.h:46

◆ workspace()

experimental::MemoryRequirements workspace ( ) const
overridevirtual

Return the memory requirements required by the workspace.

Reimplemented from INEOperator.

Definition at line 517 of file CpuFullyConnected.cpp.

518 {
519  return _aux_mem;
520 }

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