每个核心的最佳线程数

比方说,我有一个4核CPU,我想在最短的时间内运行一些进程。 这个过程是理想的可并行化的,所以我可以在无数的线程上运行它的块,每个线程都花费相同的时间。

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

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

如果你的线程没有做I / O,同步等等,而且没有别的东西在运行,那么每个内核1个线程将会给你带来最好的性能。 但是,情况可能不是这样。 添加更多的线程通常会有所帮助,但是在某些点之后,会导致性能下降。

不久之前,我在一台运行在Mono上的ASP.NET应用程序的双核四线程机器上进行了性能testing,这个性能相当不错。 我们使用了最小和最大线程数,最后我们发现对于特定configuration中的特定应用程序,最佳吞吐量介于36到40个线程之间。 除此之外的任何事情都performance得更糟。 学过的知识? 如果我是你,我会testing不同数量的线程,直到你find你的应用程序的正确数字。

有一件事是肯定的:4k线程将需要更长的时间。 这是很多的上下文切换。

我同意@贡萨洛的答案。 我有一个不做I / O的过程,下面是我发现的:

在这里输入图像描述

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

1.86机器是一个带SSD的MacBook Air。 另一个mac是一个正常的硬盘(我认为它是7200转)的iMac。 Windows机器也有一个7200转硬盘。

在这个testing中,最佳数量等于机器中的核心数量。

我知道这个问题是比较老的,但是自2009年以来,事情已经演变了。

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

使用英特尔处理器时,线程数由超线程定义,超线程仅为2(可用时)。 但超线程可以将执行时间缩短两倍,即使不使用2个线程也是如此! (即在两个进程之间共享1个pipe道 – 当你有更多的进程时,这是非常好的,否则不太好,更多的核心明确更好!

在其他处理器上,您可能有2,4或8个线程。 所以如果你有8个内核,每个内核支持8个线程,你可以有64个进程并行运行而不需要上下文切换。

如果你使用一个标准的操作系统来执行上下文切换,那么你就无法进行上下文切换。 但这是主要的想法。 一些操作系统让你分配处理器,所以只有你的应用程序访问/使用该处理器!

从我自己的经验来看,如果你有很多的I / O,multithreading是好的。 如果你的内存工作量很大(读源1,读源2,快速计算,写入),那么拥有更多的线程并不会有帮助。 同样,这取决于你同时读/写多less数据(也就是说,如果使用SSE 4.2和读取256位值,这将停止其步骤中的所有线程…换句话说,1个线程可能更容易实现,如果不是真的更快的话,这可能会很快,这取决于你的进程和内存体系结构,一些先进的服务器为不同的内核pipe理单独的内存范围,所以单独的线程会更快,假设你的数据被正确地归档…这就是为什么,体系结构,4个进程运行速度快于1个进程,4个线程)。

实际的performance将取决于每个线程将自愿屈服的程度。 例如,如果线程完全没有I / O并且不使用系统服务(即它们是100%cpu绑定的),那么每个内核1个线程是最优的。 如果线程做任何需要等待的事情,那么你将不得不尝试确定最佳的线程数量。 4000线程会导致大量的调度开销,所以这可能不是最优的。

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

请阅读我的文章关于计算各种algorithm的最佳数字:pavelkazenin.wordpress.com

4000线程一次是相当高的。

答案是肯定的,不是。 如果你在每个线程中做了大量的I / O操作,那么是的,你可以在每个逻辑内核上显示大概3到4个线程。

如果你没有做太多的阻塞事情,那么额外的线程开销会让它变慢。 因此,使用一个分析器,看看每个可能平行的瓶颈在哪里。 如果你正在做大量的计算,那么每个CPU超过1个线程将无济于事。 如果你正在进行大量的内存传输,这也无济于事。 如果你正在做大量的I / O,比如磁盘访问或者互联网访问,那么是的,multithreading会在一定程度上起到一定的作用,或者至less可以使应用程序响应得更快。

基准。

我开始从1开始增加一个应用程序的线程数,然后转到100这样的程序,对每个线程数运行三到五次尝试,并build立一个运行速度与线程数量的关系图。

你应该认为四线程的情况是最佳的,在这之后运行时间略有增加,但也许不是。 这可能是因为你的应用程序是带宽有限的,也就是说,你正在加载到内存中的数据集是巨大的,你得到了很多caching未命中等,使得2个线程是最优的。

直到你testing,你都不知道。

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

维基百科 :

弱缩放:解决scheme的时间如何随处理器的数量而变化,每个处理器的固定问题大小。

强大的扩展:解决时间如何随处理器的数量而变化,以确定总的问题规模。

如果问题是假设弱缩放,那么@贡萨洛的回答就足够了。 但是,如果问题是假设强大的缩放,那么还有更多东西需要添加。 在强大的扩展中,您假定一个固定的工作负载大小,所以如果增加线程数量,每个线程需要处理的数据大小就会减less。 在现代CPU上,存储器访问是昂贵的,并且通过将数据保存在caching中来保持局部性是更可取的。 因此, 当每个线程的数据集都适合每个内核的caching时 (我不打算讨论是否是系统的L1 / L2 / L3caching),可以find最佳的线程数。

即使线程数量超过核心数量,也是如此。 例如假设程序中有8个任意单位(或AU)的工作,将在4核心机器上执行。

案例1:运行四个线程,每个线程需要完成2AU。 每个线程需要10秒才能完成( 有大量的caching未命中 )。 使用四个内核总时间将为10s(10s * 4个线程/ 4个内核)。

情况2:运行8个线程,每个线程需要完成1AU。 每个线程只需要2s(而不是5s,因为caching未命中的数量减less了 )。 八个内核的总时间将是4s(2s * 8个线程/ 4个内核)。

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

通过运行htop或ps命令可以在机器上运行多less个线程,您可以在机器上运行多less个线程。

您可以使用关于“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,你可以在这里find它。

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

一种情况可能不是这样:在内核上运行着其他线程,在这种情况下,更多的线程可能会给程序更多的执行时间。

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

由于套接字在Linux中被轮询,很multithreading可能会增加其中一个轮询在正确的时间插入正确的套接字的可能性,但总体处理成本将非常高。

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

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

的确,微软build议在IOCP实现中每个内核不要有一个以上的线程。 任何I / O都可以连接到IOCP机制。 如有必要,国际石油公司也可以由申请公布。

从计算和内存绑定的angular度来看(科学计算)4000线程会使应用程序运行速度非常慢。 部分问题是上下文切换的开销很高,很可能是非常差的内存局部性。

但是这也取决于你的架构。 据我所知,Niagara处理器能够使用某种先进的stream水线技术在单个内核上处理多个线程。 但是我没有这些处理器的经验。

希望这是有道理的,检查CPU和内存利用率,并把一些阈值。 如果超过阈值,则不允许创build新线程,否则允许…