Qt application core affinity
-
wrote on 14 Sept 2023, 10:25 last edited by romain.donze
I’m using Boot2Qt on an apalis iMX8QP board. As the iMX8QP contains 4 Cortex A53 cores as well as a Cortex A73 core, I’d like to force the main thread of my Qt application to be executed only on the A73 core in order to gain in performance. So, at the start of my main(), I execute this function:
cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(coreNo, &mask); if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { qCritical()<<"Error while executing sched_setaffinity to set affinity"; assert(false); }
The application is then executed on Core A73, but then all the different threads, whether created manually with QThread or automatically with QtConcurrent for example, are also executed on Core A73 and are not distributed between the other A53 cores. i understand that i could reuse sched_setaffinity at the start of each execution of other threads, but that’s not the point. so is there any way of forcing the main thread to run on a particular core without neglecting the use of the other cores by the subsequently created threads?
-
I’m using Boot2Qt on an apalis iMX8QP board. As the iMX8QP contains 4 Cortex A53 cores as well as a Cortex A73 core, I’d like to force the main thread of my Qt application to be executed only on the A73 core in order to gain in performance. So, at the start of my main(), I execute this function:
cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(coreNo, &mask); if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { qCritical()<<"Error while executing sched_setaffinity to set affinity"; assert(false); }
The application is then executed on Core A73, but then all the different threads, whether created manually with QThread or automatically with QtConcurrent for example, are also executed on Core A73 and are not distributed between the other A53 cores. i understand that i could reuse sched_setaffinity at the start of each execution of other threads, but that’s not the point. so is there any way of forcing the main thread to run on a particular core without neglecting the use of the other cores by the subsequently created threads?
wrote on 15 Sept 2023, 03:15 last edited bysched_setaffinity(2) says:
A child created via fork(2) inherits its parent's CPU affinity mask.
pthread_create(3) has a similar statement.
The choices appear to be explicitly setting the CPU affinity of each thread created, or to spawn addition threads from a thread that has previously had its affinity mask set.
clone(2), with lots of flags for other things, makes no mention of the topic.
-
sched_setaffinity(2) says:
A child created via fork(2) inherits its parent's CPU affinity mask.
pthread_create(3) has a similar statement.
The choices appear to be explicitly setting the CPU affinity of each thread created, or to spawn addition threads from a thread that has previously had its affinity mask set.
clone(2), with lots of flags for other things, makes no mention of the topic.
wrote on 15 Sept 2023, 06:14 last edited by romain.donzeHi @jeremy_k thank you for your answer. Correct me if I am wrong but how can I manage affinity of the threads in QThreadPool::globalInstance()? as the affinity seems to be reset after a short time of innactivity. So is there a way to monitor all the QThreads in QThreadPool so maybe I can connect to QThread::started to call a slot that set the affinity once and not every time I call QtConcurrent::run() ?
For now I am doing something like that at the beginning of my code:
for(int i=0; i<QThreadPool::globalInstance()->maxThreadCount(); i++) { QThreadPool::globalInstance()->start([]() { QObject::connect(QThread::currentThread(), &QThread::started, []() { resetCoreAffinity(); }); }); }
-
Hi @jeremy_k thank you for your answer. Correct me if I am wrong but how can I manage affinity of the threads in QThreadPool::globalInstance()? as the affinity seems to be reset after a short time of innactivity. So is there a way to monitor all the QThreads in QThreadPool so maybe I can connect to QThread::started to call a slot that set the affinity once and not every time I call QtConcurrent::run() ?
For now I am doing something like that at the beginning of my code:
for(int i=0; i<QThreadPool::globalInstance()->maxThreadCount(); i++) { QThreadPool::globalInstance()->start([]() { QObject::connect(QThread::currentThread(), &QThread::started, []() { resetCoreAffinity(); }); }); }
wrote on 15 Sept 2023, 18:43 last edited by@romain-donze said in Qt application core affinity:
Hi @jeremy_k thank you for your answer. Correct me if I am wrong but how can I manage affinity of the threads in QThreadPool::globalInstance()?
That may make it tough. Thread pool threads appear to be started from the thread that caused it to be created, ie the thread in which QThreadPool::tryStart() was invoked when a new thread is required. If the application only queues new jobs from a thread with the desired affinity, that should work.
as the affinity seems to be reset after a short time of innactivity.
Threads don't reset their affinity. They terminate if QThreadPool::expiryTimeout elapses between jobs. Setting it to a negative value prevents timeout termination.
For now I am doing something like that at the beginning of my code:
for(int i=0; i<QThreadPool::globalInstance()->maxThreadCount(); i++) { QThreadPool::globalInstance()->start([]() { QObject::connect(QThread::currentThread(), &QThread::started, []() { [...]
I don't think this will work.
- QThreadPoolThread defines its own override for QThread::run(), which doesn't appear to emit QThread::started()
- Even if QThread::started is emitted, the thread is already running by the time connect is called.
- There is no guarantee that each job will be assigned to a different thread.
1/4