From 53b405f1e08ad41cb9a527abfe0308ec1edf18ff Mon Sep 17 00:00:00 2001 From: Michalis Spyrou Date: Wed, 27 Sep 2017 15:55:31 +0100 Subject: COMPMID-417 - Add RandomAccessor support in Graph API. Change-Id: I54dd435258a2d0ff486ded64b23654bab6b80f3f Reviewed-on: http://mpd-gerrit.cambridge.arm.com/89373 Tested-by: Kaizen Reviewed-by: Georgios Pinitas --- arm_compute/core/PixelValue.h | 66 +++++++++++++++++++++++++ utils/GraphUtils.cpp | 112 ++++++++++++++++++++++++++++++++++++++++++ utils/GraphUtils.h | 32 +++++++++++- 3 files changed, 208 insertions(+), 2 deletions(-) diff --git a/arm_compute/core/PixelValue.h b/arm_compute/core/PixelValue.h index 63405560ea..ce3726b6fc 100644 --- a/arm_compute/core/PixelValue.h +++ b/arm_compute/core/PixelValue.h @@ -84,6 +84,25 @@ public: { value.s32 = v; } + + /** Initialize the union with a U64 pixel value + * + * @param[in] v U64 value. + */ + PixelValue(uint64_t v) + : PixelValue() + { + value.u64 = v; + } + /** Initialize the union with a S64 pixel value + * + * @param[in] v S64 value. + */ + PixelValue(int64_t v) + : PixelValue() + { + value.s64 = v; + } /** Initialize the union with a F16 pixel value * * @param[in] v F16 value. @@ -102,6 +121,15 @@ public: { value.f32 = v; } + /** Initialize the union with a F64 pixel value + * + * @param[in] v F64 value. + */ + PixelValue(double v) + : PixelValue() + { + value.f64 = v; + } /** Union which describes the value of a pixel for any image format. * Use the field corresponding to the image format */ @@ -110,6 +138,7 @@ public: uint8_t rgb[3]; /**< 3 channels: RGB888 */ uint8_t yuv[3]; /**< 3 channels: Any YUV format */ uint8_t rgbx[4]; /**< 4 channels: RGBX8888 */ + double f64; /**< Single channel double */ float f32; /**< Single channel float 32 */ half f16; /**< Single channel F16 */ uint8_t u8; /**< Single channel U8 */ @@ -118,6 +147,8 @@ public: int16_t s16; /**< Single channel S16 */ uint32_t u32; /**< Single channel U32 */ int32_t s32; /**< Single channel S32 */ + uint64_t u64; /**< Single channel U64 */ + int64_t s64; /**< Single channel S64 */ } value; /** Interpret the pixel value as a U8 * @@ -167,6 +198,22 @@ public: { v = value.s32; } + /** Interpret the pixel value as a U64 + * + * @param[out] v Returned value + */ + void get(uint64_t &v) const + { + v = value.u64; + } + /** Interpret the pixel value as a S64 + * + * @param[out] v Returned value + */ + void get(int64_t &v) const + { + v = value.s64; + } /** Interpret the pixel value as a F16 * * @param[out] v Returned value @@ -183,6 +230,25 @@ public: { v = value.f32; } + /** Interpret the pixel value as a double + * + * @param[out] v Returned value + */ + void get(double &v) const + { + v = value.f64; + } + /** Get the pixel value + * + * @return Pixel value + */ + template + T get() const + { + T val; + get(val); + return val; + } }; } #endif /* __ARM_COMPUTE_PIXELVALUE_H__ */ diff --git a/utils/GraphUtils.cpp b/utils/GraphUtils.cpp index d763606867..f0b0dded18 100644 --- a/utils/GraphUtils.cpp +++ b/utils/GraphUtils.cpp @@ -31,8 +31,10 @@ #endif /* ARM_COMPUTE_CL */ #include "arm_compute/core/Error.h" +#include "arm_compute/core/PixelValue.h" #include "libnpy/npy.hpp" +#include #include using namespace arm_compute::graph_utils; @@ -85,6 +87,116 @@ bool DummyAccessor::access_tensor(ITensor &tensor) return ret; } +RandomAccessor::RandomAccessor(PixelValue lower, PixelValue upper, std::random_device::result_type seed) + : _lower(lower), _upper(upper), _seed(seed) +{ +} + +template +void RandomAccessor::fill(ITensor &tensor, D &&distribution) +{ + std::mt19937 gen(_seed); + + if(tensor.info()->padding().empty()) + { + for(size_t offset = 0; offset < tensor.info()->total_size(); offset += tensor.info()->element_size()) + { + const T value = distribution(gen); + *reinterpret_cast(tensor.buffer() + offset) = value; + } + } + else + { + // If tensor has padding accessing tensor elements through execution window. + Window window; + window.use_tensor_dimensions(tensor.info()->tensor_shape()); + + execute_window_loop(window, [&](const Coordinates & id) + { + const T value = distribution(gen); + *reinterpret_cast(tensor.ptr_to_element(id)) = value; + }); + } +} + +bool RandomAccessor::access_tensor(ITensor &tensor) +{ + switch(tensor.info()->data_type()) + { + case DataType::U8: + { + std::uniform_int_distribution distribution_u8(_lower.get(), _upper.get()); + fill(tensor, distribution_u8); + break; + } + case DataType::S8: + case DataType::QS8: + { + std::uniform_int_distribution distribution_s8(_lower.get(), _upper.get()); + fill(tensor, distribution_s8); + break; + } + case DataType::U16: + { + std::uniform_int_distribution distribution_u16(_lower.get(), _upper.get()); + fill(tensor, distribution_u16); + break; + } + case DataType::S16: + case DataType::QS16: + { + std::uniform_int_distribution distribution_s16(_lower.get(), _upper.get()); + fill(tensor, distribution_s16); + break; + } + case DataType::U32: + { + std::uniform_int_distribution distribution_u32(_lower.get(), _upper.get()); + fill(tensor, distribution_u32); + break; + } + case DataType::S32: + { + std::uniform_int_distribution distribution_s32(_lower.get(), _upper.get()); + fill(tensor, distribution_s32); + break; + } + case DataType::U64: + { + std::uniform_int_distribution distribution_u64(_lower.get(), _upper.get()); + fill(tensor, distribution_u64); + break; + } + case DataType::S64: + { + std::uniform_int_distribution distribution_s64(_lower.get(), _upper.get()); + fill(tensor, distribution_s64); + break; + } + case DataType::F16: + { + std::uniform_real_distribution distribution_f16(_lower.get(), _upper.get()); + fill(tensor, distribution_f16); + break; + } + case DataType::F32: + { + std::uniform_real_distribution distribution_f32(_lower.get(), _upper.get()); + fill(tensor, distribution_f32); + break; + } + case DataType::F64: + { + std::uniform_real_distribution distribution_f64(_lower.get(), _upper.get()); + fill(tensor, distribution_f64); + break; + } + default: + ARM_COMPUTE_ERROR("NOT SUPPORTED!"); + } + return true; +} + NumPyBinLoader::NumPyBinLoader(std::string filename) : _filename(std::move(filename)) { diff --git a/utils/GraphUtils.h b/utils/GraphUtils.h index a19f7e510d..c8cbb00237 100644 --- a/utils/GraphUtils.h +++ b/utils/GraphUtils.h @@ -24,9 +24,12 @@ #ifndef __ARM_COMPUTE_GRAPH_UTILS_H__ #define __ARM_COMPUTE_GRAPH_UTILS_H__ +#include "arm_compute/core/PixelValue.h" #include "arm_compute/graph/ITensorAccessor.h" #include "arm_compute/graph/Types.h" +#include + namespace arm_compute { namespace graph_utils @@ -54,7 +57,7 @@ private: }; /** Dummy accessor class */ -class DummyAccessor : public graph::ITensorAccessor +class DummyAccessor final : public graph::ITensorAccessor { public: /** Constructor @@ -73,8 +76,33 @@ private: unsigned int _maximum; }; +/** Random accessor class */ +class RandomAccessor final : public graph::ITensorAccessor +{ +public: + /** Constructor + * + * @param[in] lower Lower bound value. + * @param[in] upper Upper bound value. + * @param[in] seed (Optional) Seed used to initialise the random number generator. + */ + RandomAccessor(PixelValue lower, PixelValue upper, const std::random_device::result_type seed = 0); + /** Allows instances to move constructed */ + RandomAccessor(RandomAccessor &&) = default; + + // Inherited methods overriden: + bool access_tensor(ITensor &tensor) override; + +private: + template + void fill(ITensor &tensor, D &&distribution); + PixelValue _lower; + PixelValue _upper; + std::random_device::result_type _seed; +}; + /** Numpy Binary loader class*/ -class NumPyBinLoader : public graph::ITensorAccessor +class NumPyBinLoader final : public graph::ITensorAccessor { public: /** Default Constructor -- cgit v1.2.1