Compute Library
 21.08
Utils.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2021 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 __UTILS_UTILS_H__
25 #define __UTILS_UTILS_H__
26 
27 /** @dir .
28  * brief Boiler plate code used by examples. Various utilities to print types, load / store assets, etc.
29  */
30 
33 #include "arm_compute/core/Types.h"
36 #pragma GCC diagnostic push
37 #pragma GCC diagnostic ignored "-Wunused-parameter"
38 #pragma GCC diagnostic ignored "-Wstrict-overflow"
39 #include "libnpy/npy.hpp"
40 #pragma GCC diagnostic pop
41 #include "support/StringSupport.h"
42 
43 #ifdef ARM_COMPUTE_CL
46 #endif /* ARM_COMPUTE_CL */
47 
48 #include <cstdlib>
49 #include <cstring>
50 #include <fstream>
51 #include <iostream>
52 #include <memory>
53 #include <random>
54 #include <string>
55 #include <tuple>
56 #include <vector>
57 
58 namespace arm_compute
59 {
60 namespace utils
61 {
62 /** Supported image types */
63 enum class ImageType
64 {
65  UNKNOWN,
66  PPM,
67  JPEG
68 };
69 
70 /** Abstract Example class.
71  *
72  * All examples have to inherit from this class.
73  */
74 class Example
75 {
76 public:
77  /** Setup the example.
78  *
79  * @param[in] argc Argument count.
80  * @param[in] argv Argument values.
81  *
82  * @return True in case of no errors in setup else false
83  */
84  virtual bool do_setup(int argc, char **argv)
85  {
86  ARM_COMPUTE_UNUSED(argc, argv);
87  return true;
88  };
89  /** Run the example. */
90  virtual void do_run() {};
91  /** Teardown the example. */
92  virtual void do_teardown() {};
93 
94  /** Default destructor. */
95  virtual ~Example() = default;
96 };
97 
98 /** Run an example and handle the potential exceptions it throws
99  *
100  * @param[in] argc Number of command line arguments
101  * @param[in] argv Command line arguments
102  * @param[in] example Example to run
103  */
104 int run_example(int argc, char **argv, std::unique_ptr<Example> example);
105 
106 template <typename T>
107 int run_example(int argc, char **argv)
108 {
109  return run_example(argc, argv, std::make_unique<T>());
110 }
111 
112 /** Draw a RGB rectangular window for the detected object
113  *
114  * @param[in, out] tensor Input tensor where the rectangle will be drawn on. Format supported: RGB888
115  * @param[in] rect Geometry of the rectangular window
116  * @param[in] r Red colour to use
117  * @param[in] g Green colour to use
118  * @param[in] b Blue colour to use
119  */
120 void draw_detection_rectangle(arm_compute::ITensor *tensor, const arm_compute::DetectionWindow &rect, uint8_t r, uint8_t g, uint8_t b);
121 
122 /** Gets image type given a file
123  *
124  * @param[in] filename File to identify its image type
125  *
126  * @return Image type
127  */
128 ImageType get_image_type_from_file(const std::string &filename);
129 
130 /** Parse the ppm header from an input file stream. At the end of the execution,
131  * the file position pointer will be located at the first pixel stored in the ppm file
132  *
133  * @param[in] fs Input file stream to parse
134  *
135  * @return The width, height and max value stored in the header of the PPM file
136  */
137 std::tuple<unsigned int, unsigned int, int> parse_ppm_header(std::ifstream &fs);
138 
139 /** Parse the npy header from an input file stream. At the end of the execution,
140  * the file position pointer will be located at the first pixel stored in the npy file //TODO
141  *
142  * @param[in] fs Input file stream to parse
143  *
144  * @return The width and height stored in the header of the NPY file
145  */
146 std::tuple<std::vector<unsigned long>, bool, std::string> parse_npy_header(std::ifstream &fs);
147 
148 /** Obtain numpy type string from DataType.
149  *
150  * @param[in] data_type Data type.
151  *
152  * @return numpy type string.
153  */
154 inline std::string get_typestring(DataType data_type)
155 {
156  // Check endianness
157  const unsigned int i = 1;
158  const char *c = reinterpret_cast<const char *>(&i);
159  std::string endianness;
160  if(*c == 1)
161  {
162  endianness = std::string("<");
163  }
164  else
165  {
166  endianness = std::string(">");
167  }
168  const std::string no_endianness("|");
169 
170  switch(data_type)
171  {
172  case DataType::U8:
173  case DataType::QASYMM8:
174  return no_endianness + "u" + support::cpp11::to_string(sizeof(uint8_t));
175  case DataType::S8:
176  case DataType::QSYMM8:
178  return no_endianness + "i" + support::cpp11::to_string(sizeof(int8_t));
179  case DataType::U16:
180  case DataType::QASYMM16:
181  return endianness + "u" + support::cpp11::to_string(sizeof(uint16_t));
182  case DataType::S16:
183  case DataType::QSYMM16:
184  return endianness + "i" + support::cpp11::to_string(sizeof(int16_t));
185  case DataType::U32:
186  return endianness + "u" + support::cpp11::to_string(sizeof(uint32_t));
187  case DataType::S32:
188  return endianness + "i" + support::cpp11::to_string(sizeof(int32_t));
189  case DataType::U64:
190  return endianness + "u" + support::cpp11::to_string(sizeof(uint64_t));
191  case DataType::S64:
192  return endianness + "i" + support::cpp11::to_string(sizeof(int64_t));
193  case DataType::F16:
194  return endianness + "f" + support::cpp11::to_string(sizeof(half));
195  case DataType::F32:
196  return endianness + "f" + support::cpp11::to_string(sizeof(float));
197  case DataType::F64:
198  return endianness + "f" + support::cpp11::to_string(sizeof(double));
199  case DataType::SIZET:
200  return endianness + "u" + support::cpp11::to_string(sizeof(size_t));
201  default:
202  ARM_COMPUTE_ERROR("Data type not supported");
203  }
204 }
205 
206 /** Maps a tensor if needed
207  *
208  * @param[in] tensor Tensor to be mapped
209  * @param[in] blocking Specified if map is blocking or not
210  */
211 template <typename T>
212 inline void map(T &tensor, bool blocking)
213 {
214  ARM_COMPUTE_UNUSED(tensor);
215  ARM_COMPUTE_UNUSED(blocking);
216 }
217 
218 /** Unmaps a tensor if needed
219  *
220  * @param tensor Tensor to be unmapped
221  */
222 template <typename T>
223 inline void unmap(T &tensor)
224 {
225  ARM_COMPUTE_UNUSED(tensor);
226 }
227 
228 #ifdef ARM_COMPUTE_CL
229 /** Maps a tensor if needed
230  *
231  * @param[in] tensor Tensor to be mapped
232  * @param[in] blocking Specified if map is blocking or not
233  */
234 inline void map(CLTensor &tensor, bool blocking)
235 {
236  tensor.map(blocking);
237 }
238 
239 /** Unmaps a tensor if needed
240  *
241  * @param tensor Tensor to be unmapped
242  */
243 inline void unmap(CLTensor &tensor)
244 {
245  tensor.unmap();
246 }
247 #endif /* ARM_COMPUTE_CL */
248 
249 /** Specialized class to generate random non-zero FP16 values.
250  * uniform_real_distribution<half> generates values that get rounded off to zero, causing
251  * differences between ACL and reference implementation
252 */
253 template <typename T>
255 {
256  static_assert(std::is_same<T, half>::value || std::is_same<T, bfloat16>::value, "Only half and bfloat16 data types supported");
257 
258 public:
259  using result_type = T;
260  /** Constructor
261  *
262  * @param[in] min Minimum value of the distribution
263  * @param[in] max Maximum value of the distribution
264  */
265  explicit uniform_real_distribution_16bit(float min = 0.f, float max = 1.0)
266  : dist(min, max)
267  {
268  }
269 
270  /** () operator to generate next value
271  *
272  * @param[in] gen an uniform random bit generator object
273  */
274  T operator()(std::mt19937 &gen)
275  {
276  return T(dist(gen));
277  }
278 
279 private:
280  std::uniform_real_distribution<float> dist;
281 };
282 
283 /** Numpy data loader */
285 {
286 public:
287  /** Default constructor */
289  : _fs(), _shape(), _fortran_order(false), _typestring(), _file_layout(DataLayout::NCHW)
290  {
291  }
292 
293  /** Open a NPY file and reads its metadata
294  *
295  * @param[in] npy_filename File to open
296  * @param[in] file_layout (Optional) Layout in which the weights are stored in the file.
297  */
298  void open(const std::string &npy_filename, DataLayout file_layout = DataLayout::NCHW)
299  {
300  ARM_COMPUTE_ERROR_ON(is_open());
301  try
302  {
303  _fs.open(npy_filename, std::ios::in | std::ios::binary);
304  ARM_COMPUTE_EXIT_ON_MSG_VAR(!_fs.good(), "Failed to load binary data from %s", npy_filename.c_str());
305  _fs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
306  _file_layout = file_layout;
307 
308  std::tie(_shape, _fortran_order, _typestring) = parse_npy_header(_fs);
309  }
310  catch(const std::ifstream::failure &e)
311  {
312  ARM_COMPUTE_ERROR_VAR("Accessing %s: %s", npy_filename.c_str(), e.what());
313  }
314  }
315  /** Return true if a NPY file is currently open */
316  bool is_open()
317  {
318  return _fs.is_open();
319  }
320 
321  /** Return true if a NPY file is in fortran order */
322  bool is_fortran()
323  {
324  return _fortran_order;
325  }
326 
327  /** Initialise the tensor's metadata with the dimensions of the NPY file currently open
328  *
329  * @param[out] tensor Tensor to initialise
330  * @param[in] dt Data type to use for the tensor
331  */
332  template <typename T>
334  {
335  ARM_COMPUTE_ERROR_ON(!is_open());
337 
338  // Use the size of the input NPY tensor
340  shape.set_num_dimensions(_shape.size());
341  for(size_t i = 0; i < _shape.size(); ++i)
342  {
343  size_t src = i;
344  if(_fortran_order)
345  {
346  src = _shape.size() - 1 - i;
347  }
348  shape.set(i, _shape.at(src));
349  }
350 
351  arm_compute::TensorInfo tensor_info(shape, 1, dt);
352  tensor.allocator()->init(tensor_info);
353  }
354 
355  /** Fill a tensor with the content of the currently open NPY file.
356  *
357  * @note If the tensor is a CLTensor, the function maps and unmaps the tensor
358  *
359  * @param[in,out] tensor Tensor to fill (Must be allocated, and of matching dimensions with the opened NPY).
360  */
361  template <typename T>
362  void fill_tensor(T &tensor)
363  {
364  ARM_COMPUTE_ERROR_ON(!is_open());
366  try
367  {
368  // Map buffer if creating a CLTensor
369  map(tensor, true);
370 
371  // Check if the file is large enough to fill the tensor
372  const size_t current_position = _fs.tellg();
373  _fs.seekg(0, std::ios_base::end);
374  const size_t end_position = _fs.tellg();
375  _fs.seekg(current_position, std::ios_base::beg);
376 
377  ARM_COMPUTE_ERROR_ON_MSG((end_position - current_position) < tensor.info()->tensor_shape().total_size() * tensor.info()->element_size(),
378  "Not enough data in file");
379  ARM_COMPUTE_UNUSED(end_position);
380 
381  // Check if the typestring matches the given one
382  std::string expect_typestr = get_typestring(tensor.info()->data_type());
383  ARM_COMPUTE_ERROR_ON_MSG(_typestring != expect_typestr, "Typestrings mismatch");
384 
385  bool are_layouts_different = (_file_layout != tensor.info()->data_layout());
386  // Correct dimensions (Needs to match TensorShape dimension corrections)
387  if(_shape.size() != tensor.info()->tensor_shape().num_dimensions())
388  {
389  for(int i = static_cast<int>(_shape.size()) - 1; i > 0; --i)
390  {
391  if(_shape[i] == 1)
392  {
393  _shape.pop_back();
394  }
395  else
396  {
397  break;
398  }
399  }
400  }
401 
402  TensorShape permuted_shape = tensor.info()->tensor_shape();
404  if(are_layouts_different && tensor.info()->tensor_shape().num_dimensions() > 2)
405  {
406  perm = (tensor.info()->data_layout() == arm_compute::DataLayout::NHWC) ? arm_compute::PermutationVector(2U, 0U, 1U) : arm_compute::PermutationVector(1U, 2U, 0U);
408 
409  arm_compute::permute(permuted_shape, perm_vec);
410  }
411 
412  // Validate tensor shape
413  ARM_COMPUTE_ERROR_ON_MSG(_shape.size() != tensor.info()->tensor_shape().num_dimensions(), "Tensor ranks mismatch");
414  for(size_t i = 0; i < _shape.size(); ++i)
415  {
416  ARM_COMPUTE_ERROR_ON_MSG(permuted_shape[i] != _shape[i], "Tensor dimensions mismatch");
417  }
418 
419  switch(tensor.info()->data_type())
420  {
425  {
426  // Read data
427  if(!are_layouts_different && !_fortran_order && tensor.info()->padding().empty())
428  {
429  // If tensor has no padding read directly from stream.
430  _fs.read(reinterpret_cast<char *>(tensor.buffer()), tensor.info()->total_size());
431  }
432  else
433  {
434  // If tensor has padding or is in fortran order accessing tensor elements through execution window.
435  Window window;
436  const unsigned int num_dims = _shape.size();
437  if(_fortran_order)
438  {
439  for(unsigned int dim = 0; dim < num_dims; dim++)
440  {
441  permuted_shape.set(dim, _shape[num_dims - dim - 1]);
442  perm.set(dim, num_dims - dim - 1);
443  }
444  if(are_layouts_different)
445  {
446  // Permute only if num_dimensions greater than 2
447  if(num_dims > 2)
448  {
449  if(_file_layout == DataLayout::NHWC) // i.e destination is NCHW --> permute(1,2,0)
450  {
452  }
453  else
454  {
456  }
457  }
458  }
459  }
460  window.use_tensor_dimensions(permuted_shape);
461 
462  execute_window_loop(window, [&](const Coordinates & id)
463  {
464  Coordinates dst(id);
465  arm_compute::permute(dst, perm);
466  _fs.read(reinterpret_cast<char *>(tensor.ptr_to_element(dst)), tensor.info()->element_size());
467  });
468  }
469 
470  break;
471  }
472  default:
473  ARM_COMPUTE_ERROR("Unsupported data type");
474  }
475 
476  // Unmap buffer if creating a CLTensor
477  unmap(tensor);
478  }
479  catch(const std::ifstream::failure &e)
480  {
481  ARM_COMPUTE_ERROR_VAR("Loading NPY file: %s", e.what());
482  }
483  }
484 
485 private:
486  std::ifstream _fs;
487  std::vector<unsigned long> _shape;
488  bool _fortran_order;
489  std::string _typestring;
490  DataLayout _file_layout;
491 };
492 
493 /** Template helper function to save a tensor image to a PPM file.
494  *
495  * @note Only U8 and RGB888 formats supported.
496  * @note Only works with 2D tensors.
497  * @note If the input tensor is a CLTensor, the function maps and unmaps the image
498  *
499  * @param[in] tensor The tensor to save as PPM file
500  * @param[in] ppm_filename Filename of the file to create.
501  */
502 template <typename T>
503 void save_to_ppm(T &tensor, const std::string &ppm_filename)
504 {
506  ARM_COMPUTE_ERROR_ON(tensor.info()->num_dimensions() > 2);
507 
508  std::ofstream fs;
509 
510  try
511  {
512  fs.exceptions(std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit);
513  fs.open(ppm_filename, std::ios::out | std::ios::binary);
514 
515  const unsigned int width = tensor.info()->tensor_shape()[0];
516  const unsigned int height = tensor.info()->tensor_shape()[1];
517 
518  fs << "P6\n"
519  << width << " " << height << " 255\n";
520 
521  // Map buffer if creating a CLTensor
522  map(tensor, true);
523 
524  switch(tensor.info()->format())
525  {
527  {
528  arm_compute::Window window;
531 
532  arm_compute::Iterator in(&tensor, window);
533 
535  {
536  const unsigned char value = *in.ptr();
537 
538  fs << value << value << value;
539  },
540  in);
541 
542  break;
543  }
545  {
546  arm_compute::Window window;
549 
550  arm_compute::Iterator in(&tensor, window);
551 
553  {
554  fs.write(reinterpret_cast<std::fstream::char_type *>(in.ptr()), width * tensor.info()->element_size());
555  },
556  in);
557 
558  break;
559  }
560  default:
561  ARM_COMPUTE_ERROR("Unsupported format");
562  }
563 
564  // Unmap buffer if creating a CLTensor
565  unmap(tensor);
566  }
567  catch(const std::ofstream::failure &e)
568  {
569  ARM_COMPUTE_ERROR_VAR("Writing %s: (%s)", ppm_filename.c_str(), e.what());
570  }
571 }
572 
573 /** Template helper function to save a tensor image to a NPY file.
574  *
575  * @note Only F32 data type supported.
576  * @note If the input tensor is a CLTensor, the function maps and unmaps the image
577  *
578  * @param[in] tensor The tensor to save as NPY file
579  * @param[in] npy_filename Filename of the file to create.
580  * @param[in] fortran_order If true, save matrix in fortran order.
581  */
582 template <typename T, typename U = float>
583 void save_to_npy(T &tensor, const std::string &npy_filename, bool fortran_order)
584 {
586 
587  std::ofstream fs;
588  try
589  {
590  fs.exceptions(std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit);
591  fs.open(npy_filename, std::ios::out | std::ios::binary);
592 
593  std::vector<npy::ndarray_len_t> shape(tensor.info()->num_dimensions());
594 
595  for(unsigned int i = 0, j = tensor.info()->num_dimensions() - 1; i < tensor.info()->num_dimensions(); ++i, --j)
596  {
597  shape[i] = tensor.info()->tensor_shape()[!fortran_order ? j : i];
598  }
599 
600  // Map buffer if creating a CLTensor
601  map(tensor, true);
602 
603  using typestring_type = typename std::conditional<std::is_floating_point<U>::value, float, qasymm8_t>::type;
604 
605  std::vector<typestring_type> tmp; /* Used only to get the typestring */
606  npy::Typestring typestring_o{ tmp };
607  std::string typestring = typestring_o.str();
608 
609  std::ofstream stream(npy_filename, std::ofstream::binary);
610  npy::write_header(stream, typestring, fortran_order, shape);
611 
612  arm_compute::Window window;
613  window.use_tensor_dimensions(tensor.info()->tensor_shape());
614 
615  arm_compute::Iterator in(&tensor, window);
616 
618  {
619  stream.write(reinterpret_cast<const char *>(in.ptr()), sizeof(typestring_type));
620  },
621  in);
622 
623  // Unmap buffer if creating a CLTensor
624  unmap(tensor);
625  }
626  catch(const std::ofstream::failure &e)
627  {
628  ARM_COMPUTE_ERROR_VAR("Writing %s: (%s)", npy_filename.c_str(), e.what());
629  }
630 }
631 
632 /** Load the tensor with pre-trained data from a binary file
633  *
634  * @param[in] tensor The tensor to be filled. Data type supported: F32.
635  * @param[in] filename Filename of the binary file to load from.
636  */
637 template <typename T>
638 void load_trained_data(T &tensor, const std::string &filename)
639 {
641 
642  std::ifstream fs;
643 
644  try
645  {
646  fs.exceptions(std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit);
647  // Open file
648  fs.open(filename, std::ios::in | std::ios::binary);
649 
650  if(!fs.good())
651  {
652  throw std::runtime_error("Could not load binary data: " + filename);
653  }
654 
655  // Map buffer if creating a CLTensor
656  map(tensor, true);
657 
658  Window window;
659 
661 
662  for(unsigned int d = 1; d < tensor.info()->num_dimensions(); ++d)
663  {
664  window.set(d, Window::Dimension(0, tensor.info()->tensor_shape()[d], 1));
665  }
666 
667  arm_compute::Iterator in(&tensor, window);
668 
669  execute_window_loop(window, [&](const Coordinates &)
670  {
671  fs.read(reinterpret_cast<std::fstream::char_type *>(in.ptr()), tensor.info()->tensor_shape()[0] * tensor.info()->element_size());
672  },
673  in);
674 
675  // Unmap buffer if creating a CLTensor
676  unmap(tensor);
677  }
678  catch(const std::ofstream::failure &e)
679  {
680  ARM_COMPUTE_ERROR_VAR("Writing %s: (%s)", filename.c_str(), e.what());
681  }
682 }
683 
684 template <typename T, typename TensorType>
685 void fill_tensor_value(TensorType &tensor, T value)
686 {
687  map(tensor, true);
688 
689  Window window;
690  window.use_tensor_dimensions(tensor.info()->tensor_shape());
691 
692  Iterator it_tensor(&tensor, window);
693  execute_window_loop(window, [&](const Coordinates &)
694  {
695  *reinterpret_cast<T *>(it_tensor.ptr()) = value;
696  },
697  it_tensor);
698 
699  unmap(tensor);
700 }
701 
702 template <typename T, typename TensorType>
704 {
705  fill_tensor_value(tensor, T(0));
706 }
707 
708 template <typename T, typename TensorType>
709 void fill_tensor_vector(TensorType &tensor, std::vector<T> vec)
710 {
711  ARM_COMPUTE_ERROR_ON(tensor.info()->tensor_shape().total_size() != vec.size());
712 
713  map(tensor, true);
714 
715  Window window;
716  window.use_tensor_dimensions(tensor.info()->tensor_shape());
717 
718  int i = 0;
719  Iterator it_tensor(&tensor, window);
720  execute_window_loop(window, [&](const Coordinates &)
721  {
722  *reinterpret_cast<T *>(it_tensor.ptr()) = vec.at(i++);
723  },
724  it_tensor);
725 
726  unmap(tensor);
727 }
728 
729 template <typename T, typename TensorType>
730 void fill_random_tensor(TensorType &tensor, std::random_device::result_type seed, T lower_bound = std::numeric_limits<T>::lowest(), T upper_bound = std::numeric_limits<T>::max())
731 {
732  constexpr bool is_fp_16bit = std::is_same<T, half>::value || std::is_same<T, bfloat16>::value;
733  constexpr bool is_integral = std::is_integral<T>::value && !is_fp_16bit;
734 
735  using fp_dist_type = typename std::conditional<is_fp_16bit, arm_compute::utils::uniform_real_distribution_16bit<T>, std::uniform_real_distribution<T>>::type;
736  using dist_type = typename std::conditional<is_integral, std::uniform_int_distribution<T>, fp_dist_type>::type;
737 
738  std::mt19937 gen(seed);
739  dist_type dist(lower_bound, upper_bound);
740 
741  map(tensor, true);
742 
743  Window window;
744  window.use_tensor_dimensions(tensor.info()->tensor_shape());
745 
746  Iterator it(&tensor, window);
747  execute_window_loop(window, [&](const Coordinates &)
748  {
749  *reinterpret_cast<T *>(it.ptr()) = dist(gen);
750  },
751  it);
752 
753  unmap(tensor);
754 }
755 
756 template <typename T, typename TensorType>
757 void fill_random_tensor(TensorType &tensor, T lower_bound = std::numeric_limits<T>::lowest(), T upper_bound = std::numeric_limits<T>::max())
758 {
759  std::random_device rd;
760  fill_random_tensor(tensor, rd(), lower_bound, upper_bound);
761 }
762 
763 template <typename T>
764 void init_sgemm_output(T &dst, T &src0, T &src1, arm_compute::DataType dt)
765 {
766  dst.allocator()->init(TensorInfo(TensorShape(src1.info()->dimension(0), src0.info()->dimension(1), src0.info()->dimension(2)), 1, dt));
767 }
768 /** This function returns the amount of memory free reading from /proc/meminfo
769  *
770  * @return The free memory in kB
771  */
772 uint64_t get_mem_free_from_meminfo();
773 
774 /** Compare two tensors
775  *
776  * @param[in] tensor1 First tensor to be compared.
777  * @param[in] tensor2 Second tensor to be compared.
778  * @param[in] tolerance Tolerance used for the comparison.
779  *
780  * @return The number of mismatches
781  */
782 template <typename T>
783 int compare_tensor(ITensor &tensor1, ITensor &tensor2, T tolerance)
784 {
786  ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(&tensor1, &tensor2);
787 
788  int num_mismatches = 0;
789  Window window;
790  window.use_tensor_dimensions(tensor1.info()->tensor_shape());
791 
792  map(tensor1, true);
793  map(tensor2, true);
794 
795  Iterator itensor1(&tensor1, window);
796  Iterator itensor2(&tensor2, window);
797 
798  execute_window_loop(window, [&](const Coordinates &)
799  {
800  if(std::abs(*reinterpret_cast<T *>(itensor1.ptr()) - *reinterpret_cast<T *>(itensor2.ptr())) > tolerance)
801  {
802  ++num_mismatches;
803  }
804  },
805  itensor1, itensor2);
806 
807  unmap(itensor1);
808  unmap(itensor2);
809 
810  return num_mismatches;
811 }
812 } // namespace utils
813 } // namespace arm_compute
814 #endif /* __UTILS_UTILS_H__*/
void set(size_t dimension, T value, bool increase_dim_unit=true)
Accessor to set the value of one of the dimensions.
Definition: Dimensions.h:76
void save_to_ppm(T &tensor, const std::string &ppm_filename)
Template helper function to save a tensor image to a PPM file.
Definition: Utils.h:503
int run_example(int argc, char **argv, std::unique_ptr< Example > example)
Run an example and handle the potential exceptions it throws.
Definition: RunExample.cpp:94
uint64_t get_mem_free_from_meminfo()
This function returns the amount of memory free reading from /proc/meminfo.
Definition: Utils.cpp:254
Shape of a tensor.
Definition: TensorShape.h:39
quantized, symmetric fixed-point 16-bit number
bool is_fortran()
Return true if a NPY file is in fortran order.
Definition: Utils.h:322
SimpleTensor< float > b
Definition: DFT.cpp:157
void init_tensor(T &tensor, arm_compute::DataType dt)
Initialise the tensor&#39;s metadata with the dimensions of the NPY file currently open.
Definition: Utils.h:333
#define ARM_COMPUTE_ERROR(msg)
Print the given message then throw an std::runtime_error.
Definition: Error.h:352
TensorType
Memory type.
Definition: Types.h:38
1 channel, 1 U8 per channel
#define ARM_COMPUTE_EXIT_ON_MSG_VAR(cond, msg,...)
If the condition is true, the given message is printed and program exits.
Definition: Error.h:395
std::string to_string(T &&value)
Convert integer and float values to string.
void fill_tensor(T &tensor)
Fill a tensor with the content of the currently open NPY file.
Definition: Utils.h:362
half_float::half half
16-bit floating point type
Definition: Types.h:46
1 channel, 1 F32 per channel
Strides PermutationVector
Permutation vector.
Definition: Types.h:49
#define ARM_COMPUTE_ERROR_VAR(msg,...)
Print the given message then throw an std::runtime_error.
Definition: Error.h:346
void fill_tensor_value(TensorType &tensor, T value)
Definition: Utils.h:685
#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
Describe one of the image&#39;s dimensions with a start, end and step.
Definition: Window.h:77
quantized, asymmetric fixed-point 16-bit number
1 channel, 1 U16 per channel
#define ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(t,...)
Definition: Validate.h:639
decltype(strategy::transforms) typedef type
Interface for CPU tensor.
Definition: ITensor.h:36
uniform_real_distribution_16bit(float min=0.f, float max=1.0)
Constructor.
Definition: Utils.h:265
void use_tensor_dimensions(const TensorShape &shape, size_t first_dimension=Window::DimX)
Use the tensor&#39;s dimensions to fill the window dimensions.
Definition: Window.inl:276
SimpleTensor< float > src
Definition: DFT.cpp:155
Copyright (c) 2017-2021 Arm Limited.
1 channel, 1 F16 per channel
void map(bool blocking=true)
Enqueue a map operation of the allocated buffer.
Definition: CLTensor.cpp:66
virtual void do_teardown()
Teardown the example.
Definition: Utils.h:92
DataType dt
void fill_random_tensor(TensorType &tensor, std::random_device::result_type seed, T lower_bound=std::numeric_limits< T >::lowest(), T upper_bound=std::numeric_limits< T >::max())
Definition: Utils.h:730
void permute(Dimensions< T > &dimensions, const PermutationVector &perm)
Permutes given Dimensions according to a permutation vector.
Definition: Helpers.h:125
void unmap(T &tensor)
Unmaps a tensor if needed.
Definition: Utils.h:223
1 channel, 1 S32 per channel
signed 64-bit number
3 channels, 1 U8 per channel
Specialized class to generate random non-zero FP16 values.
Definition: Utils.h:254
const DataType data_type
Definition: Im2Col.cpp:150
std::string get_typestring(DataType data_type)
Obtain numpy type string from DataType.
Definition: Utils.h:154
#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_NOT_IN(t,...)
Definition: Validate.h:688
static constexpr size_t DimX
Alias for dimension 0 also known as X dimension.
Definition: Window.h:43
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
void save_to_npy(T &tensor, const std::string &npy_filename, bool fortran_order)
Template helper function to save a tensor image to a NPY file.
Definition: Utils.h:583
virtual void do_run()
Run the example.
Definition: Utils.h:90
1 channel, 1 U32 per channel
virtual const TensorShape & tensor_shape() const =0
Size for each dimension of the tensor.
#define ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(...)
Definition: Validate.h:539
Numpy data loader.
Definition: Utils.h:284
quantized, asymmetric fixed-point 8-bit number unsigned
#define ARM_COMPUTE_ERROR_ON_MSG(cond, msg)
Definition: Error.h:456
NPYLoader()
Default constructor.
Definition: Utils.h:288
Coordinates of an item.
Definition: Coordinates.h:37
#define ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(...)
Definition: Validate.h:437
std::tuple< std::vector< unsigned long >, bool, std::string > parse_npy_header(std::ifstream &fs)
Parse the npy header from an input file stream.
Definition: Utils.cpp:233
Abstract Example class.
Definition: Utils.h:74
virtual ITensorInfo * info() const =0
Interface to be implemented by the child class to return the tensor&#39;s metadata.
T operator()(std::mt19937 &gen)
() operator to generate next value
Definition: Utils.h:274
constexpr uint8_t * ptr() const
Return a pointer to the current pixel.
Definition: Helpers.inl:139
void end(TokenStream &in, bool &valid)
Definition: MLGOParser.cpp:290
void set(size_t dimension, const Dimension &dim)
Set the values of a given dimension.
Definition: Window.inl:49
bool is_open()
Return true if a NPY file is currently open.
Definition: Utils.h:316
1 channel, 1 S16 per channel
quantized, symmetric fixed-point 8-bit number
Num samples, channels, height, width.
#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c,...)
Definition: Validate.h:786
Strides of an item in bytes.
Definition: Strides.h:37
quantized, symmetric per channel fixed-point 8-bit number
static constexpr size_t DimY
Alias for dimension 1 also known as Y dimension.
Definition: Window.h:45
void map(T &tensor, bool blocking)
Maps a tensor if needed.
Definition: Utils.h:212
Detection window used for the object detection.
Definition: Types.h:515
int compare_tensor(ITensor &tensor1, ITensor &tensor2, T tolerance)
Compare two tensors.
Definition: Utils.h:783
uint8_t qasymm8_t
8 bit quantized asymmetric scalar value
Num samples, height, width, channels.
void draw_detection_rectangle(ITensor *tensor, const DetectionWindow &rect, uint8_t r, uint8_t g, uint8_t b)
Draw a RGB rectangular window for the detected object.
Definition: Utils.cpp:130
ImageType
Supported image types.
Definition: Utils.h:63
Wrapper to configure the Khronos OpenCL C++ header.
void open(const std::string &npy_filename, DataLayout file_layout=DataLayout::NCHW)
Open a NPY file and reads its metadata.
Definition: Utils.h:298
void fill_tensor_zero(TensorType &tensor)
Definition: Utils.h:703
std::tuple< unsigned int, unsigned int, int > parse_ppm_header(std::ifstream &fs)
Parse the ppm header from an input file stream.
Definition: Utils.cpp:202
Store the tensor&#39;s metadata.
Definition: TensorInfo.h:43
void execute_window_loop(const Window &w, L &&lambda_function, Ts &&... iterators)
Iterate through the passed window, automatically adjusting the iterators and calling the lambda_funct...
Definition: Helpers.inl:77
ImageType get_image_type_from_file(const std::string &filename)
Gets image type given a file.
Definition: Utils.cpp:167
void set_num_dimensions(size_t num_dimensions)
Set number of dimensions.
Definition: Dimensions.h:149
void load_trained_data(T &tensor, const std::string &filename)
Load the tensor with pre-trained data from a binary file.
Definition: Utils.h:638
64-bit floating-point number
Iterator updated by execute_window_loop for each window element.
Definition: Helpers.h:46
unsigned 64-bit number
DataType
Available data types.
Definition: Types.h:77
void unmap()
Enqueue an unmap operation of the allocated and mapped buffer.
Definition: CLTensor.cpp:71
void init_sgemm_output(T &dst, T &src0, T &src1, arm_compute::DataType dt)
Definition: Utils.h:764
DataLayout
[DataLayout enum definition]
Definition: Types.h:111
signed 8-bit number
Describe a multidimensional execution window.
Definition: Window.h:39
TensorShape & set(size_t dimension, size_t value, bool apply_dim_correction=true, bool increase_dim_unit=true)
Accessor to set the value of one of the dimensions.
Definition: TensorShape.h:79
void fill_tensor_vector(TensorType &tensor, std::vector< T > vec)
Definition: Utils.h:709
virtual bool do_setup(int argc, char **argv)
Setup the example.
Definition: Utils.h:84
Basic implementation of the OpenCL tensor interface.
Definition: CLTensor.h:41