CPU核心未使用QThreads正确使用

时间:2012-03-26 13:06:08

标签: c++ multithreading qt qthread

使用:C++ (MinGW)Qt4.7.4Vista (OS)intel core2vPro

我需要以完全相同的方式处理2个大文件。所以我想从2个单独的线程中为2个单独的文件调用处理例程。 GUI线程没有什么重要的;只显示一个标签并运行一个事件循环来检查线程终止条件的发射并相应地退出主应用程序。我预计这会同样地利用两个核心(intel core2),但相反,我从任务管理器看到其中一个核心被高度利用而另一个核心没有(尽管不是每次我都运行代码);处理2个文件所花费的时间远远超过处理一个文件所花费的时间(我认为它应该相等或稍微多一点,但这几乎等于在非线程中一个接一个地处理2个文件应用)。我可以以某种方式强制线程使用我指定的核心吗?

QThread* ptrThread1=new QThread;
QThread* ptrThread2=new QThread;
ProcessTimeConsuming* ptrPTC1=new ProcessTimeConsuming();
ProcessTimeConsuming* ptrPTC2=new ProcessTimeConsuming();

ptrPTC1->moveToThread(ptrThread1);
ptrPTC2->moveToThread(ptrThread2);

//make connections to specify what to do when processing ends, threads terminate etc
//display some label to give an idea that the code is in execution

ptrThread1->start();
ptrThread2->start(); //i want this thread to be executed in the core other than the one used above

ptrQApplication->exec(); //GUI event loop for label display and signal-slot monitoring

3 个答案:

答案 0 :(得分:16)

通常从单个机械磁盘并行读取(可能在您的情况下)并不会产生任何性能提升,因为磁盘的机械磁头需要每次都旋转以寻找下一个读取位置,从而有效地进行读取顺序。更糟糕的是,如果许多线程试图读取,性能甚至可能会因顺序版本而降低,因为磁盘头被反弹到磁盘的不同位置,因此需要每次都停止旋转。< / p>

通常,你不能比按顺序读取文件然后使用生产者 - 消费者模型并行处理它们做得更好。

答案 1 :(得分:2)

使用机械硬盘驱动器,您需要明确控制执行顺序读取所花费的时间与搜索时间的比率。这样做的规范方法是在m+min(n, QThread::idealThreadCount())个线程上运行 n + m 个对象。这里, m 是文件所在的硬盘数量, n 是文件数。

  • 每个 m 对象都是以循环方式从给定的硬盘驱动器中读取文件。每次读取必须足够大。在现代硬盘驱动器上,让我们预算70Mbytes / s的带宽(您可以对实际值进行基准测试),5ms用于搜索。要浪费最多10%的带宽,你只需要100ms或100ms /(5ms / seek)=每秒20次搜索。因此,在从下一个文件读取之前,必须从每个文件中读取至少70Mbytes /(20seeks + 1)= 3.3兆字节。该线程用文件数据填充缓冲区,然后缓冲区发信号通知附加到缓冲区另一侧的相关计算对象。当缓冲区忙时,您只需跳过从给定文件中读取的内容,直到缓冲区再次可用。

  • 其他 n 对象是计算对象,它们根据来自缓冲区的信号执行计算,指示缓冲区已满。一旦不再需要缓冲区数据,缓冲区就会“重置”,以便文件阅读器可以重新填充它。

所有读者对象都需要自己的线程。计算对象可以以循环方式在它们自己的线程中分布,这样线程都可以在+1,-0对象之内。

答案 2 :(得分:1)

我认为我的经验数据可能会对此讨论有所帮助。我有一个目录,包含980个txt文件,我想阅读。在Qt / C ++框架中并运行在Intel i5四核上,我创建了一个GUI应用程序并添加了一个类工作者来读取给定其路径的文件。我将工作者推入一个线程,然后每次运行时重复添加一个额外的线程。我用1个线程大约13分钟,用2分钟9分钟,用3分钟8分钟。因此,在我的情况下有一些好处,但它很快就退化了。