Compute Library
 20.08
NEGEMMConvolutionLayer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2020 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 
27 #include "arm_compute/core/Utils.h"
32 
33 #include <set>
34 #include <tuple>
35 
36 namespace arm_compute
37 {
39 
41  : _weights_reshape_kernel()
42 {
43 }
44 
46 {
47  // Perform validation step
50  (biases != nullptr) ? biases->info() : nullptr,
51  output->info()));
52  const bool append_biases = (biases != nullptr) && !is_data_type_quantized_asymmetric(weights->info()->data_type());
53  const ITensor *biases_to_use = (append_biases) ? biases : nullptr;
54 
55  _weights_reshape_kernel.configure(weights, biases_to_use, output);
56 
58 }
59 
61 {
66  ARM_COMPUTE_RETURN_ERROR_ON(weights->num_dimensions() > 4);
67 
68  if(biases != nullptr)
69  {
70  const int idx_kernels = get_data_layout_dimension_index(weights->data_layout(), DataLayoutDimension::BATCHES);
73  ARM_COMPUTE_RETURN_ERROR_ON(biases->dimension(0) != weights->dimension(idx_kernels));
75  }
76 
77  if((output != nullptr) && (output->total_size() != 0))
78  {
80 
82  }
83 
84  return Status{};
85 }
86 
88 {
89  NEScheduler::get().schedule(&_weights_reshape_kernel, 3);
90 }
91 
92 NEGEMMConvolutionLayer::NEGEMMConvolutionLayer(const std::shared_ptr<IMemoryManager> &memory_manager, IWeightsManager *weights_manager)
93  : _memory_group(memory_manager), _weights_manager(weights_manager), _reshape_weights(), _reshape_weights_managed(), _im2col_kernel(), _mm_gemm(memory_manager), _mm_gemmlowp(memory_manager),
94  _col2im_kernel(), _reshape_layer(), _original_weights(nullptr), _im2col_output(), _weights_reshaped(), _gemm_output(), _tmp_output(), _data_layout(DataLayout::NCHW), _skip_im2col(false),
95  _skip_col2im(false), _is_quantized(false), _is_prepared(false)
96 {
97 }
98 
99 void NEGEMMConvolutionLayer::configure_mm(const ITensor *input, const ITensor *weights, const ITensor *biases, ITensor *output, const ActivationLayerInfo &act_info, int gemm_3d_depth)
100 {
102  ARM_COMPUTE_ERROR_THROW_ON(validate_mm(input->info(), weights->info(), biases == nullptr ? nullptr : biases->info(), output == nullptr ? nullptr : output->info(),
103  act_info, gemm_3d_depth, _skip_im2col));
104 
105  // Create GEMMInfo structure
106  const GEMMInfo &gemm_info = GEMMInfo(false, false, true /* Reshape weights only for the first run */,
107  gemm_3d_depth, _skip_im2col /* Reinterpret the input as 3D if im2col is skipped */,
108  false, GEMMLowpOutputStageInfo(), false, false, act_info);
109 
110  // Supported activations in GEMM
111  const std::set<ActivationLayerInfo::ActivationFunction> supported_acts = { ActivationLayerInfo::ActivationFunction::RELU,
114  };
115 
116  if(_is_quantized)
117  {
118  // Since we need negative offsets for computing convolution, we need to change QuantizationInfo()
119  // Extract and negate input and weights offset
120  const QuantizationInfo iqinfo = input->info()->quantization_info();
121  const QuantizationInfo wqinfo = weights->info()->quantization_info();
122  const QuantizationInfo oqinfo = (output->info()->total_size() == 0) ? iqinfo : output->info()->quantization_info();
123  const UniformQuantizationInfo uiqinfo = iqinfo.uniform();
124  const UniformQuantizationInfo uoqinfo = oqinfo.uniform();
125  const DataType data_type = input->info()->data_type();
126 
127  input->info()->set_quantization_info(QuantizationInfo(uiqinfo.scale, -uiqinfo.offset));
129  {
130  const UniformQuantizationInfo uwqinfo = wqinfo.uniform();
131  weights->info()->set_quantization_info(QuantizationInfo(uwqinfo.scale, -uwqinfo.offset));
132  }
133 
134  // Merge activation with output stage
135  PixelValue type_min{};
136  PixelValue type_max{};
137  std::tie(type_min, type_max) = get_min_max(data_type);
138  int32_t min_activation = type_min.get<int32_t>();
139  int32_t max_activation = type_max.get<int32_t>();
140 
141  if(supported_acts.count(act_info.activation()) != 0)
142  {
143  std::tie(min_activation, max_activation) = get_quantized_activation_min_max(act_info, data_type, uoqinfo);
144  }
145 
146  GEMMLowpOutputStageInfo output_info;
148  output_info.gemmlowp_offset = uoqinfo.offset;
149  output_info.gemmlowp_min_bound = min_activation;
150  output_info.gemmlowp_max_bound = max_activation;
151  output_info.is_quantized_per_channel = (weights->info()->data_type() == DataType::QSYMM8_PER_CHANNEL);
153 
154  _mm_gemmlowp.configure(input, weights, biases, output, GEMMInfo(false, false, true, gemm_3d_depth, _skip_im2col, false, output_info));
155 
156  // Revert back QuantizatioInfo as input and weights could be used in other convolution layers
157  input->info()->set_quantization_info(iqinfo);
158  weights->info()->set_quantization_info(wqinfo);
159  }
160  else
161  {
162  // Configure matrix multiply function
163  _mm_gemm.configure(input, weights, biases, output, 1.0f, 0.0f, gemm_info);
164  }
165 }
166 
167 Status NEGEMMConvolutionLayer::validate_mm(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output,
168  const ActivationLayerInfo &act_info, int gemm_3d_depth, bool skip_im2col)
169 {
170  const DataType data_type = input->data_type();
171  const bool is_quantized = is_data_type_quantized_asymmetric(data_type);
172  const bool is_activation_enabled = act_info.enabled();
173 
174  // Create GEMMInfo structure
175  const GEMMInfo gemm_info = GEMMInfo(false, false, true /* Reshape weights only for the first run */,
176  gemm_3d_depth, skip_im2col /* Reinterpret the input as 3D if im2col is skipped */,
177  false, GEMMLowpOutputStageInfo(), false, false, act_info);
178 
179  if(is_quantized)
180  {
181  // Since we need negative offsets for computing convolution, we need to change QuantizationInfo()
182  // Extract and negate input and weights offset
183  const QuantizationInfo &iqinfo = input->quantization_info();
184  const QuantizationInfo &wqinfo = weights->quantization_info();
185  const QuantizationInfo &oqinfo = (output->total_size() == 0) ? iqinfo : output->quantization_info();
186  const UniformQuantizationInfo uoqinfo = oqinfo.uniform();
187 
188  // Merge activation with output stage
189  PixelValue type_min{};
190  PixelValue type_max{};
191  std::tie(type_min, type_max) = get_min_max(data_type);
192  int32_t min_activation = type_min.get<int32_t>();
193  int32_t max_activation = type_max.get<int32_t>();
194 
195  const std::set<ActivationLayerInfo::ActivationFunction> supported_acts = { ActivationLayerInfo::ActivationFunction::RELU,
198  };
199  if(is_activation_enabled && supported_acts.count(act_info.activation()) != 0)
200  {
201  std::tie(min_activation, max_activation) = get_quantized_activation_min_max(act_info, data_type, uoqinfo);
202  }
203 
204  GEMMLowpOutputStageInfo output_info;
206  output_info.gemmlowp_offset = uoqinfo.offset;
207  output_info.gemmlowp_min_bound = min_activation;
208  output_info.gemmlowp_max_bound = max_activation;
209  output_info.is_quantized_per_channel = (weights->data_type() == DataType::QSYMM8_PER_CHANNEL);
211 
212  // Perform validation step on GEMMLowp
213  std::unique_ptr<ITensorInfo> input_qa = input->clone();
214  std::unique_ptr<ITensorInfo> weights_qa = weights->clone();
215  input_qa->set_quantization_info(QuantizationInfo(iqinfo.uniform().scale, -iqinfo.uniform().offset));
216  weights_qa->set_quantization_info(QuantizationInfo(wqinfo.uniform().scale, -wqinfo.uniform().offset));
217  return NEGEMMLowpMatrixMultiplyCore::validate(input_qa.get(), weights_qa.get(), biases, output, GEMMInfo(false, false, true, gemm_3d_depth, skip_im2col, false, output_info));
218  }
219  else
220  {
221  // Perform validation step on Matrix multiply function
222  return NEGEMM::validate(input, weights, nullptr, output, 1.0f, 0.0f, gemm_info);
223  }
224 }
225 
226 Status NEGEMMConvolutionLayer::validate_gemm3d(const ITensorInfo *input_info, const ITensorInfo *weights_info, const ActivationLayerInfo &act_info, int gemm_3d_depth, bool skip_im2col)
227 {
228  const DataType data_type = input_info->data_type();
229  const unsigned int mult_y = skip_im2col ? 1U : gemm_3d_depth;
230  const unsigned int mult_z = skip_im2col ? gemm_3d_depth : 1U;
231 
232  // Set dummy tensor shapes for the validation
233  const TensorInfo dummy_input_info(TensorShape(4U, 4U * mult_y, 1U * mult_z), 1, data_type, input_info->quantization_info());
234  const TensorInfo dummy_weights_info(TensorShape(4U, 4U), 1, data_type, weights_info->quantization_info());
235  const TensorInfo dummy_output_info(TensorShape(4U, 4U, gemm_3d_depth), 1, data_type, input_info->quantization_info());
236 
237  return validate_mm(&dummy_input_info, &dummy_weights_info, nullptr, &dummy_output_info, act_info, gemm_3d_depth, skip_im2col);
238 }
239 
241  const Size2D &dilation, const ActivationLayerInfo &act_info, unsigned int num_groups)
242 {
246  weights->info(),
247  biases != nullptr ? biases->info() : nullptr,
248  output->info(),
249  conv_info,
250  weights_info,
251  dilation,
252  act_info,
253  num_groups));
254 
255  const DataType data_type = input->info()->data_type();
256  const DataLayout data_layout = input->info()->data_layout();
260 
261  const unsigned int kernel_width = weights->info()->dimension(idx_width);
262  const unsigned int kernel_height = weights->info()->dimension(idx_height);
263 
264  _is_prepared = weights_info.retain_internal_weights();
265  _original_weights = weights;
266  _is_quantized = is_data_type_quantized_asymmetric(input->info()->data_type());
267  _data_layout = data_layout;
268  _skip_im2col = (data_layout == DataLayout::NHWC && kernel_width == 1 && kernel_height == 1 && conv_info.stride().first == 1 && conv_info.stride().second == 1);
269 
270  const ITensor *gemm_input_to_use = input;
271  ITensor *gemm_output_to_use = output;
272 
273  // Get convolved dimensions
274  unsigned int conv_w = 0;
275  unsigned int conv_h = 0;
276  std::tie(conv_w, conv_h) = scaled_dimensions(input->info()->dimension(idx_width),
277  input->info()->dimension(idx_height),
278  kernel_width,
279  kernel_height,
280  conv_info,
281  dilation);
282 
283  // Check if GEMM3D is supported
285  {
286  _skip_col2im = bool(validate_gemm3d(input->info(), weights->info(), act_info, conv_h, true));
287  // If not supported, we need to perform im2col and col2im (or reshape layer)
288  if(!_skip_col2im)
289  {
290  _skip_im2col = false;
291  }
292  }
293  else
294  {
295  _skip_col2im = false;
296  }
297 
298  // Get parameters from conv_info
299  unsigned int stride_x = 0;
300  unsigned int stride_y = 0;
301  std::tie(stride_x, stride_y) = conv_info.stride();
302 
303  unsigned int mat_weights_cols = weights->info()->dimension(idx_kernels);
304 
305  // _weights_reshaped will be auto configured in the kernel.
306  // Just append biases and do not transpose 1xW as it will be reshaped in NEGEMM
307  const ITensor *weights_to_use = weights;
308 
309  if(_weights_manager && _weights_manager->are_weights_managed(weights))
310  {
311  _reshape_weights_managed.configure(weights, nullptr);
312  weights_to_use = _weights_manager->acquire(weights, &_reshape_weights_managed);
313  }
314  else
315  {
316  _reshape_weights.configure(weights, nullptr, &_weights_reshaped);
317  weights_to_use = &_weights_reshaped;
318  }
319 
320  // Create tensor to store im2col reshaped inputs
321  if(!_skip_im2col)
322  {
323  _memory_group.manage(&_im2col_output);
324 
325  // Configure
326  _im2col_kernel.configure(input, &_im2col_output, Size2D(kernel_width, kernel_height), conv_info, false, dilation);
327 
328  // Update GEMM input
329  gemm_input_to_use = &_im2col_output;
330  }
331 
332  // Create temporary GEMM output tensor in case we cannot skip col2im
334  if(!_skip_col2im)
335  {
336  TensorShape shape_gemm;
337 
338  // Calculate GEMM output shape
339  shape_gemm = _im2col_output.info()->tensor_shape();
340  shape_gemm.set(0, mat_weights_cols);
341  shape_gemm.set(1, conv_w * conv_h);
342 
343  // FIXME: input->clone() doesn't work with subtensors for grouped convolutions.
344  TensorInfo info_gemm(shape_gemm, 1, output_data_type);
345  info_gemm.set_quantization_info(output->info()->quantization_info()).set_data_layout(input->info()->data_layout());
346  _gemm_output.allocator()->init(info_gemm);
347  _memory_group.manage(&_gemm_output);
348 
349  // Update GEMM output
350  gemm_output_to_use = &_gemm_output;
351  }
352 
353  // Configure GEMM
354  // In case we need to skip col2im, GEMM3D (gemm_3d_depth != 0) must be called in order to avoid reshaping the output matrix
355  const unsigned int gemm_3d_depth = _skip_col2im ? conv_h : 0;
356  configure_mm(gemm_input_to_use, weights_to_use, biases, gemm_output_to_use, act_info, gemm_3d_depth);
357 
358  if(!_skip_im2col)
359  {
360  _im2col_output.allocator()->allocate();
361  }
362 
363  if(!_skip_col2im)
364  {
365  if(_data_layout == DataLayout::NCHW)
366  {
367  // Configure col2im
368  _col2im_kernel.configure(gemm_output_to_use, output, Size2D(conv_w, conv_h));
369  }
370  else
371  {
372  // Configure reshape layer
373  _reshape_layer.configure(gemm_output_to_use, output);
374  }
375  }
376 
377  if(_is_quantized && !_skip_col2im)
378  {
379  _tmp_output.allocator()->allocate();
380  }
381 
382  if(!_skip_col2im || _is_quantized)
383  {
384  _gemm_output.allocator()->allocate();
385  }
386 
387  ARM_COMPUTE_ERROR_ON_MSG((output->info()->dimension(idx_width) != conv_w) || (output->info()->dimension(idx_height) != conv_h),
388  "Output shape does not match the expected one");
389 }
390 
392  const WeightsInfo &weights_info, const Size2D &dilation, const ActivationLayerInfo &act_info, unsigned int num_groups)
393 {
395  ARM_COMPUTE_RETURN_ERROR_ON_MSG(weights_info.are_reshaped(), "Weights already reshaped are not supported!");
399  ARM_COMPUTE_RETURN_ERROR_ON_MSG(num_groups > 1, "Grouping (num_groups != 1) is not supported on NEON");
400 
401  const DataLayout data_layout = input->data_layout();
402  const DataType data_type = input->data_type();
407 
408  const unsigned int kernel_width = weights->dimension(idx_width);
409  const unsigned int kernel_height = weights->dimension(idx_height);
410 
411  TensorInfo im2col_reshaped_info{};
412  TensorInfo info_gemm{};
413  TensorInfo tmp_info{};
414  TensorInfo weights_reshaped_info{};
415  const ITensorInfo *gemm_input_to_use = input;
416  const ITensorInfo *gemm_output_to_use = output;
417  const ITensorInfo *weights_to_use = weights;
418 
419  const bool append_bias = false;
420  const bool is_quantized = is_data_type_quantized_asymmetric(data_type);
421  const bool is_bf16 = data_type == DataType::BFLOAT16;
422  bool skip_im2col = (data_layout == DataLayout::NHWC && kernel_width == 1 && kernel_height == 1 && conv_info.stride().first == 1 && conv_info.stride().second == 1);
423 
424  // Get convolved dimensions
425  unsigned int conv_w = 0;
426  unsigned int conv_h = 0;
427 
428  std::tie(conv_w, conv_h) = scaled_dimensions(input->dimension(idx_width),
429  input->dimension(idx_height),
430  kernel_width,
431  kernel_height,
432  conv_info,
433  dilation);
434 
435  // Check if GEMM3D is supported
436  bool skip_col2im = false;
438  {
439  skip_col2im = bool(validate_gemm3d(input, weights, act_info, conv_h, true));
440  // If not supported, we need to perform im2col and col2im (or reshape layer)
441  if(!skip_col2im)
442  {
443  skip_im2col = false;
444  }
445  }
446 
447  if(skip_col2im)
448  {
449  // If not supported, we need to perform im2col and col2im (or reshape layer)
450  if(!bool(validate_gemm3d(input, weights, act_info, conv_h, skip_im2col)))
451  {
452  skip_im2col = false;
453  skip_col2im = false;
454  }
455  }
456 
457  ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(idx_channel) != input->dimension(idx_channel));
458  ARM_COMPUTE_RETURN_ERROR_ON(weights->num_dimensions() > 4);
459 
460  // Validate biases
461  if(biases != nullptr)
462  {
463  if(is_quantized)
464  {
466  }
467  else if(is_bf16)
468  {
470  }
471  else
472  {
474  }
475  ARM_COMPUTE_RETURN_ERROR_ON(biases->dimension(0) != weights->dimension(idx_kernels));
477  }
478 
479  unsigned int mat_weights_cols = weights->dimension(idx_kernels);
480  unsigned int mat_weights_rows = weights->dimension(idx_width) * weights->dimension(idx_height) * weights->dimension(idx_channel);
481 
482  // Output tensor auto inizialization if not yet initialized
484  weights_reshaped_info = TensorInfo(compute_weights_reshaped_shape(*weights, append_bias), 1, data_type);
485  weights_reshaped_info.set_quantization_info(weights->quantization_info());
486  weights_to_use = &weights_reshaped_info;
487 
488  if(!skip_im2col)
489  {
490  // Create tensor info for im2col reshaped inputs
491  // For NEON the batch size is on the fourth dimension
492  // TODO (giaiod01): Auto-initialize the output shape of im2col COMPMID-1482
493  TensorShape shape_im2col = input->tensor_shape();
494  shape_im2col.set(0, mat_weights_rows);
495  shape_im2col.set(1, conv_w * conv_h);
496  shape_im2col.set(2, 1);
497 
498  im2col_reshaped_info = TensorInfo(shape_im2col, 1, data_type);
499  im2col_reshaped_info.set_quantization_info(input->quantization_info());
500 
501  ARM_COMPUTE_RETURN_ON_ERROR(NEIm2ColKernel::validate(input, &im2col_reshaped_info, Size2D(kernel_width, kernel_height), conv_info, append_bias, dilation));
502  gemm_input_to_use = &im2col_reshaped_info;
503  }
504 
505  // Create temporary GEMM output tensor in case we cannot skip col2im
507  if(!skip_col2im)
508  {
509  TensorShape shape_gemm = gemm_input_to_use->tensor_shape();
510  shape_gemm.set(0, mat_weights_cols);
511  shape_gemm.set(1, conv_w * conv_h);
512  info_gemm = TensorInfo(shape_gemm, 1, output_data_type);
513  }
514  else
515  {
516  info_gemm = TensorInfo(output->tensor_shape(), 1, output_data_type);
517  }
518  info_gemm.set_quantization_info(output->quantization_info()).set_data_layout(input->data_layout());
519  gemm_output_to_use = &info_gemm;
520  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));
521 
522  // Validate Col2Im/ReshapeLayer
523  if(!skip_col2im && (data_layout == DataLayout::NCHW))
524  {
525  ARM_COMPUTE_RETURN_ON_ERROR(NECol2ImKernel::validate(gemm_output_to_use, output, Size2D(conv_w, conv_h)));
526  }
527 
528  return Status{};
529 }
530 
532 {
533  prepare();
534 
535  MemoryGroupResourceScope scope_mg(_memory_group);
536 
537  if(!_skip_im2col)
538  {
539  // Run input reshaping
540  unsigned int y_dim = get_data_layout_dimension_index(_data_layout, DataLayoutDimension::HEIGHT);
541  NEScheduler::get().schedule(&_im2col_kernel, y_dim);
542  }
543 
544  // Runs NEGEMM or NEGEMMLowpMatrixMultiplyCore functions
545  if(_is_quantized)
546  {
547  // Run gemmlowp
548  _mm_gemmlowp.run();
549  }
550  else
551  {
552  // Run gemm
553  _mm_gemm.run();
554  }
555 
556  // Reshape output matrix
557  if(!_skip_col2im)
558  {
559  if(_data_layout == DataLayout::NCHW)
560  {
561  NEScheduler::get().schedule(&_col2im_kernel, Window::DimY);
562  }
563  else
564  {
565  _reshape_layer.run();
566  }
567  }
568 }
569 
571 {
572  if(!_is_prepared)
573  {
574  if(_weights_manager && _weights_manager->are_weights_managed(_original_weights))
575  {
576  _weights_manager->run(_original_weights, &_reshape_weights_managed);
577  }
578  else
579  {
580  // Run weights reshaping and mark original weights tensor as unused
581  _weights_reshaped.allocator()->allocate();
582  _reshape_weights.run();
583  _original_weights->mark_as_unused();
584  }
585 
586  // Prepare GEMM
587  _is_quantized ? _mm_gemmlowp.prepare() : _mm_gemm.prepare();
588  if(!_weights_reshaped.is_used())
589  {
590  _weights_reshaped.allocator()->free();
591  }
592 
593  _is_prepared = true;
594  }
595 }
596 } // namespace arm_compute
void configure(const ITensor *input, const ITensor *bias, ITensor *output)
Set the input and output of the kernel.
virtual size_t num_dimensions() const =0
The number of dimensions of the tensor (rank)
void prepare() override
Prepare the function for executing.
Shape of a tensor.
Definition: TensorShape.h:39
const DataLayout data_layout
Definition: Im2Col.cpp:146
Quantize using a fixed point multiplication.
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.
#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
virtual DataType data_type() const =0
Data type used for each element of the tensor.
bool is_used() const
Flags if the tensor is used or not.
Definition: ITensor.cpp:163
#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
#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
Activation Layer Information class.
Definition: Types.h:1517
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.
Copyright (c) 2017-2020 Arm Limited.
void configure(const ITensor *input, ITensor *output, const Size2D &convolved_dims)
Set the input and output of the kernel.
static Status validate(const ITensorInfo *input, const ITensorInfo *biases, const ITensorInfo *output)
Static function to check if given info will lead to a valid configuration of NEWeightsReshapeKernel.
1 channel, 1 F16 per channel
std::pair< unsigned int, unsigned int > scaled_dimensions(int width, int height, int kernel_width, 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:395
ITensorInfo & set_quantization_info(const QuantizationInfo &quantization_info) override
Set the quantization settings (scale and offset) of the tensor.
Definition: TensorInfo.cpp:372
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
Convolution Layer Weights Information class.
Definition: Types.h:1694
void mark_as_unused() const
Marks a tensor as unused.
Definition: ITensor.cpp:168
1 channel, 1 S32 per channel
void manage(IMemoryManageable *obj) override
Sets a object to be managed by the given memory group.
Definition: MemoryGroup.h:79
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...
16-bit brain floating-point number
bool are_weights_managed(const ITensor *weights)
Check if the weights are managed.
static Status validate(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, float alpha, float beta, const GEMMInfo &gemm_info=GEMMInfo())
Static function to check if given info will lead to a valid configuration of NEGEMM.
Definition: NEGEMM.cpp:163
void run() override
Run the kernels contained in the function.
Definition: NEGEMM.cpp:281
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
void configure(const ITensor *a, const ITensor *b, const ITensor *c, ITensor *output, const GEMMInfo &gemm_info=GEMMInfo())
Initialise the kernel's inputs, output.
bool is_data_type_quantized_per_channel(DataType dt)
Check if a given data type is of per channel type.
Definition: Utils.h:1198
virtual const TensorShape & tensor_shape() const =0
Size for each dimension of the tensor.
std::pair< int32_t, int32_t > get_quantized_activation_min_max(ActivationLayerInfo act_info, DataType data_type, UniformQuantizationInfo oq_info)
Returns a pair of minimum and maximum values for a quantized activation.
Definition: Utils.cpp:459
Status calculate_quantized_multipliers(const QuantizationInfo &iq_info, const QuantizationInfo &wq_info, const QuantizationInfo &oq_info, GEMMLowpOutputStageInfo &stage_info)
Calculate quantized representation of per-channel multipliers.
void run() override
Run the kernels contained in the function.
quantized, asymmetric fixed-point 8-bit number unsigned
#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.
UniformQuantizationInfo uniform() const
Return per layer quantization info.
GEMMLowp output stage info.
Definition: Types.h:1881
virtual ITensorInfo * info() const =0
Interface to be implemented by the child class to return the tensor's metadata.
Padding and stride information class.
Definition: Types.h:689
virtual ITensorInfo & set_quantization_info(const QuantizationInfo &quantization_info)=0
Set the quantization settings (scale and offset) of the tensor.
void free() override
Free allocated CPU memory.
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.
Weights manager interface to handle weights transformations.
virtual QuantizationInfo quantization_info() const =0
Get the quantization settings (scale and offset) of the tensor.
void run() override
Run the kernels contained in the function.
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:1143
quantized, symmetric per channel fixed-point 8-bit number
__constant DATA_TYPE16 type_min
Definition: minmaxloc.cl:46
#define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...)
Definition: Validate.h:163
static constexpr size_t DimY
Alias for dimension 1 also known as Y dimension.
Definition: Window.h:45
NEGEMMConvolutionLayer(const std::shared_ptr< IMemoryManager > &memory_manager=nullptr, IWeightsManager *weights_manager=nullptr)
Constructor.
void run() override
Run the kernels contained in the function.
#define ARM_COMPUTE_ERROR_ON_NULLPTR(...)
Definition: Validate.h:161
Memory group resources scope handling class.
Definition: IMemoryGroup.h:82
virtual size_t total_size() const =0
Returns the total size of the tensor in bytes.
virtual void schedule(ICPPKernel *kernel, const Hints &hints)=0
Runs the kernel in the same thread as the caller synchronously.
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.
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.
void configure(const ITensor *a, const ITensor *b, const ITensor *c, ITensor *d, float alpha, float beta, const GEMMInfo &gemm_info=GEMMInfo())
Initialise the kernel's inputs, output.
Definition: NEGEMM.cpp:51
void prepare() override
Prepare the function for executing.
Definition: NEGEMM.cpp:331
__constant DATA_TYPE16 type_max
Definition: minmaxloc.cl:47
void configure(const ITensor *input, ITensor *output)
Initialise the kernel's inputs and outputs.
#define ARM_COMPUTE_RETURN_ERROR_ON_MSG(cond, msg)
If the condition is true, an error is returned.
Definition: Error.h:244
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
static Status validate(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, const GEMMInfo &gemm_info=GEMMInfo())
Static function to check if given info will lead to a valid configuration of NEGEMMLowpMatrixMultiply...
GEMM information class.
Definition: Types.h:1932
ITensor * run(const ITensor *weights, ITransformWeights *weights_transform)
Run the reshape function.
ActivationFunction activation() const
Get the type of activation function.
Definition: Types.h:1552
quantized, asymmetric fixed-point 8-bit number signed
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:332
void configure(const ITensor *weights, const ITensor *biases, ITensor *output)
Set the input and output tensors.
DataType
Available data types.
Definition: Types.h:77
DataLayout
[DataLayout enum definition]
Definition: Types.h:120
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.
std::tuple< PixelValue, PixelValue > get_min_max(DataType dt)
Compute the mininum and maximum values a data type can take.
Definition: Utils.h:560
void run() override
Run the kernels contained in the function.
ITensor * acquire(const ITensor *weights, ITransformWeights *weights_transform)
Acquire the requested reshape tensor of the selected weights.
static IScheduler & get()
Access the scheduler singleton.
Definition: Scheduler.cpp:95