每个核心的最佳线程数


280

假设我有一个4核CPU,并且我想在最短的时间内运行某些进程。理想情况下,该过程是可并行化的,因此我可以在无限数量的线程上运行它的块,并且每个线程花费相同的时间。

由于我有4个核心,因此我不希望通过运行比核心更多的线程来提高速度,因为单个核心只能在给定的时刻运行单个线程。我对硬件了解不多,所以这只是一个猜测。

在比内核更多的线程上运行可并行化进程是否有好处?换句话说,如果我使用4000个线程而不是4个线程来运行它,那么该过程会更快,更慢还是在大约相同的时间内完成?

Answers:


253

如果您的线程不执行I / O,同步等操作,并且没有其他任何运行,则每个内核1个线程将为您带来最佳性能。但是,事实并非如此。添加更多的线程通常会有所帮助,但是在某些时候,它们会导致性能下降。

不久前,我在负载相当不错的Mono上运行ASP.NET应用程序的2四核计算机上进行了性能测试。我们使用了最小和最大线程数,最后发现,对于在特定配置中的特定应用程序,最佳吞吐量在36至40个线程之间。在这些界限之外的任何事情都表现得更糟。学过的知识?如果我是你,我将使用不同数量的线程进行测试,直到找到适合您的应用程序的正确数量。

可以肯定的一件事:4k线程将花费更长的时间。那是很多上下文切换。


21
我认为贡萨洛的答案很好。我只是补充说,您应该尝试和测量。您的程序将不同于他,我的程序或任何其他人的程序,并且只有对自己程序的行为进行度量才能正确回答您的问题。并行(或并发)程序的性能并不是仅凭第一条原则就能得出良好结论的领域。
高性能Mark

5
+ 1,+答案:让我感到惊讶的是,线程数多于内核数会带来更好的性能,尽管从某种意义上说,与竞争线程相比,更多线程意味着更大的时间份额。我的应用程序可以检测性能差异并自动将其自身调整为最佳线程数,这将是很好的。
朱丽叶2009年

12
在现实世界中,这并不会让您感到惊讶。线程阻止等待IO资源(如磁盘访问,网络等),也等待非IO资源(如其他线程)完成使用共享变量的操作。您真正想要实现的是最小数量的线程,这样每个内核至少可以一直运行一个线程。
patros

4
每个内核1个线程不是最佳选择。它需要稍微多一点,最好是两倍,因为如果一个线程被临时阻塞,这将允许另一个线程运行。即使只有内存。如果您具有配备SMT / HT的系统(P4,I7,Sun Rock等),这将更加重要
Marco van de Voort 2009年

1
因此,我的回答是“事实并非如此”。找到合适的编号取决于应用程序及其运行的体系结构。
贡萨洛2009年

129

我同意@Gonzalo的回答。我有一个不执行I / O的过程,这是我发现的结果:

enter image description here

请注意,所有线程都在一个数组上工作,但范围不同(两个线程不能访问相同的索引),因此,如果它们在不同的数组上工作,结果可能会有所不同。

1.86机器是带有SSD的macbook air。另一台Mac是具有普通HDD(我认为是7200 rpm)的iMac。Windows机器还具有7200 rpm的硬盘。

在此测试中,最佳数量等于机器中的核心数量。


14
图表为+1。显然,每个内核最好有1个线程,但是有趣的是,四核系统似乎不像其他内核那样具有更高的线程数(无论如何<100)。
Jim Garrison 2012年

46
-1为图!通过整数值x坐标平滑曲线?从1 2 3猛增到10 20 30到50 100?并且y坐标是10加2的倍数,代表很好的度量。这是Excel的工作,不是吗?
Spacedman

5
@Spacedman是的。平滑的曲线恕我直言。:D
Motasim 2012年

22
@PascalvKooten,问题不在于它看起来很漂亮,而是乍看之下是在欺骗。首先,y轴从42开始,放大了测试机器之间的视差。其次,x轴值的怪异变化表明“耗时”与“线程数”不成线性比例,对于蓝线尤其如此。我认为其他人(包括我自己)遇到的问题是它歪曲了数据。
pauluss86

13
@Spacedman图表上的评论是我在过去24小时内遇到的最荒谬的事情。该图很有帮助。很多。期。可以做得更好吗?没人在乎。平滑曲线而不是离散曲线?那是你的问题吗???我想,你们所有人永远都不会在他们的答案中包含这样的图表,因为您没有多余的时间/精力来使它看起来不错。这就是我的意思。
tyrex

49

我知道这个问题比较老,但是自2009年以来情况已经发生了变化。

现在要考虑两件事:内核数,以及每个内核中可以运行的线程数。

对于Intel处理器,线程数由超线程定义,该线程只有2个(如果可用)。但是,即使不使用2个线程,超线程也可以将执行时间减少两倍!(即,两个进程之间共享1条管道-当您拥有更多进程时,这很好,否则就不好了。更多的内核肯定会更好!)

