diff options
author | Anthony Barbier <anthony.barbier@arm.com> | 2018-02-22 15:45:35 +0000 |
---|---|---|
committer | Anthony Barbier <anthony.barbier@arm.com> | 2018-02-23 11:49:54 +0000 |
commit | 06ea048f062a50404b1b3998a61a45449c2d1f0f (patch) | |
tree | aa0dea3b0c49422538df9a5a02578b2c29e6fa67 /utils | |
parent | 292227986edb37b01061afcad6df18ba9d6ccbeb (diff) | |
download | armcl-06ea048f062a50404b1b3998a61a45449c2d1f0f.tar.gz armcl-06ea048f062a50404b1b3998a61a45449c2d1f0f.tar.bz2 armcl-06ea048f062a50404b1b3998a61a45449c2d1f0f.zip |
arm_compute v18.02
Change-Id: I7207aa488e5470f235f39b6c188b4678dc38d1a6
Diffstat (limited to 'utils')
-rw-r--r-- | utils/GraphUtils.cpp | 105 | ||||
-rw-r--r-- | utils/GraphUtils.h | 87 | ||||
-rw-r--r-- | utils/TypePrinter.h | 81 | ||||
-rw-r--r-- | utils/Utils.cpp | 36 | ||||
-rw-r--r-- | utils/Utils.h | 6 |
5 files changed, 235 insertions, 80 deletions
diff --git a/utils/GraphUtils.cpp b/utils/GraphUtils.cpp index f190af488..448343a97 100644 --- a/utils/GraphUtils.cpp +++ b/utils/GraphUtils.cpp @@ -23,8 +23,9 @@ */ #include "utils/GraphUtils.h" -#include "utils/Utils.h" + #include "arm_compute/runtime/SubTensor.h" +#include "utils/Utils.h" #ifdef ARM_COMPUTE_CL #include "arm_compute/core/CL/OpenCL.h" @@ -35,6 +36,41 @@ using namespace arm_compute::graph_utils; +void TFPreproccessor::preprocess(ITensor &tensor) +{ + Window window; + window.use_tensor_dimensions(tensor.info()->tensor_shape()); + + execute_window_loop(window, [&](const Coordinates & id) + { + const float value = *reinterpret_cast<float *>(tensor.ptr_to_element(id)); + float res = value / 255.f; // Normalize to [0, 1] + res = (res - 0.5f) * 2.f; // Map to [-1, 1] + *reinterpret_cast<float *>(tensor.ptr_to_element(id)) = res; + }); +} + +CaffePreproccessor::CaffePreproccessor(std::array<float, 3> mean, bool bgr) + : _mean(mean), _bgr(bgr) +{ + if(_bgr) + { + std::swap(_mean[0], _mean[2]); + } +} + +void CaffePreproccessor::preprocess(ITensor &tensor) +{ + Window window; + window.use_tensor_dimensions(tensor.info()->tensor_shape()); + + execute_window_loop(window, [&](const Coordinates & id) + { + const float value = *reinterpret_cast<float *>(tensor.ptr_to_element(id)) - _mean[id.z()]; + *reinterpret_cast<float *>(tensor.ptr_to_element(id)) = value; + }); +} + PPMWriter::PPMWriter(std::string name, unsigned int maximum) : _name(std::move(name)), _iterator(0), _maximum(maximum) { @@ -75,28 +111,14 @@ bool DummyAccessor::access_tensor(ITensor &tensor) return ret; } -PPMAccessor::PPMAccessor(std::string ppm_path, bool bgr, - float mean_r, float mean_g, float mean_b, - float std_r, float std_g, float std_b) - : _ppm_path(std::move(ppm_path)), _bgr(bgr), _mean_r(mean_r), _mean_g(mean_g), _mean_b(mean_b), _std_r(std_r), _std_g(std_g), _std_b(std_b) +PPMAccessor::PPMAccessor(std::string ppm_path, bool bgr, std::unique_ptr<IPreprocessor> preprocessor) + : _ppm_path(std::move(ppm_path)), _bgr(bgr), _preprocessor(std::move(preprocessor)) { } bool PPMAccessor::access_tensor(ITensor &tensor) { utils::PPMLoader ppm; - const float mean[3] = - { - _bgr ? _mean_b : _mean_r, - _mean_g, - _bgr ? _mean_r : _mean_b - }; - const float std[3] = - { - _bgr ? _std_b : _std_r, - _std_g, - _bgr ? _std_r : _std_b - }; // Open PPM file ppm.open(_ppm_path); @@ -107,15 +129,11 @@ bool PPMAccessor::access_tensor(ITensor &tensor) // Fill the tensor with the PPM content (BGR) ppm.fill_planar_tensor(tensor, _bgr); - // Subtract the mean value from each channel - Window window; - window.use_tensor_dimensions(tensor.info()->tensor_shape()); - - execute_window_loop(window, [&](const Coordinates & id) + // Preprocess tensor + if(_preprocessor) { - const float value = *reinterpret_cast<float *>(tensor.ptr_to_element(id)) - mean[id.z()]; - *reinterpret_cast<float *>(tensor.ptr_to_element(id)) = value / std[id.z()]; - }); + _preprocessor->preprocess(tensor); + } return true; } @@ -207,7 +225,7 @@ void RandomAccessor::fill(ITensor &tensor, D &&distribution) { std::mt19937 gen(_seed); - if(tensor.info()->padding().empty() && !dynamic_cast<SubTensor*>(&tensor)) + if(tensor.info()->padding().empty() && (dynamic_cast<SubTensor *>(&tensor) == nullptr)) { for(size_t offset = 0; offset < tensor.info()->total_size(); offset += tensor.info()->element_size()) { @@ -331,26 +349,39 @@ bool NumPyBinLoader::access_tensor(ITensor &tensor) std::string expect_typestr = arm_compute::utils::get_typestring(tensor.info()->data_type()); ARM_COMPUTE_ERROR_ON_MSG(typestr != expect_typestr, "Typestrings mismatch"); - // Validate tensor shape - ARM_COMPUTE_ERROR_ON_MSG(shape.size() != tensor_shape.num_dimensions(), "Tensor ranks mismatch"); + // Reverse vector in case of non fortran order + if(!fortran_order) + { + std::reverse(shape.begin(), shape.end()); + } - if(fortran_order) + // Correct dimensions (Needs to match TensorShape dimension corrections) + if(shape.size() != tensor_shape.num_dimensions()) { - for(size_t i = 0; i < shape.size(); ++i) + for(int i = static_cast<int>(shape.size()) - 1; i > 0; --i) { - ARM_COMPUTE_ERROR_ON_MSG(tensor_shape[i] != shape[i], "Tensor dimensions mismatch"); + if(shape[i] == 1) + { + shape.pop_back(); + } + else + { + break; + } } } - else + + // Validate tensor ranks + ARM_COMPUTE_ERROR_ON_MSG(shape.size() != tensor_shape.num_dimensions(), "Tensor ranks mismatch"); + + // Validate shapes + for(size_t i = 0; i < shape.size(); ++i) { - for(size_t i = 0; i < shape.size(); ++i) - { - ARM_COMPUTE_ERROR_ON_MSG(tensor_shape[i] != shape[shape.size() - i - 1], "Tensor dimensions mismatch"); - } + ARM_COMPUTE_ERROR_ON_MSG(tensor_shape[i] != shape[i], "Tensor dimensions mismatch"); } // Read data - if(tensor.info()->padding().empty() && !dynamic_cast<SubTensor*>(&tensor)) + if(tensor.info()->padding().empty() && (dynamic_cast<SubTensor *>(&tensor) == nullptr)) { // If tensor has no padding read directly from stream. stream.read(reinterpret_cast<char *>(tensor.buffer()), tensor.info()->total_size()); diff --git a/utils/GraphUtils.h b/utils/GraphUtils.h index da52c2652..cc6f40417 100644 --- a/utils/GraphUtils.h +++ b/utils/GraphUtils.h @@ -29,6 +29,7 @@ #include "arm_compute/graph/ITensorAccessor.h" #include "arm_compute/graph/Types.h" +#include <array> #include <random> #include <string> #include <vector> @@ -37,6 +38,38 @@ namespace arm_compute { namespace graph_utils { +/** Preprocessor interface **/ +class IPreprocessor +{ +public: + virtual ~IPreprocessor() = default; + virtual void preprocess(ITensor &tensor) = 0; +}; + +/** Caffe preproccessor */ +class CaffePreproccessor : public IPreprocessor +{ +public: + /** Default Constructor + * + * @param mean Mean array in RGB ordering + * @param bgr Boolean specifying if the preprocessing should assume BGR format + */ + CaffePreproccessor(std::array<float, 3> mean = std::array<float, 3> { { 0, 0, 0 } }, bool bgr = true); + void preprocess(ITensor &tensor) override; + +private: + std::array<float, 3> _mean; + bool _bgr; +}; + +/** TF preproccessor */ +class TFPreproccessor : public IPreprocessor +{ +public: + void preprocess(ITensor &tensor) override; +}; + /** PPM writer class */ class PPMWriter : public graph::ITensorAccessor { @@ -85,18 +118,11 @@ class PPMAccessor final : public graph::ITensorAccessor public: /** Constructor * - * @param[in] ppm_path Path to PPM file - * @param[in] bgr (Optional) Fill the first plane with blue channel (default = false) - * @param[in] mean_r (Optional) Red mean value to be subtracted from red channel - * @param[in] mean_g (Optional) Green mean value to be subtracted from green channel - * @param[in] mean_b (Optional) Blue mean value to be subtracted from blue channel - * @param[in] std_r (Optional) Red standard deviation value to be divided from red channel - * @param[in] std_g (Optional) Green standard deviation value to be divided from green channel - * @param[in] std_b (Optional) Blue standard deviation value to be divided from blue channel + * @param[in] ppm_path Path to PPM file + * @param[in] bgr (Optional) Fill the first plane with blue channel (default = false) + * @param[in] preprocessor (Optional) PPM pre-processing object */ - PPMAccessor(std::string ppm_path, bool bgr = true, - float mean_r = 0.0f, float mean_g = 0.0f, float mean_b = 0.0f, - float std_r = 1.f, float std_g = 1.f, float std_b = 1.f); + PPMAccessor(std::string ppm_path, bool bgr = true, std::unique_ptr<IPreprocessor> preprocessor = nullptr); /** Allow instances of this class to be move constructed */ PPMAccessor(PPMAccessor &&) = default; @@ -104,14 +130,9 @@ public: bool access_tensor(ITensor &tensor) override; private: - const std::string _ppm_path; - const bool _bgr; - const float _mean_r; - const float _mean_g; - const float _mean_b; - const float _std_r; - const float _std_g; - const float _std_b; + const std::string _ppm_path; + const bool _bgr; + std::unique_ptr<IPreprocessor> _preprocessor; }; /** Result accessor class */ @@ -226,21 +247,15 @@ inline std::unique_ptr<graph::ITensorAccessor> get_weights_accessor(const std::s * * @note If ppm_path is empty will generate a DummyAccessor else will generate a PPMAccessor * - * @param[in] ppm_path Path to PPM file - * @param[in] mean_r Red mean value to be subtracted from red channel - * @param[in] mean_g Green mean value to be subtracted from green channel - * @param[in] mean_b Blue mean value to be subtracted from blue channel - * @param[in] std_r (Optional) Red standard deviation value to be divided from red channel - * @param[in] std_g (Optional) Green standard deviation value to be divided from green channel - * @param[in] std_b (Optional) Blue standard deviation value to be divided from blue channel - * @param[in] bgr (Optional) Fill the first plane with blue channel (default = true) + * @param[in] ppm_path Path to PPM file + * @param[in] preprocessor Preproccessor object + * @param[in] bgr (Optional) Fill the first plane with blue channel (default = true) * * @return An appropriate tensor accessor */ -inline std::unique_ptr<graph::ITensorAccessor> get_input_accessor(const std::string &ppm_path, - float mean_r = 0.f, float mean_g = 0.f, float mean_b = 0.f, - float std_r = 1.f, float std_g = 1.f, float std_b = 1.f, - bool bgr = true) +inline std::unique_ptr<graph::ITensorAccessor> get_input_accessor(const std::string &ppm_path, + std::unique_ptr<IPreprocessor> preprocessor = nullptr, + bool bgr = true) { if(ppm_path.empty()) { @@ -248,22 +263,20 @@ inline std::unique_ptr<graph::ITensorAccessor> get_input_accessor(const std::str } else { - return arm_compute::support::cpp14::make_unique<PPMAccessor>(ppm_path, bgr, - mean_r, mean_g, mean_b, - std_r, std_g, std_b); + return arm_compute::support::cpp14::make_unique<PPMAccessor>(ppm_path, bgr, std::move(preprocessor)); } } /** Utility function to return the TargetHint * - * @param[in] target Integer value which expresses the selected target. Must be 0 for NEON or 1 for OpenCL + * @param[in] target Integer value which expresses the selected target. Must be 0 for NEON, 1 for OpenCL or 2 for OpenCL with Tuner * * @return the TargetHint */ inline graph::TargetHint set_target_hint(int target) { - ARM_COMPUTE_ERROR_ON_MSG(target > 1, "Invalid target. Target must be 0 (NEON) or 1 (OpenCL)"); - if(target == 1 && graph::Graph::opencl_is_available()) + ARM_COMPUTE_ERROR_ON_MSG(target > 2, "Invalid target. Target must be 0 (NEON), 1 (OpenCL) or 2 (OpenCL with Tuner)"); + if((target == 1 || target == 2) && graph::Graph::opencl_is_available()) { // If type of target is OpenCL, check if OpenCL is available and initialize the scheduler return graph::TargetHint::OPENCL; diff --git a/utils/TypePrinter.h b/utils/TypePrinter.h index 2dc2d787d..313fad1a5 100644 --- a/utils/TypePrinter.h +++ b/utils/TypePrinter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018 ARM Limited. + * Copyright (c) 2017-2018 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -24,6 +24,7 @@ #ifndef __ARM_COMPUTE_TEST_TYPE_PRINTER_H__ #define __ARM_COMPUTE_TEST_TYPE_PRINTER_H__ +#include "arm_compute/core/CL/CLTypes.h" #include "arm_compute/core/Dimensions.h" #include "arm_compute/core/Error.h" #include "arm_compute/core/HOGInfo.h" @@ -290,14 +291,14 @@ inline ::std::ostream &operator<<(::std::ostream &os, const NormType &norm_type) inline std::string to_string(const arm_compute::NormalizationLayerInfo &info) { std::stringstream str; - str << info.type(); + str << info.type() << ":NormSize=" << info.norm_size(); return str.str(); } /** Formatted output of @ref NormalizationLayerInfo. */ inline ::std::ostream &operator<<(::std::ostream &os, const NormalizationLayerInfo &info) { - os << info.type(); + os << info.type() << ":NormSize=" << info.norm_size(); return os; } @@ -522,6 +523,13 @@ inline ::std::ostream &operator<<(::std::ostream &os, const Channel &channel) return os; } +inline std::string to_string(const Channel &channel) +{ + std::stringstream str; + str << channel; + return str.str(); +} + /** Formatted output of the BorderMode type. */ inline ::std::ostream &operator<<(::std::ostream &os, const BorderMode &mode) { @@ -759,7 +767,7 @@ inline std::string to_string(const PoolingLayerInfo &info) if(!info.is_global_pooling()) { str << "," - << "PoolSize=" << info.pool_size() << "," + << "PoolSize=" << info.pool_size().width << "," << info.pool_size().height << "," << "PadStride=" << info.pad_stride_info(); } str << "}"; @@ -924,5 +932,70 @@ inline std::string to_string(const HOGInfo &type) return str.str(); } +inline ::std::ostream &operator<<(::std::ostream &os, const ConvolutionMethod &conv_method) +{ + switch(conv_method) + { + case ConvolutionMethod::GEMM: + os << "GEMM"; + break; + case ConvolutionMethod::DIRECT: + os << "DIRECT"; + break; + case ConvolutionMethod::WINOGRAD: + os << "WINOGRAD"; + break; + default: + ARM_COMPUTE_ERROR("NOT_SUPPORTED!"); + } + + return os; +} + +inline std::string to_string(const ConvolutionMethod &conv_method) +{ + std::stringstream str; + str << conv_method; + return str.str(); +} + +inline ::std::ostream &operator<<(::std::ostream &os, const GPUTarget &gpu_target) +{ + switch(gpu_target) + { + case GPUTarget::GPU_ARCH_MASK: + os << "GPU_ARCH_MASK"; + break; + case GPUTarget::MIDGARD: + os << "MIDGARD"; + break; + case GPUTarget::BIFROST: + os << "BIFROST"; + break; + case GPUTarget::T600: + os << "T600"; + break; + case GPUTarget::T700: + os << "T700"; + break; + case GPUTarget::T800: + os << "T800"; + break; + case GPUTarget::G70: + os << "G70"; + break; + default: + ARM_COMPUTE_ERROR("NOT_SUPPORTED!"); + } + + return os; +} + +inline std::string to_string(const GPUTarget &gpu_target) +{ + std::stringstream str; + str << gpu_target; + return str.str(); +} } // namespace arm_compute #endif /* __ARM_COMPUTE_TEST_TYPE_PRINTER_H__ */ diff --git a/utils/Utils.cpp b/utils/Utils.cpp index 32d5e3a6c..8a2d11814 100644 --- a/utils/Utils.cpp +++ b/utils/Utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018 ARM Limited. + * Copyright (c) 2017-2018 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -191,5 +191,39 @@ std::tuple<std::vector<unsigned long>, bool, std::string> parse_npy_header(std:: return std::make_tuple(shape, fortran_order, typestr); } + +/** This function returns the amount of memory free reading from /proc/meminfo + * + * @return The free memory in kB + */ +uint64_t get_mem_free_from_meminfo() +{ + std::string line_attribute; + std::ifstream file_meminfo("/proc/meminfo"); + + if(file_meminfo.is_open()) + { + while(!(file_meminfo >> line_attribute).fail()) + { + //Test if is the line containing MemFree + if(line_attribute == "MemFree:") + { + uint64_t mem_available; + if(!(file_meminfo >> mem_available).fail()) + { + return mem_available; + } + else + { + return 0; + } + } + // if it's not MemFree ignore rest of the line + file_meminfo.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); + } + } + // Nothing found or an error during opening the file + return 0; +} } // namespace utils } // namespace arm_compute diff --git a/utils/Utils.h b/utils/Utils.h index 83468d861..4cce39fbc 100644 --- a/utils/Utils.h +++ b/utils/Utils.h @@ -895,7 +895,11 @@ void init_sgemm_output(T &dst, T &src0, T &src1, arm_compute::DataType dt) { dst.allocator()->init(TensorInfo(TensorShape(src1.info()->dimension(0), src0.info()->dimension(1)), 1, dt)); } - +/** This function returns the amount of memory free reading from /proc/meminfo + * + * @return The free memory in kB + */ +uint64_t get_mem_free_from_meminfo(); } // namespace utils } // namespace arm_compute #endif /* __UTILS_UTILS_H__*/ |