QThread::idealThreadCount: use the thread affinity set
Instead of returning the total number of logical processors in the system, which we may not be allowed to wholly run on, use the affinity set that the calling thread is allowed to use. Implemented for Linux and FreeBSD only, with up to 4x the number of processors than CPU_SETSIZE has as default (that would be 4096 logical processors on Linux, 1024 on FreeBSD). Implementation for Windows is possible, but the API there is always limited to 64, so I'm unsure if it is correct. Darwin (macOS) does not have this capability. Testing: $ ./tst_qthread idealThreadCount | grep QDEBUG QDEBUG : tst_QThread::idealThreadCount() Ideal thread count: 8 $ taskset 3 ./tst_qthread idealThreadCount | grep QDEBUG QDEBUG : tst_QThread::idealThreadCount() Ideal thread count: 2 [ChangeLog][QtCore][QThread] idealThreadCount() will now return the number of logical processors that the current process (thread) has assigned in its affinity set, instead of the total number of processors in the system. These two numbers can be different if the process is launched by the parent with a different affinity set, with tools like Linux's taskset(1) or schedtool(1). This is currently implemented for Linux and FreeBSD. Change-Id: I2cffe62afda945079b63fffd16bd086f64f5f314 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
c54fb03446
commit
19d231e47d
@ -314,9 +314,20 @@ QThreadPrivate::~QThreadPrivate()
|
||||
/*!
|
||||
\fn int QThread::idealThreadCount()
|
||||
|
||||
Returns the ideal number of threads that can be run on the system. This is done querying
|
||||
the number of processor cores, both real and logical, in the system. This function returns 1
|
||||
if the number of processor cores could not be detected.
|
||||
Returns the ideal number of threads that this process can run in parallel.
|
||||
This is done by querying the number of logical processors available to this
|
||||
process (if supported by this OS) or the total number of logical processors
|
||||
in the system. This function returns 1 if neither value could be
|
||||
determined.
|
||||
|
||||
\note On operating systems that support setting a thread's affinity to a
|
||||
subset of all logical processors, the value returned by this function may
|
||||
change between threads and over time.
|
||||
|
||||
\note On operating systems that support CPU hotplugging and hot-unplugging,
|
||||
the value returned by this function may also change over time (and note
|
||||
that CPUs can be turned on and off by software, without a physical,
|
||||
hardware change).
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
@ -70,8 +70,10 @@
|
||||
#include <sched.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef Q_OS_BSD4
|
||||
#include <sys/sysctl.h>
|
||||
#if defined(Q_OS_FREEBSD)
|
||||
# include <sys/cpuset.h>
|
||||
#elif defined(Q_OS_BSD4)
|
||||
# include <sys/sysctl.h>
|
||||
#endif
|
||||
#ifdef Q_OS_VXWORKS
|
||||
# if (_WRS_VXWORKS_MAJOR > 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR >= 6))
|
||||
@ -455,8 +457,31 @@ int QThread::idealThreadCount() noexcept
|
||||
} else {
|
||||
cores = (int)psd.psd_proc_cnt;
|
||||
}
|
||||
#elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
|
||||
# ifdef Q_OS_FREEBSD
|
||||
# define CPU_COUNT_S(setsize, cpusetp) ((int)BIT_COUNT(setsize, cpusetp))
|
||||
// match the Linux API for simplicity
|
||||
using cpu_set_t = cpuset_t;
|
||||
auto sched_getaffinity = [](pid_t, size_t cpusetsize, cpu_set_t *mask) {
|
||||
return cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, cpusetsize, mask);
|
||||
};
|
||||
# endif
|
||||
|
||||
// get the number of threads we're assigned, not the total in the system
|
||||
QVarLengthArray<cpu_set_t, 1> cpuset(1);
|
||||
int size = 1;
|
||||
if (Q_UNLIKELY(sched_getaffinity(0, sizeof(cpu_set_t), cpuset.data()) < 0)) {
|
||||
for (size = 2; size <= 4; size *= 2) {
|
||||
cpuset.resize(size);
|
||||
if (sched_getaffinity(0, sizeof(cpu_set_t) * size, cpuset.data()) == 0)
|
||||
break;
|
||||
}
|
||||
if (size > 4)
|
||||
return 1;
|
||||
}
|
||||
cores = CPU_COUNT_S(sizeof(cpu_set_t) * size, cpuset.data());
|
||||
#elif defined(Q_OS_BSD4)
|
||||
// FreeBSD, OpenBSD, NetBSD, BSD/OS, OS X, iOS
|
||||
// OpenBSD, NetBSD, BSD/OS, Darwin (macOS, iOS, etc.)
|
||||
size_t len = sizeof(cores);
|
||||
int mib[2];
|
||||
mib[0] = CTL_HW;
|
||||
@ -494,7 +519,7 @@ int QThread::idealThreadCount() noexcept
|
||||
#elif defined(Q_OS_WASM)
|
||||
cores = QThreadPrivate::idealThreadCount;
|
||||
#else
|
||||
// the rest: Linux, Solaris, AIX, Tru64
|
||||
// the rest: Solaris, AIX, Tru64
|
||||
cores = (int)sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (cores == -1)
|
||||
return 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user