Thread priority is "Odd"?
-
wrote on 15 Aug 2014, 15:09 last edited by
I am running a simple console app with four identical threads......C / D / E / F.
OS is Win7/64 Qt is 5.3.
I have set thread C to be "TimeCriticalPriority", and thread F to be "IdlePriority".
Is there any reason why F should be the fastest thread, and C the slowest?
Probably me doing something daft........but it smells buggy,
I have run the threads starting C,D,E,F and F,E,D,C as order of start, and made sure that the CPU is loaded enough to actually have to think about scheduling.....(that was my first discovery.......if the CPU is bored, then all threads run at the same speed).
Any gurus out there?
-
wrote on 15 Aug 2014, 15:35 last edited by
Hi,
Fist of all, what CPU do you have? Multicore CPU's handle threading in a very different way then single core CPU's. What do you want to achieve with this test? Your OS will do the scheduling and it's up to that system to run the threads. Causing a very busy CPU may not influence the other threads in other cores etc. MAybe show how you create the threads to verify it they work at all as you expect. Do you really see different threads in your debugger? -
wrote on 15 Aug 2014, 15:50 last edited by
Hi, thanks for getting interested. CPU is Intel i7,
All the threads do is count upwards using a (x=0;X<number;X++) loop, with an added (y=0,y<largenumber;y++) loop within the loop.
All four threads run the same, and just qDebug the threadname, and value of x, on each pass. I have QMutex locked the actual qDebug statement, as I was getting half complete output lines.
This is "main"
@#include <QCoreApplication>
#include <QThread>
#include<QMutex>
#include "myobject.h"int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);QThread cThread; QThread dThread; QThread eThread; QThread fThread; MyObject cObject; MyObject dObject; MyObject eObject; MyObject fObject; cObject.DoSetup(cThread); cObject.name = "CThread"; dObject.DoSetup(dThread); dObject.name = "DThread"; eObject.DoSetup(eThread); eObject.name = "EThread"; fObject.DoSetup(fThread); fObject.name = "FThread"; cObject.moveToThread(&cThread); dObject.moveToThread(&dThread); eObject.moveToThread(&eThread); fObject.moveToThread(&fThread); fThread.start(QThread::IdlePriority); eThread.start(); dThread.start(); cThread.start(QThread::TimeCriticalPriority); return a.exec();
}@
and myobject.h
@#ifndef MYOBJECT_H
#define MYOBJECT_H#include <QObject>
#include <QDebug>
#include <QThread>
#include <QMutex>class MyObject : public QObject
{
Q_OBJECT
public:
explicit MyObject(QObject *parent = 0);
void DoSetup(QThread &cThread);
QString name;signals:
public slots:
void DoWork();};@
and finally myobject.cpp
@#include "myobject.h"
QMutex mutex;
MyObject::MyObject(QObject *parent) :
QObject(parent)
{
}void MyObject::DoSetup(QThread &zThread)
{
connect(&zThread, SIGNAL(started()),this,SLOT (DoWork()));
}void MyObject::DoWork()
{for(int i = 0; i<100000 ; i++) { for(int h=0; h<100000000;h++) { //small delay } mutex.lock(); qDebug() << this->name << i; mutex.unlock(); }
}@
I am still fairly new to Qt, and threaded apps......so was really just exploring.
If I am being daft......I'd appreciate a pointer.
The code is actually a variant of a previously followed tutorial.
-
wrote on 15 Aug 2014, 15:51 last edited by
When running, the debugger shows 6 thread ids. Sorry, forgot to add that bit.
-
wrote on 18 Aug 2014, 08:20 last edited by
So, when using an i7 you probably have 4 cores. So your OS will determine where en when your threads will be run. Some very busy programs often only use a single core. Then the RAM working memory limitations kick in and that becomes the bottleneck. So debugging your threads is very tricky to say which one will finish first. If you really need to find out, you should switch to a single core CPU. Setting the priority will effect the speed that the threads are finished, that is for sure.
Maybe read this doc: "Threading basics":http://qt-project.org/doc/qt-4.8/thread-basics.html
and the QtConcurrent class to add to that. The QtConcurrent is a bit more high level and is much easier to use! The QThread has some tricky memory allocation issues. -
wrote on 18 Aug 2014, 08:27 last edited by
Loading the CPU a little drives up activity across all the cores, and whilst I appreciate that the threads will be handled by the OS, I would still expect the thread marked as "critical priority" to at least complete no slower than the one marked as "idle time priority". The fact that the highest priority thread runs consistently slower than the others, and the low priority thread runs fastest of all just seems "wrong" to me, hence my original question. :-) I will have a look at QtConcurrent too though, thanks for that!
-
wrote on 18 Aug 2014, 10:09 last edited by
Ah, so setting the priority doesn't result in expected behavior. I understand that that is very fishy, must give you that.
But then again, to be simple. Every threads gets a time slot of the OS in the CPU core. So only when the core is maxed out (load is 100% for all cores) there might be a difference in number of thread scheduled for operation per time sequence, but the lowest priority will still be scheduled ones a while. It's up to the OS to handle the requested priorities. In your case Windows? No idea how the threads are scheduled in that OS.
What does the debug data tell you? Is the the gap between output values increasing between the differently set priority threads? -
wrote on 18 Aug 2014, 12:45 last edited by
I ran a quick control (runs at about 50% CPU loading).
The critical thread was faster than the unprioritised ones this time, but still slower than the idle time priority one.....which should in theory have been the slowest of all? Not much in it.......C thread 10017
D thread 10009
E thread 10010
F thread 10034Something is just fishy......haha.......of well, I shall "blame" Windows for now, although I might just run it on one of my Linux machines, to see if it is wildly different
-
wrote on 18 Aug 2014, 14:20 last edited by
Hi, The only 'real' way of finding out is to use a single core CPU machine and then generate so much threads as you can possibly create in your program and check out if number e.g. 100 and 104 thread get finished.
You could also increase the numbers counted to extend the thread. With the mutex you also block processes (as you should to protect thread races etc) from running.
Maybe it's better to all add a signal to the threads, make a single slot in the MainWindow and only display the numbers in that MainWindow class. Then on the background the thread keep on running and keep on sending events (signals) but the threads themselves are not connected via mutex etc.
1/9