2011-05-13 127 views
7

我已经在多线程版本中实现了PageRank的一个版本。我在4核Q6600上运行它。当我运行它设置为创建4个线程,我得到:为什么有更多的线程比核心更快?

real 6.968s 
user 26.020s 
sys  0.050s 

当我和128个线程运行我得到:

real 0.545s 
user 1.330s 
sys  0.040s 

这是没有意义的我。基本算法是sum-reduce:

  1. 所有线程总和输入的一个子集;
  2. 同步;
  3. 然后每个线程累积来自其他线程的部分结果;
  4. 主线程将所有线程的中间值相加,然后确定是否继续。

分析没有帮助。我不确定哪些数据有助于理解我的代码 - 请只问。

真的让我感到困惑。

+0

这种情况下的输入是什么?有什么IO限制?你有没有测量每个单独的步骤? – 2011-05-13 06:02:02

+0

是否有可能有更多的线程,每个线程都得到足够小的块来在一个时间片内完成?有些调度系统会在第一个切片中为线程留出一点额外时间。如果它没有及时完成,它就会被安排并参与正常切片。如果工作被分解到真正简单的级别,那么您可以通过为应用程序获取更多切片并盗取其他进程来“游戏系统”。你也可以尝试以更高的优先级运行,看看你是否得到类似的结果。 – 2011-05-13 14:52:13

+0

输入全部在开始时读入,所以没有IO界限。我重写了多线程代码的很大一部分,并删除了一个错误共享的实例。虚假分享修复会稍微提高速度。 – laurencer 2011-05-14 09:39:19

回答

10

有意创建比处理器更多的线程是一种标准技术,用于利用线程被阻塞等待某些事情的“备用周期”,无论是I/O,互斥锁还是其他通过提供其他有用工作的东西为处理器做。

如果你的线程正在进行I/O操作,那么这是加速的强有力竞争者:当每个线程阻塞等待I/O时,处理器可以运行其他线程,直到它们也阻塞I/O ,希望第一个线程的数据已准备好,等等。

加速的另一个可能的原因是您的线程正在经历虚假分享。如果您有两个线程将数据写入同一高速缓存行上的不同值(例如,数组中的相邻元素),则会在高速缓存行来回传输时阻塞CPU。通过添加更多的线程,您可以降低它们在相邻元素上运行的可能性,从而减少错误共享的可能性。您可以通过向数据元素添加额外填充来轻松测试这些数据元素,因此它们的大小至少为64个字节(典型的高速缓存行大小)。如果你的4线程代码加速,这就是问题所在。

+3

关于虚假分享的猜测是非常好的。但考虑到运行时间的巨大差异,我宁愿怀疑工作分区逻辑中的竞争条件错误,以便带有许多线程的版本“忘记”某些工作,并且不会像其他工作那么多。 – Ringding 2011-05-13 12:12:24

6

您可能有空闲的CPU周期,而线程会阻塞某些资源(如内存)。这些CPU周期可以被其他线程使用。我会看到的数据是... 4个线程版本是否显示每个内核的100%利用率?如果不是,你已经找到了你的备用CPU周期。

相关问题