3

Working with threads in Qt5, how can I set a single thread's CPU affinity?

I want to specify a mask of available CPU cores that the thread may run under.

In other words, what is the Qt5 equivalent to Posix thread's pthread_setaffinity_np() ?

Can I do this for threads managed by QThreadPool?

Mr. Developerdude
  • 9,118
  • 10
  • 57
  • 95

2 Answers2

3

Qt doesn't provide any public APIs for setting processor affinity. There's definitely no way to do this for a QThreadPool, which doesn't even provide an API for accessing the QThreads within the pool.

For explicitly-created QThread objects, you could try using the QThread::getCurrentThreadId() function to return a native "handle" to the thread, and then pass that to your system's thread-management library calls. But I would strongly recommend against this. The docs explicitly state:

Warning: The handle returned by this function is used for internal purposes and should not be used in any application code.

If you're building for a specific platform, you might be able to mix calls to your OS's library (e.g., pthreads), but that will not be portable and I have no idea if it will work.

Your best bet is probably to manage the CPU affinity of the whole application from the command-line. If you're on Linux, taskset is the way to go. For Windows, take a look at this SO answer. Unfortunately, Apple seems pretty determined to prevent users from setting thread affinity, at least from the command line.

bnaecker
  • 6,152
  • 1
  • 20
  • 33
  • I don't know anything about Mac OS/X except that I remember they based on BSD ([SO: How closely are Mac OS X and BSD related?](https://stackoverflow.com/q/3446231/7478597)). Out of curiosity, I googled and found this: [SU: How to set processor affinity on OS X?](https://superuser.com/a/770772). – Scheff's Cat Dec 06 '17 at 10:21
  • @Scheff Yeah, I'm aware of the thread affinity API. But most of the Mach threading code is *really* poorly documented. I've mostly had to dig around in system headers to figure out how to use any of it, which is...annoying. – bnaecker Dec 06 '17 at 22:01
3

Usually that sort of things is done by extracting the native thread handle and then doing whatever system specific stuff necessary, as no accepted cross-platform API exists for low level thread management.

Indeed, if we inspect the source for the qthread_unix.cpp we will see the following:

Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
{
    // requires a C cast here otherwise we run into trouble on AIX
    return to_HANDLE(pthread_self());
}

And in qthread_win.cpp the implementation will differ in the expected way:

Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
{
    return reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId()));
}

So, it is responsibility of the application code to do the proper low level actions pertaining to each platform it is expected to run on.

oakad
  • 6,945
  • 1
  • 22
  • 31