QtConcurrent 与具有多个线程的 QThread 的多线程性能
Multithreading performance of QtConcurrent Vs QThread with many threads
假设您的应用程序需要 运行 多线程中的一个函数,其数量多于 CPU cores/threads 的数量。一种方法是使用 QtConcurrent
并设置最大线程数:
MyClass *obj = new MyClass;
QThreadPool::globalInstance()->setMaxThreadCount(30);
for(int i=0;i<30;i++)
QtConcurrent::run(obj, &MyClass::someFunction);
另一种方法是拥有多个对象并使用 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();
}
由于线程数多于CPU核数,运行ning时需要在不同核之间切换线程。
问题是这两种方法是否有不同的表现?即 QThread
的切换是否不同于 运行 使用 QtConcurrent::run
的切换?
简答:这取决于工作量的nature/logic。
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(较低级别的构造)可能更适合该操作(每个代表一个线程)。
我同意第一个答案,但我想补充一点。
QThread
是低级 class,它只是 运行 OS 特定的功能。 QtConcurrent
是什么?答案在 Qt
源代码中。
一级:run
QFuture<T> run(T (*functionPointer)())
{
return (new StoredFunctorCall0<T, T (*)()>(functionPointer))->start();
}
struct StoredFunctorCall0: public RunFunctionTask<T> { ...
template <typename T>
class RunFunctionTaskBase : public QFutureInterface<T> , public QRunnable
{ ...
现在大约 QRunnable
。当我们以 QThreadPool
开始 QRunnable
时,我们做:
start() which calls tryStart()
which calls startThread()
which operate with QThreadPoolThread
(and it is a QThread subclass) 最后调用 QThread
的 start()
。
当然这条链还没有满,路很长,不是吗?所以据我所知,当我们使用抽象时,我们有抽象惩罚(QtConcurrent
比 QThread
有更大的惩罚),但最终结果是相同的,它是 QThread
.
假设您的应用程序需要 运行 多线程中的一个函数,其数量多于 CPU cores/threads 的数量。一种方法是使用 QtConcurrent
并设置最大线程数:
MyClass *obj = new MyClass;
QThreadPool::globalInstance()->setMaxThreadCount(30);
for(int i=0;i<30;i++)
QtConcurrent::run(obj, &MyClass::someFunction);
另一种方法是拥有多个对象并使用 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();
}
由于线程数多于CPU核数,运行ning时需要在不同核之间切换线程。
问题是这两种方法是否有不同的表现?即 QThread
的切换是否不同于 运行 使用 QtConcurrent::run
的切换?
简答:这取决于工作量的nature/logic。
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(较低级别的构造)可能更适合该操作(每个代表一个线程)。
我同意第一个答案,但我想补充一点。
QThread
是低级 class,它只是 运行 OS 特定的功能。 QtConcurrent
是什么?答案在 Qt
源代码中。
一级:run
QFuture<T> run(T (*functionPointer)())
{
return (new StoredFunctorCall0<T, T (*)()>(functionPointer))->start();
}
struct StoredFunctorCall0: public RunFunctionTask<T> { ...
template <typename T>
class RunFunctionTaskBase : public QFutureInterface<T> , public QRunnable
{ ...
现在大约 QRunnable
。当我们以 QThreadPool
开始 QRunnable
时,我们做:
start() which calls tryStart()
which calls startThread()
which operate with QThreadPoolThread
(and it is a QThread subclass) 最后调用 QThread
的 start()
。
当然这条链还没有满,路很长,不是吗?所以据我所知,当我们使用抽象时,我们有抽象惩罚(QtConcurrent
比 QThread
有更大的惩罚),但最终结果是相同的,它是 QThread
.