Skip to content
Advertisement

QThreads using MinGw doesn’t work properly under windows

I’m developing a large optimzation tool using Qt. For a better CPU usage I use QThreads. Then I move worker objects (derived from QObject, containing non QObject data members) into the threads. Everything looks fine, builds fine and runs smoothly on Linux using GCC and Qt 4.8

However using MinGw using Qt 5.5 under Windows, the calculation took much longer. It seems like the threads are blocking somewhere in the calculation and are serialized. I displayed some debug messages to ensure that the threads are working correctly. It seems like there is a bottelneck that exists on Windows but not under Linux. I don’t think that the Qt Version makes a difference, I’d rather think the problem is caused by MinGw. The OS are Windows 7 and Debian. I use the compiled MinGw binaries of Qt5.

Is there any further configuration for MinGw’s Qt build necessary? Or is there a problem using non QObject members, when moving worker objects into threads? Could this be a problem with the different thread types, QThread uses internally? Thank you in advance 🙂

EDIT:

The starting ob the threads looks like this.

for (int i = 0; i < this->numberOfCores; i++)
    {
        QThread *thread = new QThread(this);
        thread->setObjectName("Thread " + QString::number(i));
        Calculator *calculator = new Calculator(/* Skip parameters */);

        calculator->moveToThread(thread);
        connect(calculator, SIGNAL(debugInfo(DebugData)), this, SIGNAL(debugInfo(DebugData)));
        connect(this, SIGNAL(startCalculator()),
                calculator, SLOT(startCalculation()));
        connect(calculator, SIGNAL(solutionFound(Solution*)),
                this, SLOT(addSolution(Solution*)));
        connect(calculator, SIGNAL(calculationFinished()), this, SLOT(calculatorFinished()));

        thread->start(QThread::HighestPriority);

I used this approach multiple times and it always worked.

The Calculator then just calculates the solution. Each calclator has its own data und there cannot be a race condition. They all work on completly different data.

Advertisement

Answer

On each signal emission, the high priority threads will be synchronizing with the lower priority thread that receives the cross-thread slot calls. That’s probably the source of platform differences: different kernels address temporary priority boosts differently, and on top of that on Linux the event loops are from glib, on Windows they are not. They will behave differently when it comes to synchronization across threads of differing priorities. If the receiving thread spends a lot of time in the event loop actively dispatching events, it can wreak havoc on high priority threads.

Perhaps counter-intuitively, the solution might be as simple as not making the computation threads high priority.

Anyway, your users will hate you for depriving them of interactive performance for some calculations that should be running in the background. The computation threads will preempt default priority GUI threads, the system will feel very sluggish to an interactive user, and that applies to your own UI too! The calculation threads should be of a lower priority instead. This of course assumes that the computations aren’t used to drive interaction (e.g. physics engine in a game); if they do, and you think the application deserves it, you must raise the priority of the entire process.

Advertisement