在其他处理器上,您可能具有2、4甚至8个线程。因此,如果您有8个内核,每个内核都支持8个线程,则可以有64个并行运行的进程而无需上下文切换。

如果您在标准操作系统上运行,则“无上下文切换”显然是不正确的,该操作系统将对您无法控制的所有其他事情进行上下文切换。但这是主要思想。一些操作系统允许您分配处理器,因此只有您的应用程序可以访问/使用该处理器!

根据我自己的经验,如果您有很多I / O,那么多线程比较好。如果您有大量的内存密集型工作(读取源1,读取源2,快速计算,写入),那么拥有更多线程将无济于事。同样,这取决于同时读取/写入多少数据(即,如果您使用SSE 4.2并读取256位值,则这将停止所有线程的步...换句话说,一个线程可能更容易实现,并且如果不是真的更快的话,速度可能差不多快。这取决于您的进程和内存架构,一些高级服务器为单独的内核管理单独的内存范围,因此假设您的数据已正确归档,单独的线程会更快...这就是为什么在某些情况下架构,则4个进程的运行速度将比具有4个线程的1个进程快。)


4
可能还有其他,但我知道的是IBM的POWER处理器。他们的系统每个处理器具有4或8个线程。现在他们可以启动更多的内核,因此它们每个内核提供2个线程...
Alexis Wilke

这很老,但是大多数Intel i5,i7具有多线程cpu,例如i7 cpu通常具有4个核心,但有8个线程。
Edgar.A,2015年

4
处理器没有线程。它们具有物理和逻辑核心。使用超线程,单个物理核心可以充当两个逻辑核心。我有一项技术坚持认为带有线程的处理器是真实的东西,所以我在处理器的白板上画了一张图,其中的线程轴伸出来。

@TechnikEmpire看看这个intel.com/content/www/us/en/processors/core/…,也许您也可以联系intel并为其绘制线程。
g7k 2015年

24

实际性能将取决于每个线程将执行多少自愿产量。例如,如果线程根本不执行I / O并且不使用任何系统服务(即它们是100%cpu绑定的),则每个内核1个线程是最佳选择。如果线程做了任何需要等待的事情,那么您将不得不尝试确定最佳线程数。4000个线程会产生大量的调度开销,因此这也不是最佳选择。


21

答案取决于程序中使用的算法的复杂性。我想出了一种方法,通过对两个任意数量的线程“ n”和“ m”进行两次处理时间Tn和Tm的测量来计算最佳线程数。对于线性算法,最佳线程数为N = sqrt((m n(Tm *(n-1)– Tn *(m-1)))/(n Tn-m Tm))。

请阅读我的文章,了解有关各种算法的最佳数的计算:pavelkazenin.wordpress.com


4
为什么要投票?抱歉,这是此问题的最佳答案。gonzalo回答了问题的粗体部分,pkazen回答了标题。这两个答案都非常有用,但是pkazen答案很重要,因为我们有一个系统的方法来估计线程数。他甚至给出了线性算法的公式。
tobiak777

1
我没有拒绝投票,但是如果我这样做,那就是基于没有真正的解释,即为什么或如何将最佳线程数与算法的复杂性相关联,除非阅读完整的链接文章,否则,是一本长篇小说(由于文章的复杂性)。除此之外,本文的某些方面对我还不清楚,最重要的是实验结果如何证实了这一理论。
编码

另外,我相信此计算假设您拥有无限数量的CPU内核。尽管这绝对是有价值的信息,但问题是针对具有少量内核的真实机器。
Navneeth '19

9

我以为我会在这里添加另一个观点。答案取决于问题是假设是弱缩放还是强缩放。

维基百科

扩展能力弱:对于每个处理器固定的问题大小,解决时间如何随处理器数量的变化而变化。

强大的扩展能力:对于固定的总问题大小,解决时间如何随处理器数量的变化而变化。

如果问题是假设缩放较弱,则@Gonzalo的答案就足够了。但是,如果问题是要进行强扩展,则还有更多需要添加的内容。在强扩展中,您假设工作负载大小固定,因此,如果增加线程数,则每个线程需要处理的数据大小会减少。在现代CPU上,内存访问非常昂贵,因此最好通过将数据保存在缓存中来保持局部性。因此,当每个线程的数据集适合每个内核的缓存时,可以找到可能的最佳线程数(我不讨论讨论它是否是系统的L1 / L2 / L3缓存的细节)。

即使线程数超过内核数,也是如此。例如,假设程序中有8个任意工作单元(或AU),这些工作将在4核计算机上执行。

情况1:使用四个线程运行,其中每个线程需要完成2AU。每个线程需要10秒钟才能完成(有很多高速缓存未命中)。如果使用四个内核,则总时间将为10s(10s * 4个线程/ 4个内核)。

