Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multithreading performance of QtConcurrent Vs QThread with many threads

Suppose your application needs to run a function in multiple threads the number of which is more than the number of CPU cores/threads. One way is to use QtConcurrent and setting the maximum thread count :

MyClass *obj = new MyClass;

QThreadPool::globalInstance()->setMaxThreadCount(30);

for(int i=0;i<30;i++)
    QtConcurrent::run(obj, &MyClass::someFunction);

Another way is to have multiple objects and move them to different threads using moveToThread :

for(int i=0;i<30;i++)
{
        MyClass *obj = new MyClass;
        QThread *th = new QThread();
        obj->moveToThread(th);
        connect(th, SIGNAL(started()), obj, SLOT(someFunction()) );
        connect(obj, SIGNAL(workFinished()), th, SLOT(quit()) );
        connect(th, SIGNAL(finished()), obj, SLOT(deleteLater()) );
        connect(th, SIGNAL(finished()), th, SLOT(deleteLater()) );

        th->start();
}

As the number of threads are more than the number of CPU cores, the threads should be switched between different cores when running.

The question is whether the two approaches have different performances or not? i.e does switching of a QThread differ from one that is run using QtConcurrent::run ?

like image 214
Nejat Avatar asked Jun 06 '15 07:06

Nejat


People also ask

Is QT multithreaded?

Qt offers many classes and functions for working with threads. Below are four different approaches that Qt programmers can use to implement multithreaded applications.

How do you use Qt multithreading?

Some below steps will be used to create thread in Qt: To create a new thread executing some code, subclass QThread and reimplement run() method. Then, create an instance of the subclass and call start() . Threads have priorities that we can specify as an optional parameter to start() , or change with setPriority() .

What is thread in Qt?

A QThread object manages one thread of control within the program. QThreads begin executing in run(). By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread. You can use worker objects by moving them to the thread using QObject::moveToThread().


2 Answers

I agree with first answer, but I want to add something.

QThread is low-level class which just run OS-specific functions. What is the QtConcurrent? The answer is in Qt source code.

First level: run

QFuture<T> run(T (*functionPointer)())  
{
        return (new StoredFunctorCall0<T, T (*)()>(functionPointer))->start();
}

Second:

struct StoredFunctorCall0: public RunFunctionTask<T>    { ...

Third:

template <typename T>
class RunFunctionTaskBase : public QFutureInterface<T> , public QRunnable
{ ...

Now about QRunnable. When we start QRunnable with QThreadPool we do:

start() which calls tryStart() which calls startThread() which operate with QThreadPoolThread (and it is a QThread subclass) and it is finally call start() of QThread.

And of course this chain is not full, long road, isn't it? So as I know, when we use abstraction, we have abstraction penalty (QtConcurrent has bigger penalty then QThread), but final result is same, it is QThread.

like image 86
Kosovan Avatar answered Sep 16 '22 20:09

Kosovan


Short answer: it depends on the nature/logic of the workload.

QtConcurrent runs a pool of threads and it is a higher level API not well-suited to run a large number of blocking operations: if you do a lot of blocking operations you will soon end up draining the pool and having other requests queued. In that case QThread (a lower level construct) is probably better suited for the operation (each one represents a single thread).

like image 21
Marco A. Avatar answered Sep 17 '22 20:09

Marco A.