Compute Library
 23.05
SimpleTensor.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2020, 2023 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  */
24 #ifndef ARM_COMPUTE_TEST_SIMPLE_TENSOR_H
25 #define ARM_COMPUTE_TEST_SIMPLE_TENSOR_H
26 
28 #include "arm_compute/core/Types.h"
29 #include "arm_compute/core/Utils.h"
30 #include "tests/IAccessor.h"
31 #include "tests/Utils.h"
32 
33 #include <algorithm>
34 #include <array>
35 #include <cstddef>
36 #include <cstdint>
37 #include <functional>
38 #include <memory>
39 #include <stdexcept>
40 #include <utility>
41 
42 namespace arm_compute
43 {
44 namespace test
45 {
46 class RawTensor;
47 
48 /** Simple tensor object that stores elements in a consecutive chunk of memory.
49  *
50  * It can be created by either loading an image from a file which also
51  * initialises the content of the tensor or by explcitly specifying the size.
52  * The latter leaves the content uninitialised.
53  *
54  * Furthermore, the class provides methods to convert the tensor's values into
55  * different image format.
56  */
57 template <typename T>
58 class SimpleTensor : public IAccessor
59 {
60 public:
61  /** Create an uninitialised tensor. */
62  SimpleTensor() = default;
63 
64  /** Create an uninitialised tensor of the given @p shape and @p format.
65  *
66  * @param[in] shape Shape of the new raw tensor.
67  * @param[in] format Format of the new raw tensor.
68  */
70 
71  /** Create an uninitialised tensor of the given @p shape and @p data type.
72  *
73  * @param[in] shape Shape of the new raw tensor.
74  * @param[in] data_type Data type of the new raw tensor.
75  * @param[in] num_channels (Optional) Number of channels (default = 1).
76  * @param[in] quantization_info (Optional) Quantization info for asymmetric quantization (default = empty).
77  * @param[in] data_layout (Optional) Data layout of the tensor (default = NCHW).
78  */
80  int num_channels = 1,
83 
84  /** Create a deep copy of the given @p tensor.
85  *
86  * @param[in] tensor To be copied tensor.
87  */
89 
90  /** Create a deep copy of the given @p tensor.
91  *
92  * @param[in] tensor To be copied tensor.
93  *
94  * @return a copy of the given tensor.
95  */
97  /** Allow instances of this class to be move constructed */
98  SimpleTensor(SimpleTensor &&) = default;
99  /** Default destructor. */
100  ~SimpleTensor() = default;
101 
102  /** Tensor value type */
103  using value_type = T;
104  /** Tensor buffer pointer type */
105  using Buffer = std::unique_ptr<value_type[]>;
106 
107  friend class RawTensor;
108 
109  /** Return value at @p offset in the buffer.
110  *
111  * @param[in] offset Offset within the buffer.
112  *
113  * @return value in the buffer.
114  */
115  T &operator[](size_t offset);
116 
117  /** Return constant value at @p offset in the buffer.
118  *
119  * @param[in] offset Offset within the buffer.
120  *
121  * @return constant value in the buffer.
122  */
123  const T &operator[](size_t offset) const;
124 
125  /** Shape of the tensor.
126  *
127  * @return the shape of the tensor.
128  */
129  TensorShape shape() const override;
130  /** Size of each element in the tensor in bytes.
131  *
132  * @return the size of each element in the tensor in bytes.
133  */
134  size_t element_size() const override;
135  /** Total size of the tensor in bytes.
136  *
137  * @return the total size of the tensor in bytes.
138  */
139  size_t size() const override;
140  /** Image format of the tensor.
141  *
142  * @return the format of the tensor.
143  */
144  Format format() const override;
145  /** Data layout of the tensor.
146  *
147  * @return the data layout of the tensor.
148  */
149  DataLayout data_layout() const override;
150  /** Data type of the tensor.
151  *
152  * @return the data type of the tensor.
153  */
154  DataType data_type() const override;
155  /** Number of channels of the tensor.
156  *
157  * @return the number of channels of the tensor.
158  */
159  int num_channels() const override;
160  /** Number of elements of the tensor.
161  *
162  * @return the number of elements of the tensor.
163  */
164  int num_elements() const override;
165  /** Available padding around the tensor.
166  *
167  * @return the available padding around the tensor.
168  */
169  PaddingSize padding() const override;
170  /** Quantization info in case of asymmetric quantized type
171  *
172  * @return
173  */
174  QuantizationInfo quantization_info() const override;
175 
176  /** Set the quantization information of the tensor.
177  *
178  * This function does not have any effect on the raw quantized data of the tensor.
179  * It simply changes the quantization information, hence changes the dequantized values.
180  *
181  * @return A reference to the current object.
182  */
184 
185  /** Constant pointer to the underlying buffer.
186  *
187  * @return a constant pointer to the data.
188  */
189  const T *data() const;
190 
191  /** Pointer to the underlying buffer.
192  *
193  * @return a pointer to the data.
194  */
195  T *data();
196 
197  /** Read only access to the specified element.
198  *
199  * @param[in] coord Coordinates of the desired element.
200  *
201  * @return A pointer to the desired element.
202  */
203  const void *operator()(const Coordinates &coord) const override;
204 
205  /** Access to the specified element.
206  *
207  * @param[in] coord Coordinates of the desired element.
208  *
209  * @return A pointer to the desired element.
210  */
211  void *operator()(const Coordinates &coord) override;
212 
213  /** Swaps the content of the provided tensors.
214  *
215  * @param[in, out] tensor1 Tensor to be swapped.
216  * @param[in, out] tensor2 Tensor to be swapped.
217  */
218  template <typename U>
219  friend void swap(SimpleTensor<U> &tensor1, SimpleTensor<U> &tensor2);
220 
221 protected:
222  Buffer _buffer{ nullptr };
223  TensorShape _shape{};
224  Format _format{ Format::UNKNOWN };
225  DataType _data_type{ DataType::UNKNOWN };
226  int _num_channels{ 0 };
227  QuantizationInfo _quantization_info{};
228  DataLayout _data_layout{ DataLayout::UNKNOWN };
229 };
230 
231 template <typename T1, typename T2>
233 {
234  SimpleTensor<T1> st(tensor.shape(), tensor.data_type(),
235  tensor.num_channels(),
236  tensor.quantization_info(),
237  tensor.data_layout());
238  for(size_t n = 0; n < size_t(st.num_elements()); n++)
239  {
240  st.data()[n] = static_cast<T1>(tensor.data()[n]);
241  }
242  return st;
243 }
244 
245 template <typename T1, typename T2, typename std::enable_if<std::is_same<T1, T2>::value, int>::type = 0>
247 {
248  SimpleTensor<T1> st(tensor.shape(), tensor.data_type(),
249  tensor.num_channels(),
250  tensor.quantization_info(),
251  tensor.data_layout());
252  memcpy((void *)st.data(), (const void *)tensor.data(), size_t(st.num_elements() * sizeof(T1)));
253  return st;
254 }
255 
256 template < typename T1, typename T2, typename std::enable_if < (std::is_same<T1, half>::value || std::is_same<T2, half>::value), int >::type = 0 >
258 {
259  SimpleTensor<T1> st(tensor.shape(), tensor.data_type(),
260  tensor.num_channels(),
261  tensor.quantization_info(),
262  tensor.data_layout());
263  for(size_t n = 0; n < size_t(st.num_elements()); n++)
264  {
265  st.data()[n] = half_float::detail::half_cast<T1, T2>(tensor.data()[n]);
266  }
267  return st;
268 }
269 
270 template <typename T>
272  : _buffer(nullptr),
273  _shape(shape),
274  _format(format),
275  _quantization_info(),
276  _data_layout(DataLayout::NCHW)
277 {
278  _num_channels = num_channels();
279  _buffer = std::make_unique<T[]>(num_elements() * _num_channels);
280 }
281 
282 template <typename T>
284  : _buffer(nullptr),
285  _shape(shape),
286  _data_type(data_type),
287  _num_channels(num_channels),
288  _quantization_info(quantization_info),
289  _data_layout(data_layout)
290 {
291  _buffer = std::make_unique<T[]>(this->_shape.total_size() * _num_channels);
292 }
293 
294 template <typename T>
296  : _buffer(nullptr),
297  _shape(tensor.shape()),
298  _format(tensor.format()),
299  _data_type(tensor.data_type()),
300  _num_channels(tensor.num_channels()),
301  _quantization_info(tensor.quantization_info()),
302  _data_layout(tensor.data_layout())
303 {
304  _buffer = std::make_unique<T[]>(tensor.num_elements() * _num_channels);
305  std::copy_n(tensor.data(), this->_shape.total_size() * _num_channels, _buffer.get());
306 }
307 
308 template <typename T>
310 {
311  swap(*this, tensor);
312 
313  return *this;
314 }
315 
316 template <typename T>
318 {
319  return _buffer[offset];
320 }
321 
322 template <typename T>
323 const T &SimpleTensor<T>::operator[](size_t offset) const
324 {
325  return _buffer[offset];
326 }
327 
328 template <typename T>
330 {
331  return _shape;
332 }
333 
334 template <typename T>
336 {
337  return num_channels() * element_size_from_data_type(data_type());
338 }
339 
340 template <typename T>
342 {
343  return _quantization_info;
344 }
345 
346 template <typename T>
348 {
349  _quantization_info = qinfo;
350  return *this;
351 }
352 
353 template <typename T>
354 size_t SimpleTensor<T>::size() const
355 {
356  const size_t size = std::accumulate(_shape.cbegin(), _shape.cend(), 1, std::multiplies<size_t>());
357  return size * element_size();
358 }
359 
360 template <typename T>
362 {
363  return _format;
364 }
365 
366 template <typename T>
368 {
369  return _data_layout;
370 }
371 
372 template <typename T>
374 {
375  if(_format != Format::UNKNOWN)
376  {
377  return data_type_from_format(_format);
378  }
379  else
380  {
381  return _data_type;
382  }
383 }
384 
385 template <typename T>
387 {
388  switch(_format)
389  {
390  case Format::U8:
391  case Format::U16:
392  case Format::S16:
393  case Format::U32:
394  case Format::S32:
395  case Format::F16:
396  case Format::F32:
397  return 1;
398  // Because the U and V channels are subsampled
399  // these formats appear like having only 2 channels:
400  case Format::YUYV422:
401  case Format::UYVY422:
402  return 2;
403  case Format::UV88:
404  return 2;
405  case Format::RGB888:
406  return 3;
407  case Format::RGBA8888:
408  return 4;
409  case Format::UNKNOWN:
410  return _num_channels;
411  //Doesn't make sense for planar formats:
412  case Format::NV12:
413  case Format::NV21:
414  case Format::IYUV:
415  case Format::YUV444:
416  default:
417  return 0;
418  }
419 }
420 
421 template <typename T>
423 {
424  return _shape.total_size();
425 }
426 
427 template <typename T>
429 {
430  return PaddingSize(0);
431 }
432 
433 template <typename T>
434 const T *SimpleTensor<T>::data() const
435 {
436  return _buffer.get();
437 }
438 
439 template <typename T>
441 {
442  return _buffer.get();
443 }
444 
445 template <typename T>
446 const void *SimpleTensor<T>::operator()(const Coordinates &coord) const
447 {
448  return _buffer.get() + coord2index(_shape, coord) * _num_channels;
449 }
450 
451 template <typename T>
453 {
454  return _buffer.get() + coord2index(_shape, coord) * _num_channels;
455 }
456 
457 template <typename U>
458 void swap(SimpleTensor<U> &tensor1, SimpleTensor<U> &tensor2)
459 {
460  // Use unqualified call to swap to enable ADL. But make std::swap available
461  // as backup.
462  using std::swap;
463  swap(tensor1._shape, tensor2._shape);
464  swap(tensor1._format, tensor2._format);
465  swap(tensor1._data_type, tensor2._data_type);
466  swap(tensor1._num_channels, tensor2._num_channels);
467  swap(tensor1._quantization_info, tensor2._quantization_info);
468  swap(tensor1._buffer, tensor2._buffer);
469 }
470 } // namespace test
471 } // namespace arm_compute
472 #endif /* ARM_COMPUTE_TEST_SIMPLE_TENSOR_H */
friend void swap(SimpleTensor< U > &tensor1, SimpleTensor< U > &tensor2)
Swaps the content of the provided tensors.
Definition: SimpleTensor.h:458
__global uchar * offset(const Image *img, int x, int y)
Get the pointer position of a Image.
Definition: helpers.h:1110
size_t element_size() const override
Size of each element in the tensor in bytes.
Definition: SimpleTensor.h:335
Subclass of SimpleTensor using uint8_t as value type.
Definition: RawTensor.h:38
Shape of a tensor.
Definition: TensorShape.h:39
size_t size() const override
Total size of the tensor in bytes.
Definition: SimpleTensor.h:354
T & operator[](size_t offset)
Return value at offset in the buffer.
Definition: SimpleTensor.h:317
Unknown CL kernel type.
Definition: CLTypes.h:82
Container for 2D border size.
Definition: Types.h:284
size_t element_size_from_data_type(DataType dt)
The size in bytes of the data type.
Definition: Utils.h:185
Format format() const override
Image format of the tensor.
Definition: SimpleTensor.h:361
DataType data_type() const override
Data type of the tensor.
Definition: SimpleTensor.h:373
void swap(SimpleTensor< U > &tensor1, SimpleTensor< U > &tensor2)
Definition: SimpleTensor.h:458
TensorShape shape() const override
Shape of the tensor.
Definition: SimpleTensor.h:329
decltype(strategy::transforms) typedef type
SimpleTensor< T2 > accumulate(const SimpleTensor< T1 > &src, DataType output_data_type)
Definition: Accumulate.cpp:38
SimpleTensor< T1 > copy_tensor(const SimpleTensor< T2 > &tensor)
Definition: SimpleTensor.h:232
Copyright (c) 2017-2023 Arm Limited.
int coord2index(const TensorShape &shape, const Coordinates &coord)
Linearise the given coordinate.
Definition: Utils.h:388
Quantization information.
Format
Image colour formats.
Definition: Types.h:56
~SimpleTensor()=default
Default destructor.
Coordinates of an item.
Definition: Coordinates.h:37
uint8_t value_type
Tensor value type.
Definition: SimpleTensor.h:103
PaddingSize padding() const override
Available padding around the tensor.
Definition: SimpleTensor.h:428
DataLayout data_layout() const override
Data layout of the tensor.
Definition: SimpleTensor.h:367
BorderSize PaddingSize
Container for 2D padding size.
Definition: Types.h:399
Num samples, channels, height, width.
SimpleTensor()=default
Create an uninitialised tensor.
const void * operator()(const Coordinates &coord) const override
Read only access to the specified element.
Definition: SimpleTensor.h:446
DataType data_type_from_format(Format format)
Return the data type used by a given single-planar pixel format.
Definition: Utils.h:219
std::unique_ptr< value_type[]> Buffer
Tensor buffer pointer type.
Definition: SimpleTensor.h:105
Simple tensor object that stores elements in a consecutive chunk of memory.
Definition: SimpleTensor.h:58
int num_channels() const override
Number of channels of the tensor.
Definition: SimpleTensor.h:386
SimpleTensor & operator=(SimpleTensor tensor)
Create a deep copy of the given tensor.
Definition: SimpleTensor.h:309
Common interface to provide information and access to tensor like structures.
Definition: IAccessor.h:37
const QuantizationInfo qinfo
Definition: Im2Col.cpp:155
int num_elements() const override
Number of elements of the tensor.
Definition: SimpleTensor.h:422
CLTensor * tensor
Pointer to the auxiliary tensor.
QuantizationInfo quantization_info() const override
Quantization info in case of asymmetric quantized type.
Definition: SimpleTensor.h:341
DataType
Available data types.
Definition: Types.h:79
DataLayout
[DataLayout enum definition]
Definition: Types.h:113
const T * data() const
Constant pointer to the underlying buffer.
Definition: SimpleTensor.h:434