diff options
-rw-r--r-- | arm_compute/core/CPP/CPPTypes.h | 41 | ||||
-rw-r--r-- | arm_compute/core/Types.h | 4 | ||||
-rw-r--r-- | examples/graph_vgg16.cpp | 10 | ||||
-rw-r--r-- | examples/graph_vgg19.cpp | 10 | ||||
-rw-r--r-- | src/runtime/MEMUtils.cpp | 111 | ||||
-rw-r--r-- | src/runtime/NEON/functions/NEGEMM.cpp | 9 |
6 files changed, 182 insertions, 3 deletions
diff --git a/arm_compute/core/CPP/CPPTypes.h b/arm_compute/core/CPP/CPPTypes.h index 9ffb4840a3..0ac8bf6e52 100644 --- a/arm_compute/core/CPP/CPPTypes.h +++ b/arm_compute/core/CPP/CPPTypes.h @@ -26,6 +26,7 @@ #include "arm_compute/core/Error.h" +#include <array> #include <string> #include <vector> @@ -46,6 +47,19 @@ enum class CPUModel A55r1 }; +/** Global memory policy. + * The functions in the runtime will use different strategies based on the policy currently set. + * + * MINIMIZE will try to reduce the amount allocated by the functions at the expense of performance normally. + * NORMAL won't try to save any memory and will favor speed over memory consumption + * + */ +enum class MemoryPolicy +{ + MINIMIZE, + NORMAL +}; + /** Convert a cpumodel value to a string * * @param val CPUModel value to be converted @@ -180,6 +194,33 @@ private: unsigned int _L2_cache_size = 262144; }; +class MEMInfo final +{ +public: + MEMInfo(); + + /** Return the total amount of RAM memory in the system expressed in KB. + * + * @return Total memory + */ + size_t get_total_in_kb() const; + + static void set_policy(MemoryPolicy policy); + static MemoryPolicy get_policy(); + + /** Common memory sizes expressed in Kb to avoid having them + * duplicated throughout the code. + */ + static const size_t ONE_GB_IN_KB = { 1035842 }; + static const size_t TWO_GB_IN_KB = { ONE_GB_IN_KB * 2 }; + +private: + size_t _total; + size_t _free; + size_t _buffer; + static MemoryPolicy _policy; +}; + /** Information about executing thread and CPU. */ struct ThreadInfo { diff --git a/arm_compute/core/Types.h b/arm_compute/core/Types.h index 0240916da8..8df5c65e1e 100644 --- a/arm_compute/core/Types.h +++ b/arm_compute/core/Types.h @@ -940,8 +940,8 @@ public: * @param[in] weights (Optional)Weights [wx, wy, ww, wh] for the deltas. Defaults to all ones * @param[in] bbox_xform_clip (Optional)Minimum bounding box width and height after bounding box transformation in log-space. Defaults to log(1000/16) */ - BoundingBoxTransformInfo(float img_width, float img_height, float scale, bool apply_scale = false, const std::array<float, 4> weights = { 1.0, 1.0, 1.0, 1.0 }, float bbox_xform_clip = - 4.135166556742356) + BoundingBoxTransformInfo(float img_width, float img_height, float scale, bool apply_scale = false, const std::array<float, 4> weights = { { 1.f, 1.f, 1.f, 1.f } }, float bbox_xform_clip = + 4.135166556742356f) : _img_width(img_width), _img_height(img_height), _scale(scale), _apply_scale(apply_scale), _weights(weights), _bbox_xform_clip(bbox_xform_clip) { } diff --git a/examples/graph_vgg16.cpp b/examples/graph_vgg16.cpp index 4b5f33a7e8..482aab1683 100644 --- a/examples/graph_vgg16.cpp +++ b/examples/graph_vgg16.cpp @@ -41,6 +41,16 @@ public: } bool do_setup(int argc, char **argv) override { + // Check if the system has enough RAM to run the example, systems with less than 2GB have + // to hint the API to minimize memory consumption otherwise it'll run out of memory and + // fail throwing the bad_alloc exception + arm_compute::MEMInfo meminfo; + const size_t mem_total = meminfo.get_total_in_kb(); + if(mem_total <= arm_compute::MEMInfo::TWO_GB_IN_KB) + { + arm_compute::MEMInfo::set_policy(arm_compute::MemoryPolicy::MINIMIZE); + } + // Parse arguments cmd_parser.parse(argc, argv); diff --git a/examples/graph_vgg19.cpp b/examples/graph_vgg19.cpp index ff7cf751a1..3b1773519a 100644 --- a/examples/graph_vgg19.cpp +++ b/examples/graph_vgg19.cpp @@ -40,6 +40,16 @@ public: } bool do_setup(int argc, char **argv) override { + // Check if the system has enough RAM to run the example, systems with less than 2GB have + // to hint the API to minimize memory consumption otherwise it'll run out of memory and + // fail throwing the bad_alloc exception + arm_compute::MEMInfo meminfo; + const size_t mem_total = meminfo.get_total_in_kb(); + if(mem_total <= arm_compute::MEMInfo::TWO_GB_IN_KB) + { + arm_compute::MEMInfo::set_policy(arm_compute::MemoryPolicy::MINIMIZE); + } + // Parse arguments cmd_parser.parse(argc, argv); diff --git a/src/runtime/MEMUtils.cpp b/src/runtime/MEMUtils.cpp new file mode 100644 index 0000000000..ad00070935 --- /dev/null +++ b/src/runtime/MEMUtils.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "arm_compute/core/CPP/CPPTypes.h" +#include "arm_compute/core/Error.h" +#include "support/ToolchainSupport.h" + +#ifndef BARE_METAL +#include <fstream> +#include <regex> +#include <sstream> +#endif // ifndef BARE_METAL + +namespace +{ +void parse_mem_info(size_t &total, size_t &free, size_t &buffer) +{ + free = 0; + total = 0; + buffer = 0; +#ifndef BARE_METAL + size_t memcache = 0; + size_t memfree = 0; + std::ifstream meminfo_f; + meminfo_f.open("/proc/meminfo", std::ios::in); + if(meminfo_f.is_open()) + { + std::stringstream str_stream; + str_stream << meminfo_f.rdbuf(); + const std::string str = str_stream.str(); + try + { + std::smatch match; + if(std::regex_search(str, match, std::regex("MemTotal: (.*)kB")) && match.size() > 1) + { + const std::string result = match.str(1); + total = std::stoul(result, nullptr, 0); + } + if(std::regex_search(str, match, std::regex("MemFree: (.*)kB")) && match.size() > 1) + { + const std::string result = match.str(1); + memfree = std::stoul(result, nullptr, 0); + } + if(std::regex_search(str, match, std::regex("Buffers: (.*)kB")) && match.size() > 1) + { + const std::string result = match.str(1); + buffer = std::stoul(result, nullptr, 0); + } + if(std::regex_search(str, match, std::regex("Cached: (.*)kB")) && match.size() > 1) + { + const std::string result = match.str(1); + memcache = std::stoul(result, nullptr, 0); + } + free = memfree + (buffer + memcache); + } + catch(std::regex_error &e) + { + // failed parsing /proc/meminfo + // return 0s on all fields + } + } +#endif // ifndef BARE_METAL +} + +} // namespace + +namespace arm_compute +{ +void MEMInfo::set_policy(MemoryPolicy policy) +{ + _policy = policy; +} + +MemoryPolicy MEMInfo::get_policy() +{ + return _policy; +} +MemoryPolicy MEMInfo::_policy = { MemoryPolicy::NORMAL }; + +MEMInfo::MEMInfo() + : _total(0), _free(0), _buffer(0) +{ + parse_mem_info(_total, _free, _buffer); +} + +size_t MEMInfo::get_total_in_kb() const +{ + return _total; +} + +} // namespace arm_compute diff --git a/src/runtime/NEON/functions/NEGEMM.cpp b/src/runtime/NEON/functions/NEGEMM.cpp index e8bf6732b2..82b9cb80ae 100644 --- a/src/runtime/NEON/functions/NEGEMM.cpp +++ b/src/runtime/NEON/functions/NEGEMM.cpp @@ -62,7 +62,14 @@ void NEGEMM::configure(const ITensor *a, const ITensor *b, const ITensor *c, ITe if(run_optimised) { - _asm_glue.configure(a, b, d, alpha, beta, _reshape_b_only_on_first_run); + if(MEMInfo::get_policy() == MemoryPolicy::MINIMIZE) + { + _asm_glue.configure(a, b, d, alpha, beta, false); + } + else + { + _asm_glue.configure(a, b, d, alpha, beta, _reshape_b_only_on_first_run); + } ARM_COMPUTE_ERROR_ON(!_asm_glue.is_configured()); } else |