2012-02-07 152 views
7

让我们假设我们有固定数量的计算工作,没有阻塞,睡眠,I/O等待。这项工作可以很好地并行 - 它由100M小而独立的计算任务组成。如何在4核CPU上执行相同的计算:4个线程或50个线程?

4核CPU的运行速度是多少?运行4个线程还是...可以说50?为什么第二个变体应该是slover和多少slover?

正如我所假设的:当您在4核CPU上运行4个重线程而没有另一个CPU消耗进程/线程时,调度程序可以不在内核间移动线程;在这种情况下没有理由这样做。 Core0(主CPU)将负责执行每秒250次硬件定时器(基本Linux配置)和其他硬件中断处理程序的中断处理程序,但其他内核可能不会感到任何担忧。

上下文切换的成本是多少?为不同的上下文存储和恢复CPU寄存器的时间? CPU内部的缓存,管道和各种代码预测事物呢?我们可以说,每当我们切换上下文时,我们都会伤害CPU中的缓存,管道和一些代码解码设施?因此,在单个内核上执行的线程越多,与串行执行相比,他们可以一起完成的工作就越少?

关于多线程环境中的缓存和另一个硬件优化问题对我来说是一个有趣的问题。

+3

答案在很大程度上取决于应用程序,系统和机器。但它可能大于4,但远远少于50个线程。你是否尝试用4,6,8,10线测量? – 2012-02-07 20:39:31

+0

4个线程(或8个超线程)。较少的数据部分。更好的缓存属性。 – bestsss 2012-02-07 20:42:48

回答

11

作为@Baile在评论中提到,这是高度应用程序,系统,环境特定。

因此,我不打算采用强硬的方法为每个内核提供恰好一个线程。 (在超线程的情况下是2线程/内核)

作为一个经验丰富的共享内存程序员,我从我的经验中看到,最优数量的线程(对于4核心机器)的范围可以从1到64 +。

现在我将列举可能导致此范围内的情况:

优化线程核心的<#

在这种非常细粒度并行(如小FFT)算法的某些任务时,线程的开销是主要的性能因素。在某些情况下,根本无法并行化。在某些情况下,您可以使用2个线程加速,但在4个线程上进行向后缩放。

另一个问题是资源争夺。即使你有一个高度可并行化的任务,可以很容易地在4个内核/线程之间分配,你可能会受到内存带宽和缓存效应的瓶颈。通常情况下,您会发现2个线程将与4个线程一样快。(仿佛往往具有非常大的FFT的情况下)磁芯

最优线程=#这是最佳的情况。这里不需要解释 - 每个核心有一个线程。大多数不符合内存或I/O限制的并行应用程序都适合于此。

优化线>核心

这是它变得有趣......非常有趣的#。你听说过负载不平衡吗?如何过度分解和偷工减料?

许多可并行化的应用程序是不规则的 - 这意味着任务不会分裂成大小相等的子任务。所以如果你最终可能将一个大任务分成4个不相等的大小,将它们分配给4个线程并在4个内核上运行它们......结果呢?差的并行性能,因为1线程碰巧得到比其他线程多10倍的工作。

这里一个常见的解决方案是将过度分解成许多子任务。你可以为每一个创建线程(所以现在你得到线程 >>核心)。或者你可以使用某种具有固定数量线程的任务调度程序。并非所有的任务都适合这两种,所以很多时候,为4核机器过度分解任务到8或16个线程的方法会产生最佳结果。


虽然产生更多的线程可以导致更好的负载平衡,但会产生开销。所以通常有一个最佳点。我在4个内核上看到了高达64个线程。但如前所述,这是高度专用的。你需要做实验。


编辑:扩大答案更直接地回答这个问题...

什么是上下文切换的成本?存储和恢复的时间 针对不同上下文的CPU寄存器?

这是非常依赖于环境 - 有点难以直接测量。
简短的回答:非常昂贵This might be a good read.

什么缓存,管道和各种符号的预测里面的东西 CPU?我们可以说,每次我们切换上下文时,我们都会伤害缓存,管道和CPU中的一些代码解码工具?

简短的回答:当你进行上下文切换时,你可能会刷新你的管道,乱了所有的预测。与缓存相同。新线程可能会用新数据替换缓存。

虽然有一个问题。在线程共享相同数据的某些应用程序中,有可能一个线程可能会为另一个传入线程或另一个共享相同缓存的核心上的另一个线程“加热”高速缓存。(虽然罕见,但我已经看到了这个在我的NUMA机器之一发生之前​​ - 超线性加速!?!?!在16个内核17.6倍)

所以多个线程在单个核心上执行,少的工作,他们与其串行执行相比,可以一起执行 吗?

取决于,......除了超线程之外,肯定会有开销。但是我读过一篇文章,其中有人使用第二个线程来预取主线程...是的,这太疯狂了......

+0

如果你有100个小任务,threads =内核看起来很明显,在最坏的情况下+工作被盗。尽管如此,一个可爱的职位。 – bestsss 2012-02-07 20:59:36

+0

实际上,在线程>内核情况下(不包括超线程),100M小任务不太可能是最优的。根据资源绑定的方式,它甚至可能会落入线程<核心类别中。如果你有一个任务分成6个相等的部分,但你只有4个核心的话,那么threads> cores case就很常见了。 – Mysticial 2012-02-07 21:30:47

0

如果您可以使用4个线程,请使用它们。在4核机器上,50的速度不会超过4。你得到的只是更多的开销。

当然,您正在描述一个理想的非现实世界的情况,所以无论您实际构建的是什么,都需要进行测量以了解性能如何受到影响。

0

超线程技术可以为每个CPU处理更多的线程,但它几乎不依赖于您想要执行的计算类型。考虑使用GPU或非常低的汇编语言来实现最大功率。

0

创建50个线程实际上会损害性能,而不是提高性能。它只是没有任何意义。

理想情况下,你应该使4线程,不是更多,而不是更少。由于上下文切换会有一些开销,但这是不可避免的。 OS /服务/其他应用程序线程也应该执行。但是现在有了如此强大而且照明快的CPU,这一点并不重要,因为这些操作系统线程只会占用CPU时间的2%以下。当你的程序运行时,它们几乎全部都处于阻塞状态。

您可能认为,由于性能至关重要,因此您应该使用低级汇编语言编写这些小型关键区域。现代编程语言允许这样做。

但是严重的......编译器和Java的情况下,JVM会优化这些部分,以至于它不值得(除非你真的想要这样做)。而不是你的计算在100秒内完成,他们将在97或98完成。你必须问自己的问题是:是否值得所有这些小时的编码和调试?

您询问了上下文切换的时间成本。这些天,这些非常低。例如,查看运行Windows 7的现代双核CPU。如果您在该计算机和MySQL数据库服务器上启动一个Apache Web服务器,您将很容易超过800个线程。机器感觉不到它。要看这个成本有多低,请阅读:How to estimate the thread context switching overhead?。为了节省您的搜索/阅读部分:上下文切换可以在的每秒数十万次完成

+0

*如果你在该机器上启动一个Apache web服务器并且启动一个MySQL数据库服务器,你将很容易超过800个线程*但几乎所有的都处于休眠状态(即没有上下文切换) – bestsss 2012-02-07 21:02:50

0

如果您可以将40个任务编程为比操作系统更好地执行,则4个线程更快。

相关问题