diff options
author | Georgios Pinitas <georgios.pinitas@arm.com> | 2018-02-01 20:23:25 +0000 |
---|---|---|
committer | Anthony Barbier <anthony.barbier@arm.com> | 2018-11-02 16:45:42 +0000 |
commit | 53d12277563f860852532ace2a6c796384d969dd (patch) | |
tree | e445c005cecea4f44cb2ab51abce82a66181c166 | |
parent | b7e3028a2bf81ca247895b8550f5a5da02d2483e (diff) | |
download | ComputeLibrary-53d12277563f860852532ace2a6c796384d969dd.tar.gz |
COMPMID-874: Improve default number of threads choice in the Scheduler
Change-Id: Ia30ec2afce0aafcd39f41440efb972b18bbda9f8
Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/118657
Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
Tested-by: Jenkins <bsgcomp@arm.com>
Reviewed-by: Pablo Tello <pablo.tello@arm.com>
-rw-r--r-- | arm_compute/runtime/IScheduler.h | 13 | ||||
-rw-r--r-- | src/runtime/CPP/CPPScheduler.cpp | 4 | ||||
-rw-r--r-- | src/runtime/IScheduler.cpp | 64 |
3 files changed, 78 insertions, 3 deletions
diff --git a/arm_compute/runtime/IScheduler.h b/arm_compute/runtime/IScheduler.h index 8918843c98..1dd7c2cfb2 100644 --- a/arm_compute/runtime/IScheduler.h +++ b/arm_compute/runtime/IScheduler.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 ARM Limited. + * Copyright (c) 2017-2018 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -70,9 +70,20 @@ public: * @return CPU info. */ CPUInfo cpu_info() const; + /** Get a hint for the best possible number of execution threads + * + * @warning In case we can't work out the best number of threads, + * std::thread::hardware_concurrency() is returned else 1 in case of bare metal builds + * + * @return Best possible number of execution threads to use + */ + unsigned int num_threads_hint() const; protected: CPUInfo _info{}; + +private: + unsigned int _num_threads_hint = {}; }; } #endif /* __ARM_COMPUTE_ISCHEDULER_H__ */ diff --git a/src/runtime/CPP/CPPScheduler.cpp b/src/runtime/CPP/CPPScheduler.cpp index a83a0bc0d3..4e4dd87ed7 100644 --- a/src/runtime/CPP/CPPScheduler.cpp +++ b/src/runtime/CPP/CPPScheduler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017 ARM Limited. + * Copyright (c) 2016-2018 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -156,7 +156,7 @@ CPPScheduler &CPPScheduler::get() } CPPScheduler::CPPScheduler() - : _num_threads(std::thread::hardware_concurrency()), + : _num_threads(num_threads_hint()), _threads(_num_threads - 1) { } diff --git a/src/runtime/IScheduler.cpp b/src/runtime/IScheduler.cpp index 1d06c4e5e9..583cb40eca 100644 --- a/src/runtime/IScheduler.cpp +++ b/src/runtime/IScheduler.cpp @@ -27,13 +27,68 @@ #include <cstdlib> #include <cstring> #include <fcntl.h> +#include <fstream> +#include <map> #include <sched.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> +#ifndef BARE_METAL +#include <regex> +#include <thread> +#endif /* BARE_METAL */ + namespace { +unsigned int get_threads_hint() +{ + unsigned int num_threads_hint = 1; + +#ifndef BARE_METAL + std::map<std::string, unsigned int> cpu_part_occurrence_map; + + // CPU part regex + std::regex cpu_part_rgx(R"(.*CPU part.+?(?=:).+?(?=\w+)(\w+).*)"); + std::smatch cpu_part_match; + + // Read cpuinfo and get occurrence of each core + std::ifstream cpuinfo; + cpuinfo.open("/proc/cpuinfo", std::ios::in); + if(cpuinfo.is_open()) + { + std::string line; + while(bool(getline(cpuinfo, line))) + { + if(std::regex_search(line.cbegin(), line.cend(), cpu_part_match, cpu_part_rgx)) + { + std::string cpu_part = cpu_part_match[1]; + if(cpu_part_occurrence_map.find(cpu_part) != cpu_part_occurrence_map.end()) + { + cpu_part_occurrence_map[cpu_part]++; + } + else + { + cpu_part_occurrence_map[cpu_part] = 1; + } + } + } + } + + // Get min number of threads + auto min_common_cores = std::min_element(cpu_part_occurrence_map.begin(), cpu_part_occurrence_map.end(), + [](const std::pair<std::string, unsigned int> &p1, const std::pair<std::string, unsigned int> &p2) + { + return p1.second < p2.second; + }); + + // Set thread hint + num_threads_hint = cpu_part_occurrence_map.empty() ? std::thread::hardware_concurrency() : min_common_cores->second; +#endif /* BARE_METAL */ + + return num_threads_hint; +} + unsigned int get_cpu_impl() { #ifndef BARE_METAL @@ -129,6 +184,10 @@ namespace arm_compute { IScheduler::IScheduler() { + // Work out the best possible number of execution threads + _num_threads_hint = get_threads_hint(); + + // Work out the CPU implementation switch(get_cpu_impl()) { case 0xd0f: @@ -161,4 +220,9 @@ CPUInfo IScheduler::cpu_info() const { return _info; } + +unsigned int IScheduler::num_threads_hint() const +{ + return _num_threads_hint; +} } // namespace arm_compute |