【问题标题】:Why is Having More Threads than Cores Faster?为什么线程数比内核数更快?
【发布时间】:2011-05-13 04:54:57
【问题描述】:

我已经在多线程版本中实现了一个 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. 主线程对所有线程的中间值求和,然后决定是否继续。

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

真的让我很困惑。

【问题讨论】:

  • 这种情况下的输入是什么? IO绑定的东西?您是否对每个单独的步骤进行了测量?
  • 是否有可能在有更多线程的情况下,每个线程获得足够小的块以在一个时间片内完成?一些调度系统在线程的第一个切片中提供了一些额外的时间。如果它没有及时完成,它会被安排并参与正常的切片。如果工作被分解为非常简单的级别,您可能会通过为您的应用程序获取更多切片并抢劫其他进程来“玩弄系统”。您也可以尝试以更高的优先级运行,看看是否会得到类似的结果。
  • 输入都是一开始就读入的,所以不受IO限制。我重写了大部分多线程代码并删除了一个错误共享的实例。错误共享修复略微提高了速度。
  • 我确实优化了内存使用 4GB -> 600MB,这使得 4 和 128 线程之间的差异可以忽略不计。我能想到的唯一解释是,我受到内存带宽的限制,并且每个内核都在相当随机地访问一个巨大的范围(因此没有用于缓存的空间局部性),而线程越多,每个线程都有相当多的空间局部性。

标签: multithreading performance pthreads


【解决方案1】:

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

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

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

【讨论】:

  • 关于虚假分享的猜测非常好。但考虑到运行时间的巨大差异,我宁愿怀疑工作分区逻辑中存在竞争条件错误,因此具有多线程的版本“忘记”了一些工作,而做的工作不如另一个。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2017-02-23
    • 2020-11-29
    • 1970-01-01
    • 2019-02-20
    • 2012-10-17
    • 1970-01-01
    • 1970-01-01
    • 2011-04-30
    • 2021-10-12
    相关资源
    最近更新 更多