|
|
|
@ -58,13 +58,20 @@ |
|
|
|
|
#include <unistd.h> |
|
|
|
|
#include <stdio.h> |
|
|
|
|
#include <sys/types.h> |
|
|
|
|
#include <fstream> |
|
|
|
|
#if defined __ANDROID__ |
|
|
|
|
#include <sys/sysconf.h> |
|
|
|
|
#include <sys/syscall.h> |
|
|
|
|
#include <sched.h> |
|
|
|
|
#elif defined __APPLE__ |
|
|
|
|
#include <sys/sysctl.h> |
|
|
|
|
#endif |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if defined CV_CXX11 |
|
|
|
|
#include <thread> |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef _OPENMP |
|
|
|
|
#define HAVE_OPENMP |
|
|
|
|
#endif |
|
|
|
@ -739,19 +746,40 @@ int cv::getThreadNum(void) |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef __ANDROID__ |
|
|
|
|
static inline int getNumberOfCPUsImpl() |
|
|
|
|
|
|
|
|
|
#if defined __linux__ || defined __GLIBC__ || defined __EMSCRIPTEN__ || defined __HAIKU__ || defined __ANDROID__ |
|
|
|
|
#define CV_CPU_GROUPS_1 |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if defined __linux__ || defined __ANDROID__ |
|
|
|
|
#define CV_HAVE_CGROUPS 1 |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if defined CV_CPU_GROUPS_1 |
|
|
|
|
static inline |
|
|
|
|
std::string getFileContents(const char *filename) |
|
|
|
|
{ |
|
|
|
|
FILE* cpuPossible = fopen("/sys/devices/system/cpu/possible", "r"); |
|
|
|
|
if(!cpuPossible) |
|
|
|
|
return 1; |
|
|
|
|
std::ifstream ifs(filename); |
|
|
|
|
if (!ifs.is_open()) |
|
|
|
|
return std::string(); |
|
|
|
|
|
|
|
|
|
std::string content( (std::istreambuf_iterator<char>(ifs) ), |
|
|
|
|
(std::istreambuf_iterator<char>() ) ); |
|
|
|
|
|
|
|
|
|
char buf[2000]; //big enough for 1000 CPUs in worst possible configuration
|
|
|
|
|
char* pbuf = fgets(buf, sizeof(buf), cpuPossible); |
|
|
|
|
fclose(cpuPossible); |
|
|
|
|
if(!pbuf) |
|
|
|
|
return 1; |
|
|
|
|
if (ifs.fail()) |
|
|
|
|
return std::string(); |
|
|
|
|
|
|
|
|
|
return content; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline |
|
|
|
|
int getNumberOfCPUsImpl(const char *filename) |
|
|
|
|
{ |
|
|
|
|
std::string file_contents = getFileContents(filename); |
|
|
|
|
if(file_contents.empty()) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
char *pbuf = const_cast<char*>(file_contents.c_str()); |
|
|
|
|
//parse string of form "0-1,3,5-7,10,13-15"
|
|
|
|
|
int cpusAvailable = 0; |
|
|
|
|
|
|
|
|
@ -775,12 +803,63 @@ static inline int getNumberOfCPUsImpl() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
return cpusAvailable ? cpusAvailable : 1; |
|
|
|
|
return cpusAvailable; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if defined CV_HAVE_CGROUPS |
|
|
|
|
static inline |
|
|
|
|
unsigned getNumberOfCPUsCFS() |
|
|
|
|
{ |
|
|
|
|
int cfs_quota = 0; |
|
|
|
|
{ |
|
|
|
|
std::ifstream ss_period("/sys/fs/cgroup/cpu/cpu.cfs_quota_us", std::ios::in | std::ios::binary); |
|
|
|
|
ss_period >> cfs_quota; |
|
|
|
|
|
|
|
|
|
if (ss_period.fail() || cfs_quota < 1) /* cfs_quota must not be 0 or negative */ |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int cfs_period = 0; |
|
|
|
|
{ |
|
|
|
|
std::ifstream ss_quota("/sys/fs/cgroup/cpu/cpu.cfs_period_us", std::ios::in | std::ios::binary); |
|
|
|
|
ss_quota >> cfs_period; |
|
|
|
|
|
|
|
|
|
if (ss_quota.fail() || cfs_period < 1) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return (unsigned)max(1, cfs_quota/cfs_period); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
template <typename T> static inline |
|
|
|
|
T minNonZero(const T& val_1, const T& val_2) |
|
|
|
|
{ |
|
|
|
|
if ((val_1 != 0) && (val_2 != 0)) |
|
|
|
|
return std::min(val_1, val_2); |
|
|
|
|
return (val_1 != 0) ? val_1 : val_2; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int cv::getNumberOfCPUs(void) |
|
|
|
|
{ |
|
|
|
|
/*
|
|
|
|
|
* Logic here is to try different methods of getting CPU counts and return |
|
|
|
|
* the minimum most value as it has high probablity of being right and safe. |
|
|
|
|
* Return 1 if we get 0 or not found on all methods. |
|
|
|
|
*/ |
|
|
|
|
#if defined CV_CXX11 |
|
|
|
|
/*
|
|
|
|
|
* Check for this standard C++11 way, we do not return directly because |
|
|
|
|
* running in a docker or K8s environment will mean this is the host |
|
|
|
|
* machines config not the containers or pods and as per docs this value |
|
|
|
|
* must be "considered only a hint". |
|
|
|
|
*/ |
|
|
|
|
unsigned ncpus = std::thread::hardware_concurrency(); /* If the value is not well defined or not computable, returns 0 */ |
|
|
|
|
#else |
|
|
|
|
unsigned ncpus = 0; /* 0 means we have to find out some other way */ |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if defined _WIN32 |
|
|
|
|
SYSTEM_INFO sysinfo; |
|
|
|
|
#if (defined(_M_ARM) || defined(_M_ARM64) || defined(_M_X64) || defined(WINRT)) && _WIN32_WINNT >= 0x501 |
|
|
|
@ -788,13 +867,37 @@ int cv::getNumberOfCPUs(void) |
|
|
|
|
#else |
|
|
|
|
GetSystemInfo( &sysinfo ); |
|
|
|
|
#endif |
|
|
|
|
unsigned ncpus_sysinfo = sysinfo.dwNumberOfProcessors < 0 ? 1 : sysinfo.dwNumberOfProcessors; /* Just a fail safe */ |
|
|
|
|
ncpus = minNonZero(ncpus, ncpus_sysinfo); |
|
|
|
|
|
|
|
|
|
#elif defined CV_CPU_GROUPS_1 |
|
|
|
|
|
|
|
|
|
#if defined CV_HAVE_CGROUPS |
|
|
|
|
static unsigned ncpus_impl_cpuset = (unsigned)getNumberOfCPUsImpl("/sys/fs/cgroup/cpuset/cpuset.cpus"); |
|
|
|
|
ncpus = minNonZero(ncpus, ncpus_impl_cpuset); |
|
|
|
|
|
|
|
|
|
static unsigned ncpus_impl_cfs = getNumberOfCPUsCFS(); |
|
|
|
|
ncpus = minNonZero(ncpus, ncpus_impl_cfs); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
static unsigned ncpus_impl_devices = (unsigned)getNumberOfCPUsImpl("/sys/devices/system/cpu/online"); |
|
|
|
|
ncpus = minNonZero(ncpus, ncpus_impl_devices); |
|
|
|
|
|
|
|
|
|
#if defined _GNU_SOURCE \ |
|
|
|
|
&& !defined(__ANDROID__) // TODO: add check for modern Android NDK
|
|
|
|
|
|
|
|
|
|
cpu_set_t cpu_set; |
|
|
|
|
if (0 == sched_getaffinity(0, sizeof(cpu_set), &cpu_set)) |
|
|
|
|
{ |
|
|
|
|
unsigned cpu_count_cpu_set = CPU_COUNT(&cpu_set); |
|
|
|
|
ncpus = minNonZero(ncpus, cpu_count_cpu_set); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
static unsigned cpu_count_sysconf = (unsigned)sysconf( _SC_NPROCESSORS_ONLN ); |
|
|
|
|
ncpus = minNonZero(ncpus, cpu_count_sysconf); |
|
|
|
|
|
|
|
|
|
return (int)sysinfo.dwNumberOfProcessors; |
|
|
|
|
#elif defined __ANDROID__ |
|
|
|
|
static int ncpus = getNumberOfCPUsImpl(); |
|
|
|
|
return ncpus; |
|
|
|
|
#elif defined __linux__ || defined __GLIBC__ || defined __HAIKU__ || defined __EMSCRIPTEN__ |
|
|
|
|
return (int)sysconf( _SC_NPROCESSORS_ONLN ); |
|
|
|
|
#elif defined __APPLE__ |
|
|
|
|
int numCPU=0; |
|
|
|
|
int mib[4]; |
|
|
|
@ -816,10 +919,9 @@ int cv::getNumberOfCPUs(void) |
|
|
|
|
numCPU = 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return (int)numCPU; |
|
|
|
|
#else |
|
|
|
|
return 1; |
|
|
|
|
ncpus = minNonZero(ncpus, (unsigned)numCPU); |
|
|
|
|
#endif |
|
|
|
|
return ncpus != 0 ? ncpus : 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const char* cv::currentParallelFramework() { |
|
|
|
|