24 #ifndef __UTILS_UTILS_H__
25 #define __UTILS_UTILS_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
104 int run_example(
int argc,
char **argv, std::unique_ptr<Example> example);
106 template <
typename T>
109 return run_example(argc, argv, std::make_unique<T>());
138 std::tuple<unsigned int, unsigned int, int>
parse_ppm_header(std::ifstream &fs);
158 const unsigned int i = 1;
159 const char *c =
reinterpret_cast<const char *
>(&i);
160 std::string endianness;
163 endianness = std::string(
"<");
167 endianness = std::string(
">");
169 const std::string no_endianness(
"|");
212 template <
typename T>
223 template <
typename T>
229 #ifdef ARM_COMPUTE_CL
254 template <
typename T>
257 static_assert(std::is_same<T, half>::value || std::is_same<T, bfloat16>::value,
258 "Only half and bfloat16 data types supported");
281 std::uniform_real_distribution<float> dist;
303 _fs.open(npy_filename, std::ios::in | std::ios::binary);
305 _fs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
306 _file_layout = file_layout;
310 _fortran_order =
header.fortran_order;
311 _typestring =
header.dtype.str();
313 catch (
const std::ifstream::failure &e)
321 return _fs.is_open();
327 return _fortran_order;
335 template <
typename T>
343 shape.set_num_dimensions(_shape.size());
344 for (
size_t i = 0; i < _shape.size(); ++i)
349 src = _shape.size() - 1 - i;
364 template <
typename T>
376 const size_t current_position = _fs.tellg();
378 const size_t end_position = _fs.tellg();
379 _fs.seekg(current_position, std::ios_base::beg);
382 tensor.info()->tensor_shape().total_size() *
tensor.info()->element_size(),
383 "Not enough data in file");
389 bool enable_f32_to_f16_conversion =
false;
390 if (_typestring != expect_typestr)
392 const std::string f32_typestring =
"<f4";
393 const std::string f16_typestring =
"<f2";
395 if (_typestring == f32_typestring && expect_typestr == f16_typestring)
397 enable_f32_to_f16_conversion =
true;
405 bool are_layouts_different = (_file_layout !=
tensor.info()->data_layout());
407 if (_shape.size() !=
tensor.info()->tensor_shape().num_dimensions())
409 for (
int i =
static_cast<int>(_shape.size()) - 1; i > 0; --i)
424 if (are_layouts_different &&
tensor.info()->tensor_shape().num_dimensions() > 2)
439 "Tensor ranks mismatch");
440 for (
size_t i = 0; i < _shape.size(); ++i)
445 switch (
tensor.info()->data_type())
453 if (!are_layouts_different && !_fortran_order &&
tensor.info()->padding().empty() &&
454 !enable_f32_to_f16_conversion)
457 _fs.read(
reinterpret_cast<char *
>(
tensor.buffer()),
tensor.info()->total_size());
463 const unsigned int num_dims = _shape.size();
466 for (
unsigned int dim = 0; dim < num_dims; dim++)
468 permuted_shape.
set(dim, _shape[num_dims - dim - 1]);
469 perm.
set(dim, num_dims - dim - 1);
471 if (are_layouts_different)
494 if (enable_f32_to_f16_conversion)
497 _fs.read(
reinterpret_cast<char *
>(&f32_val), 4u);
499 half_float::half_cast<half, std::round_to_nearest>(f32_val);
500 *(
reinterpret_cast<half *
>(
tensor.ptr_to_element(
dst))) = f16_val;
504 _fs.read(
reinterpret_cast<char *
>(
tensor.ptr_to_element(
dst)),
505 tensor.info()->element_size());
519 catch (
const std::ifstream::failure &e)
527 std::vector<unsigned long> _shape;
529 std::string _typestring;
542 template <
typename T>
552 fs.exceptions(std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit);
553 fs.open(ppm_filename, std::ios::out | std::ios::binary);
555 const unsigned int width =
tensor.info()->tensor_shape()[0];
556 const unsigned int height =
tensor.info()->tensor_shape()[1];
558 fs <<
"P6\n" << width <<
" " << height <<
" 255\n";
563 switch (
tensor.info()->format())
577 const unsigned char value = *in.
ptr();
579 fs << value << value << value;
596 fs.write(
reinterpret_cast<std::fstream::char_type *
>(in.
ptr()),
597 width *
tensor.info()->element_size());
610 catch (
const std::ofstream::failure &e)
625 template <
typename T,
typename U =
float>
633 fs.exceptions(std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit);
634 fs.open(npy_filename, std::ios::out | std::ios::binary);
636 std::vector<npy::ndarray_len_t>
shape(
tensor.info()->num_dimensions());
638 for (
unsigned int i = 0, j =
tensor.info()->num_dimensions() - 1; i <
tensor.info()->num_dimensions(); ++i, --j)
640 shape[i] =
tensor.info()->tensor_shape()[!fortran_order ? j : i];
646 using typestring_type =
typename std::conditional<std::is_floating_point<U>::value, float,
qasymm8_t>
::type;
648 std::vector<typestring_type> tmp;
649 const npy::dtype_t dtype = npy::dtype_map.at(std::type_index(
typeid(tmp)));
651 std::ofstream stream(npy_filename, std::ofstream::binary);
653 npy::write_header(stream,
header);
663 { stream.write(
reinterpret_cast<const char *
>(in.
ptr()),
sizeof(typestring_type)); },
669 catch (
const std::ofstream::failure &e)
680 template <
typename T>
689 fs.exceptions(std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit);
691 fs.open(filename, std::ios::in | std::ios::binary);
695 throw std::runtime_error(
"Could not load binary data: " + filename);
705 for (
unsigned int d = 1; d <
tensor.info()->num_dimensions(); ++d)
716 fs.read(
reinterpret_cast<std::fstream::char_type *
>(in.
ptr()),
717 tensor.info()->tensor_shape()[0] *
tensor.info()->element_size());
724 catch (
const std::ofstream::failure &e)
730 template <
typename T,
typename TensorType>
740 window, [&](
const Coordinates &) { *
reinterpret_cast<T *
>(it_tensor.
ptr()) = value; }, it_tensor);
745 template <
typename T,
typename TensorType>
751 template <
typename T,
typename TensorType>
764 window, [&](
const Coordinates &) { *
reinterpret_cast<T *
>(it_tensor.
ptr()) = vec.at(i++); }, it_tensor);
769 template <
typename T,
typename TensorType>
771 std::random_device::result_type seed,
773 T upper_bound = std::numeric_limits<T>::max())
775 constexpr
bool is_fp_16bit = std::is_same<T, half>::value || std::is_same<T, bfloat16>::value;
776 constexpr
bool is_integral = std::is_integral<T>::value && !is_fp_16bit;
778 using fp_dist_type =
typename std::conditional<is_fp_16bit, arm_compute::utils::uniform_real_distribution_16bit<T>,
779 std::uniform_real_distribution<T>>
::type;
780 using dist_type =
typename std::conditional<is_integral, std::uniform_int_distribution<T>, fp_dist_type>
::type;
782 std::mt19937 gen(seed);
783 dist_type dist(lower_bound, upper_bound);
792 window, [&](
const Coordinates &) { *
reinterpret_cast<T *
>(it.
ptr()) = dist(gen); }, it);
797 template <
typename T,
typename TensorType>
800 T upper_bound = std::numeric_limits<T>::max())
802 std::random_device rd;
806 template <
typename T>
810 TensorShape(src1.info()->dimension(0), src0.info()->dimension(1), src0.info()->dimension(2)), 1,
dt));
826 template <
typename T>
832 int num_mismatches = 0;
839 Iterator itensor1(&tensor1, window);
840 Iterator itensor2(&tensor2, window);
846 if (std::abs(*
reinterpret_cast<T *
>(itensor1.
ptr()) - *
reinterpret_cast<T *
>(itensor2.
ptr())) > tolerance)
856 return num_mismatches;