情况2:以八个线程运行,每个线程需要完成1AU。每个线程仅花费2s(而不是5s,因为减少了高速缓存未命中次数)。如果使用四个内核,则总时间将为4s(2s * 8个线程/ 4个内核)。

我已经简化了问题,并忽略了其他答案(例如,上下文切换)中提到的开销,但是希望您明白,根据您的数据大小,拥有更多数量的线程可能比可用的核心数量更有益。重新处理。


7

一次可以有4000个线程。

答案是肯定的。如果您在每个线程中执行大量阻塞I / O,那么可以,您可能会显示出显着的加速,每个逻辑内核最多可以处理3或4个线程。

但是,如果您没有做很多阻塞的事情,那么线程的额外开销只会使其变慢。因此,使用探查器查看每个可能平行的部分中的瓶颈在哪里。如果您要进行大量计算,则每个CPU超过1个线程将无济于事。如果您要进行大量的内存传输,那也无济于事。如果您要进行大量的I / O操作(例如磁盘访问或Internet访问),则可以,多个线程将在一定程度上有所帮助,或者至少使应用程序具有更高的响应速度。


7

基准测试。

我将从1开始增加一个应用程序的线程数,然后转到100,对每个线程数进行三到五次试用,然后自己建立一个操作速度与线程数的关系图。

您应该认为四线程的情况是最佳的,此后运行时间会略有增加,但可能并非如此。可能是您的应用程序受带宽限制,即,您正在加载到内存中的数据集非常庞大,您会遇到很多缓存未命中等问题,因此2个线程是最佳选择。

您必须进行测试才能知道。


3

您可以通过运行htop或ps命令找到可以在计算机上运行的线程数,这些命令返回计算机上的进程数。

您可以使用有关“ ps”命令的手册页。

man ps

如果要计算所有用户进程的数目,可以使用以下命令之一:

  1. ps -aux| wc -l
  2. ps -eLf | wc -l

计算用户进程数:

  1. ps --User root | wc -l

另外,您可以使用“ htop” [参考]

在Ubuntu或Debian上安装:

sudo apt-get install htop

在Redhat或CentOS上安装:

yum install htop
dnf install htop      [On Fedora 22+ releases]

如果要从源代码编译htop,请在此处找到它。


2

理想的情况是每核1个线程,只要没有一个线程会阻塞即可。

一种情况可能并非如此:内核上还有其他线程正在运行,在这种情况下,更多线程可能会使您的程序有更大的执行时间。


这取决于您是否希望用户的后台进程在应用程序运行时像废话一样运行。为此,您可以为每个线程设置一个实时优先级并获得最大的功能。但是用户喜欢多任务处理。
Earlz

2
好吧,我们正在处理一个理想的可并行化的神奇应用程序。如果我曾经创造过这样的东西,我将有权利尽可能多地占用CPU。
patros

2

多线程(“线程池”)与每个内核一个线程的一个例子是在Linux或Windows中实现Web服务器的例子。

由于套接字是在Linux中轮询的,因此许多线程可能会增加其中一个线程在正确的时间轮询正确的套接字的可能性-但总体处理成本将非常高。

在Windows中,将使用I / O完成端口(IOCP)来实现服务器,这将驱动应用程序事件驱动:如果I / O完成,则操作系统将启动一个备用线程来处理它。处理完成后(通常使用另一个I / O操作(如请求-响应对)),线程返回IOCP端口(队列)以等待下一个完成。

如果没有I / O完成,则不执行任何处理,也不启动线程。

确实,Microsoft建议在IOCP实现中每个核心不超过一个线程。可以将任何I / O附加到IOCP机制。如果需要,IOC也可以由应用程序发布。


我不知道您在谈论哪个Linux,但是直到连接建立,我才阻止。我建议您阅读一些有关select()和FD_SET()以及类似功能/宏的内容。
亚历克西斯·威尔克

好的,所以没有立即返回的异步形式吗?
Olof Forshell

从select()手册页中:timeout is an upper bound on the amount of time elapsed before select() returns. If both fields of the timeval structure are zero, then select() returns immediately. (This is useful for polling.) If timeout is NULL (no timeout), select() can block indefinitely.
Alexis Wilke

0

从计算和内存限制的角度(科学计算)来讲,4000个线程将使应用程序运行速度非常慢。问题的一部分是上下文切换的非常高的开销,并且很可能是非常差的内存位置。

但这也取决于您的体系结构。从那里我听说Niagara处理器应该能够使用某种高级流水线技术来处理单个内​​核上的多个线程。但是我没有那些处理器的经验。


0

希望这有意义,请检查CPU和内存利用率并设置一些阈值。如果超过阈值,则不允许创建新线程,否则允许...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.