Compute Library
 20.08
CLGEMMDeconvolutionLayer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019-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 
31 
32 #include <memory>
33 #include <tuple>
34 
35 namespace arm_compute
36 {
37 namespace
38 {
39 std::pair<Coordinates, Coordinates> compute_start_end_slice_coordinates(const ITensorInfo &output_info, const PadStrideInfo &deconv_info, bool is_nchw)
40 {
41  Coordinates start;
42  Coordinates end;
43 
44  if(is_nchw)
45  {
46  start.set(0, deconv_info.pad_left());
47  start.set(1, deconv_info.pad_top());
48  end.set(0, output_info.dimension(0) - deconv_info.pad_right());
49  end.set(1, output_info.dimension(1) - deconv_info.pad_bottom());
50  }
51  else
52  {
53  start.set(0, 0);
54  start.set(1, deconv_info.pad_left());
55  start.set(2, deconv_info.pad_top());
56 
57  end.set(0, output_info.dimension(0));
58  end.set(1, output_info.dimension(1) - deconv_info.pad_right());
59  end.set(2, output_info.dimension(2) - deconv_info.pad_bottom());
60  }
61 
62  return { start, end };
63 }
64 Status construct_gemmlowp_output_stage(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *output, GEMMLowpOutputStageInfo &output_stage_info)
65 {
66  const auto data_type = input->data_type();
67 
69  {
70  const UniformQuantizationInfo iq_info = input->quantization_info().uniform();
71  const UniformQuantizationInfo wq_info = weights->quantization_info().uniform();
72  const UniformQuantizationInfo oq_info = output->quantization_info().uniform();
73 
74  float multiplier = iq_info.scale * wq_info.scale / oq_info.scale;
75  int output_multiplier(0);
76  int output_shift(0);
77  ARM_COMPUTE_RETURN_ON_ERROR(quantization::calculate_quantized_multiplier(multiplier, &output_multiplier, &output_shift));
78 
80  output_stage_info.gemmlowp_multiplier = output_multiplier;
81  output_stage_info.gemmlowp_shift = output_shift;
82  output_stage_info.gemmlowp_offset = oq_info.offset;
83  const auto min_max_bound = get_min_max(data_type);
84  output_stage_info.gemmlowp_min_bound = (std::get<0>(min_max_bound)).get<int32_t>();
85  output_stage_info.gemmlowp_max_bound = (std::get<1>(min_max_bound)).get<int32_t>();
86  output_stage_info.output_data_type = data_type;
87  }
88  return Status{};
89 }
90 
91 } // namespace
92 
93 CLGEMMDeconvolutionLayer::CLGEMMDeconvolutionLayer(std::shared_ptr<IMemoryManager> memory_manager) // NOLINT
94  : _memory_group(std::move(memory_manager)),
95  _mm_gemm(),
96  _mm_gemmlowp(),
97  _gemmlowp_output_stage(),
98  _permute_input_to_nhwc(),
99  _permute_weights_to_nhwc(),
100  _reshape_weights(),
101  _transpose_weights(),
102  _deconv_reshape(),
103  _slice_gemm(),
104  _gemmlowp_final(),
105  _reshaped_weights(),
106  _reshaped_weights_t(),
107  _permuted_input(),
108  _permuted_weights(),
109  _gemm_output(),
110  _slice_gemm_input(),
111  _original_weights(),
112  _is_prepared(false),
113  _padded_input(false),
114  _is_nchw(false),
115  _is_quantized(false)
116 {
117 }
118 
120 {
125 
126  DataLayout data_layout = input->data_layout();
127  const bool padded_input = deconv_info.pad_bottom() > 0 || deconv_info.pad_left() > 0 || deconv_info.pad_right() > 0 || deconv_info.pad_top() > 0;
128  const bool is_nchw = input->data_layout() == DataLayout::NCHW;
129  const bool is_quantized = is_data_type_quantized_asymmetric(input->data_type());
130 
134 
135  ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(idx_w) != deconv_info.stride().first);
136  ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(idx_h) != deconv_info.stride().second);
137 
138  TensorShape nhwc_weights_shape = weights->tensor_shape();
139  TensorShape nhwc_input_shape = input->tensor_shape();
140 
141  if(is_nchw)
142  {
143  permute(nhwc_weights_shape, PermutationVector(2, 0, 1));
144  permute(nhwc_input_shape, PermutationVector(2, 0, 1));
145 
146  TensorInfo nhwc_input_info = input->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(nhwc_input_shape).set_data_layout(DataLayout::NCHW);
147 
148  TensorInfo nhwc_weights_info = weights->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(nhwc_weights_shape).set_data_layout(DataLayout::NCHW);
149 
150  CLPermute::validate(weights, &nhwc_weights_info, PermutationVector(2, 0, 1));
151  CLPermute::validate(input, &nhwc_input_info, PermutationVector(2, 0, 1));
152  }
153 
154  const TensorShape reshaped_shape = TensorShape(nhwc_weights_shape[0], nhwc_weights_shape[1] * nhwc_weights_shape[2] * nhwc_weights_shape[3]);
155  const TensorInfo reshaped_info = weights->clone()->set_tensor_shape(reshaped_shape).set_data_layout(DataLayout::NCHW).set_is_resizable(true);
157 
158  TensorShape transposed_shape(reshaped_shape[1], reshaped_shape[0]);
159  const TensorInfo reshaped_t_info = reshaped_info.clone()->set_is_resizable(true).set_tensor_shape(transposed_shape);
160  ARM_COMPUTE_RETURN_ON_ERROR(CLTranspose::validate(&reshaped_info, &reshaped_t_info));
161 
162  TensorShape gemm_output_shape(weights->dimension(idx_w) * weights->dimension(idx_h) * weights->dimension(idx_b),
163  input->dimension(idx_w),
164  input->dimension(idx_h),
165  input->dimension(idx_b));
166 
167  TensorInfo gemm_output_info = reshaped_t_info.clone()->set_tensor_shape(gemm_output_shape).set_is_resizable(true);
168  GEMMInfo gemm_info(false, false, true, input->dimension(idx_h), true);
169 
170  GEMMLowpOutputStageInfo output_stage_info;
171 
172  if(is_quantized)
173  {
174  ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMLowpMatrixMultiplyCore::validate(&input->clone()->set_tensor_shape(nhwc_input_shape), &reshaped_t_info, nullptr, &gemm_output_info.set_data_type(DataType::S32),
175  gemm_info));
176  ARM_COMPUTE_RETURN_ON_ERROR(construct_gemmlowp_output_stage(input, weights, output, output_stage_info));
177  }
178  else
179  {
180  ARM_COMPUTE_RETURN_ON_ERROR(CLGEMM::validate(&input->clone()->set_tensor_shape(nhwc_input_shape).set_is_resizable(true), &reshaped_t_info, nullptr, &gemm_output_info, 1.0f, 0.0f, gemm_info));
181  }
182 
183  const PadStrideInfo stride_info(deconv_info.stride().first, deconv_info.stride().second);
184  auto out_dims = deconvolution_output_dimensions(input->dimension(idx_w), input->dimension(idx_h), weights->dimension(idx_w), weights->dimension(idx_h), stride_info);
186  TensorInfo col2im_output_info = gemm_output_info.clone()->set_tensor_shape(deconv_shape).set_is_resizable(true);
187 
188  if(padded_input && is_quantized)
189  {
190  const auto start_end = compute_start_end_slice_coordinates(col2im_output_info, deconv_info, is_nchw);
191  ARM_COMPUTE_RETURN_ON_ERROR(CLDeconvolutionReshapeOutputKernel::validate(&gemm_output_info, bias, &col2im_output_info, input, weights, deconv_info));
192  ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMLowpOutputStage::validate(&col2im_output_info, nullptr, &col2im_output_info.clone()->set_is_resizable(true).set_data_type(input->data_type()), output_stage_info));
193  ARM_COMPUTE_RETURN_ON_ERROR(CLSlice::validate(&col2im_output_info.clone()->set_is_resizable(true).set_data_type(input->data_type()), output, start_end.first, start_end.second));
194  }
195  else if(padded_input)
196  {
197  const auto start_end = compute_start_end_slice_coordinates(col2im_output_info, deconv_info, is_nchw);
198  ARM_COMPUTE_RETURN_ON_ERROR(CLDeconvolutionReshapeOutputKernel::validate(&gemm_output_info, bias, &col2im_output_info, input, weights, deconv_info));
199  ARM_COMPUTE_RETURN_ON_ERROR(CLSlice::validate(&col2im_output_info, output, start_end.first, start_end.second));
200  }
201  else if(is_quantized)
202  {
203  ARM_COMPUTE_RETURN_ON_ERROR(CLDeconvolutionReshapeOutputKernel::validate(&gemm_output_info, bias, &col2im_output_info, input, weights, deconv_info));
204  ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMLowpOutputStage::validate(&col2im_output_info, nullptr, output, output_stage_info));
205  }
206  else
207  {
209  }
210 
211  return Status{};
212 }
213 
215 {
216  configure(CLKernelLibrary::get().get_compile_context(), input, weights, bias, output, deconv_info);
217 }
218 
219 void CLGEMMDeconvolutionLayer::configure(const CLCompileContext &compile_context, const ICLTensor *input, const ICLTensor *weights, const ICLTensor *bias, ICLTensor *output,
220  const PadStrideInfo &deconv_info)
221 {
224  weights->info(),
225  bias != nullptr ? bias->info() : nullptr,
226  output->info(),
227  deconv_info));
228 
229  _original_weights = weights;
230  _padded_input = deconv_info.pad_bottom() > 0 || deconv_info.pad_left() > 0 || deconv_info.pad_right() > 0 || deconv_info.pad_top() > 0;
231  _is_nchw = input->info()->data_layout() == DataLayout::NCHW;
232  _is_quantized = is_data_type_quantized_asymmetric(input->info()->data_type());
233 
234  const ICLTensor *input_to_use = input;
235  const ICLTensor *weights_to_use = weights;
236 
237  // If the data layout is NCHW, transform everything in NHWC. Another alternative could be to
238  // do an outer product in NCHW and then an accumulation through a reduction. This would have two
239  // drawbacks: first, the outer product is less efficient than a full GEMM. Second, the reduction
240  // might be slower than GEMM.
241  if(_is_nchw)
242  {
243  _memory_group.manage(&_permuted_input);
244  _permute_input_to_nhwc.configure(compile_context, input, &_permuted_input, PermutationVector(2U, 0U, 1U));
245 
246  _permute_weights_to_nhwc.configure(compile_context, weights, &_permuted_weights, PermutationVector(2U, 0U, 1U));
247 
248  input_to_use = &_permuted_input;
249  weights_to_use = &_permuted_weights;
250  }
251 
252  // Reshape the input weights. The weights will be reshaped only once during the call to prepare()
253  _reshaped_weights.allocator()->init(TensorInfo(TensorShape(weights_to_use->info()->dimension(0),
254  weights_to_use->info()->dimension(1) * weights_to_use->info()->dimension(2) * weights_to_use->info()->dimension(3)),
255  1,
256  input->info()->data_type(), weights->info()->quantization_info()));
257 
258  _reshape_weights.configure(compile_context, weights_to_use, &_reshaped_weights);
259  _transpose_weights.configure(compile_context, &_reshaped_weights, &_reshaped_weights_t);
260 
261  const size_t idx_h = get_data_layout_dimension_index(input->info()->data_layout(), DataLayoutDimension::HEIGHT);
262  GEMMInfo gemm_info(false, false, true, input->info()->dimension(idx_h), true);
263 
264  // Configure output stage for asymmetric quantized types
265  if(_is_quantized)
266  {
267  // gemmlowp adds the offsets (instead of subtracting them). Thus, we need to negate the original
268  // and restore them back to make it work properly.
269  QuantizationInfo iq_info = input->info()->quantization_info();
271 
272  input_to_use->info()->set_quantization_info(QuantizationInfo(iq_info.uniform().scale, -iq_info.uniform().offset));
273  _reshaped_weights_t.info()->set_quantization_info(QuantizationInfo(wq_info.uniform().scale, -wq_info.uniform().offset));
274 
275  _mm_gemmlowp.configure(compile_context, input_to_use, &_reshaped_weights_t, nullptr, &_gemm_output, gemm_info);
276 
277  input_to_use->info()->set_quantization_info(iq_info);
278  _reshaped_weights_t.info()->set_quantization_info(wq_info);
279  }
280  else
281  {
282  _mm_gemm.configure(compile_context, input_to_use, &_reshaped_weights_t, nullptr, &_gemm_output, 1.f, 0.0f, gemm_info);
283  }
284 
285  if(_is_nchw)
286  {
287  _permuted_input.allocator()->allocate();
288  }
289 
290  ICLTensor *deconv_reshape_output = nullptr;
291  ICLTensor *slice_output = nullptr;
292  ICLTensor *output_stage_output = nullptr;
293 
294  if(_padded_input && _is_quantized)
295  {
296  _memory_group.manage(&_slice_gemm_input);
297  _memory_group.manage(&_gemmlowp_final);
298  deconv_reshape_output = &_gemmlowp_final;
299  output_stage_output = &_slice_gemm_input;
300  slice_output = output;
301  }
302  else if(_padded_input)
303  {
304  _memory_group.manage(&_slice_gemm_input);
305  deconv_reshape_output = &_slice_gemm_input;
306  slice_output = output;
307  }
308  else if(_is_quantized)
309  {
310  _memory_group.manage(&_gemmlowp_final);
311  deconv_reshape_output = &_gemmlowp_final;
312  output_stage_output = output;
313  }
314  else
315  {
316  deconv_reshape_output = output;
317  }
318 
319  // Configure a Col2Im call to reshape the output of GEMM
320  _deconv_reshape.configure(compile_context, &_gemm_output, bias, deconv_reshape_output, input->info(), weights->info(), deconv_info);
321  _gemm_output.allocator()->allocate();
322 
323  if(_is_quantized)
324  {
325  GEMMLowpOutputStageInfo output_stage_info;
326  construct_gemmlowp_output_stage(input->info(), weights->info(), output->info(), output_stage_info);
327  _gemmlowp_output_stage.configure(compile_context, &_gemmlowp_final, nullptr, output_stage_output, output_stage_info);
328  _gemmlowp_final.allocator()->allocate();
329  }
330 
331  // If the input was padded, the output needs to be sliced.
332  if(_padded_input)
333  {
334  const auto start_end = compute_start_end_slice_coordinates(*deconv_reshape_output->info(), deconv_info, _is_nchw);
335  _slice_gemm.configure(compile_context, &_slice_gemm_input, slice_output, start_end.first, start_end.second);
336  _slice_gemm_input.allocator()->allocate();
337  }
338 }
339 
341 {
342  prepare();
343 
344  MemoryGroupResourceScope scope_mg(_memory_group);
345 
346  if(_is_nchw)
347  {
348  _permute_input_to_nhwc.run();
349  }
350 
351  if(_is_quantized)
352  {
353  _mm_gemmlowp.run();
354  }
355  else
356  {
357  _mm_gemm.run();
358  }
359 
360  CLScheduler::get().enqueue(_deconv_reshape, false);
361 
362  if(_is_quantized)
363  {
364  _gemmlowp_output_stage.run();
365  }
366 
367  if(_padded_input)
368  {
369  _slice_gemm.run();
370  }
371 }
372 
374 {
375  if(!_is_prepared)
376  {
377  ARM_COMPUTE_ERROR_ON(!_original_weights->is_used());
378 
379  if(_is_nchw)
380  {
381  _permuted_weights.allocator()->allocate();
382  _permute_weights_to_nhwc.run();
383  }
384 
385  _reshaped_weights.allocator()->allocate();
386  _reshape_weights.run();
387 
388  if(_is_nchw)
389  {
390  _permuted_weights.allocator()->free();
391  }
392 
393  _reshaped_weights_t.allocator()->allocate();
394  _transpose_weights.run();
395 
396  // Prepare gemm
397  if(!_is_quantized)
398  {
399  _mm_gemm.prepare();
400  }
401  else
402  {
403  _mm_gemmlowp.prepare();
404  }
405 
406  // Free resources
407  if(!_reshaped_weights_t.is_used())
408  {
409  _reshaped_weights_t.allocator()->free();
410  }
411 
412  _original_weights->mark_as_unused();
413  _is_prepared = true;
414  }
415 }
416 } // namespace arm_compute
void configure(const ICLTensor *input, const ICLTensor *weights, const ICLTensor *bias, ICLTensor *output, const PadStrideInfo &deconv_info)
Set the input, weights, biases and output tensors.
static Status validate(const ITensorInfo *input, const ITensorInfo *output)
Static function to check if given info will lead to a valid configuration of CLReshapeLayer.
static Status validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, const ITensorInfo *input_info, const ITensorInfo *weights_info, const PadStrideInfo &deconv_info)
Static function to check if given info will lead to a valid configuration of CLDeconvolutionReshapeOu...
Shape of a tensor.
Definition: TensorShape.h:39
const DataLayout data_layout
Definition: Im2Col.cpp:146
Quantize using a fixed point multiplication.
void prepare() override
Prepare the function for executing.
Definition: CLGEMM.cpp:683
std::unique_ptr< ITensorInfo > clone() const override
Provide a clone of the current object of class T.
Definition: TensorInfo.cpp:314
TensorInfo * info() const override
Interface to be implemented by the child class to return the tensor's metadata.
Definition: CLTensor.cpp:41
void prepare() override
Prepare the function for executing.
void run() override
Run the kernels contained in the function.
Definition: CLGEMM.cpp:602
virtual size_t dimension(size_t index) const =0
Return the size of the requested dimension.
static CLScheduler & get()
Access the scheduler singleton.
Definition: CLScheduler.cpp:99
#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
std::pair< unsigned int, unsigned int > deconvolution_output_dimensions(unsigned int in_width, unsigned int in_height, unsigned int kernel_width, unsigned int kernel_height, const PadStrideInfo &pad_stride_info)
Returns expected width and height of the deconvolution's output tensor.
Definition: Utils.cpp:375
static Status validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *bias, const ITensorInfo *output, const PadStrideInfo &deconv_info)
Static function to check if given info will lead to a valid configuration of CLDeconvolutionLayer.
#define ARM_COMPUTE_RETURN_ON_ERROR(status)
Checks if a status contains an error and returns it.
Definition: Error.h:204
bool is_used() const
Flags if the tensor is used or not.
Definition: ITensor.cpp:163
CLGEMMDeconvolutionLayer(std::shared_ptr< IMemoryManager > memory_manager=nullptr)
Constructor.
#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c,...)
Definition: Validate.h:792
1 channel, 1 F32 per channel
ITensorInfo & set_data_type(DataType data_type) override
Set the data type to the specified value.
Definition: TensorInfo.cpp:319
Strides PermutationVector
Permutation vector.
Definition: Types.h:49
void configure(const ICLTensor *input, const ICLTensor *bias, ICLTensor *output, const GEMMLowpOutputStageInfo &info)
Initialise the kernel's inputs, output.
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:466
void run() override
Run the kernels contained in the function.
static CLKernelLibrary & get()
Access the KernelLibrary singleton.
Store the tensor's metadata.
Definition: ITensorInfo.h:40
CLTensorAllocator * allocator()
Return a pointer to the tensor's allocator.
Definition: CLTensor.cpp:61
#define ARM_COMPUTE_ERROR_THROW_ON(status)
Definition: Error.h:455
void configure(const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, const GEMMInfo &gemm_info=GEMMInfo())
Initialise the kernel's inputs, output.
unsigned int pad_top() const
Get the top padding.
Definition: Types.h:773
Status calculate_quantized_multiplier(float multiplier, int32_t *quant_multiplier, int32_t *shift, bool ignore_epsilon=false)
Calculate quantized representation of multiplier.
Status class.
Definition: Error.h:52
void run() override
Run the kernels contained in the function.
#define ARM_COMPUTE_RETURN_ERROR_ON(cond)
If the condition is true, an error is returned.
Definition: Error.h:296
void configure(const ICLTensor *input, const ICLTensor *bias, ICLTensor *output, const ITensorInfo *input_info, const ITensorInfo *weights_info, const PadStrideInfo &deconv_info)
Initialise the kernel's source and destination.
void init(const TensorInfo &input, size_t alignment=0)
Initialize a tensor based on the passed TensorInfo.
Copyright (c) 2017-2020 Arm Limited.
1 channel, 1 F16 per channel
void run() override
Run the kernels contained in the function.
ITensorInfo & set_quantization_info(const QuantizationInfo &quantization_info) override
Set the quantization settings (scale and offset) of the tensor.
Definition: TensorInfo.cpp:372
ITensorInfo * info() const override
Interface to be implemented by the child class to return the tensor's metadata.
Definition: Tensor.cpp:33
void permute(Dimensions< T > &dimensions, const PermutationVector &perm)
Permutes given Dimensions according to a permutation vector.
Definition: Helpers.h:605
static Status validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, const GEMMLowpOutputStageInfo &info)
Static function to check if given info will lead to a valid configuration of CLGEMMLowpQuantizeDownIn...
TensorShape compute_deconvolution_output_shape(const std::pair< unsigned int, unsigned int > &out_dims, const ITensorInfo &input, const ITensorInfo &weights)
Calculate the output shape of the deconvolution layer.
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
Quantization information.
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 CLGEMMLowpMatrixMultiply...
void run() override final
Run the kernels contained in the function.
quantized, asymmetric fixed-point 8-bit number unsigned
std::pair< unsigned int, unsigned int > stride() const
Get the stride.
Definition: Types.h:737
UniformQuantizationInfo uniform() const
Return per layer quantization info.
GEMMLowp output stage info.
Definition: Types.h:1881
static Status validate(const ITensorInfo *input, const ITensorInfo *output, const Coordinates &starts, const Coordinates &ends)
Static function to check if given info will lead to a valid configuration of CLSlice.
Definition: CLSlice.cpp:80
virtual ITensorInfo * info() const =0
Interface to be implemented by the child class to return the tensor's metadata.
unsigned int pad_right() const
Get the right padding.
Definition: Types.h:768
Padding and stride information class.
Definition: Types.h:689
virtual QuantizationInfo quantization_info() const =0
Get the quantization settings (scale and offset) of the tensor.
void enqueue(ICLKernel &kernel, bool flush=true)
Schedule the execution of the passed kernel if possible.
Num samples, channels, height, width.
CLCompileContext class.
void configure(const ICLTensor *input, ICLTensor *output, const Coordinates &starts, const Coordinates &ends)
Configure kernel.
Definition: CLSlice.cpp:85
bool is_data_type_quantized_asymmetric(DataType dt)
Check if a given data type is of asymmetric quantized type.
Definition: Utils.h:1143
#define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...)
Definition: Validate.h:163
void allocate() override
Allocate size specified by TensorInfo of OpenCL memory.
#define ARM_COMPUTE_ERROR_ON_NULLPTR(...)
Definition: Validate.h:161
Memory group resources scope handling class.
Definition: IMemoryGroup.h:82
Interface for OpenCL tensor.
Definition: ICLTensor.h:42
static Status validate(const ITensorInfo *input, const ITensorInfo *output)
Static function to check if given info will lead to a valid configuration of CLTranspose.
Definition: CLTranspose.cpp:45
void run() override
Run the kernels contained in the function.
Definition: CLSlice.cpp:98
void configure(const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta, const GEMMInfo &gemm_info=GEMMInfo())
Initialise the kernel's inputs and output.
Definition: CLGEMM.cpp:497
void free() override
Free allocated OpenCL memory.
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 CLGEMM.
Definition: CLGEMM.cpp:556
Store the tensor's metadata.
Definition: TensorInfo.h:45
GEMM information class.
Definition: Types.h:1932
void configure(const ICLTensor *input, ICLTensor *output, const PermutationVector &perm)
Set the input and output tensors.
Definition: CLPermute.cpp:33
void configure(const ICLTensor *input, ICLTensor *output)
Initialise the kernel's inputs and outputs.
static Status validate(const ITensorInfo *input, const ITensorInfo *output, const PermutationVector &perm)
Static function to check if given info will lead to a valid configuration of CLPermute.
Definition: CLPermute.cpp:45
quantized, asymmetric fixed-point 8-bit number signed
void configure(const ICLTensor *input, ICLTensor *output)
Initialise the kernel's inputs and output.
Definition: CLTranspose.cpp:33
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
unsigned int pad_bottom() const
Get the bottom padding.
Definition: Types.h:778
unsigned int pad_left() const
Get the left padding.
Definition: Types.h:763
void prepare() override
Prepare the function for executing.
DataLayout
[DataLayout enum definition]
Definition: Types.h:120
std::tuple< PixelValue, PixelValue > get_min_max(DataType dt)
Compute the mininum and maximum values a data type can take.
Definition: Utils.h:560