Answers:
“为什么会这样?” 很容易回答。假设您有一个走廊,可以同时容纳四个人。您想将所有垃圾一端移动到另一端。最有效率的人数是4。
如果您有1-3个人,那么您会错过使用一些走廊空间的机会。如果您有5个或更多的人,那么这些人中至少有一个基本上总是一直排在另一个人后面。增加越来越多的人只会阻塞走廊,但不会加快活动速度。
因此,您希望拥有尽可能多的人员而不会造成任何排队。 为什么要排队(或出现瓶颈)取决于slm答案中的问题。
4
是最好的数字。
常见的建议是n + 1个线程,n是可用的CPU内核数。这样,n个线程可以在1个线程等待磁盘I / O时使CPU工作。线程较少将无法充分利用CPU资源(在某些时候总是会有I / O等待),线程过多将导致线程争用CPU资源。
线程不是免费的,而是有上下文切换之类的开销,并且-如果必须在线程之间交换数据(通常是这种情况)-各种锁定机制。仅当您实际上有更多专用的CPU内核在其上运行代码时,这才是值得的。在单个核心CPU上,单个进程(没有单独的线程)通常比完成的任何线程处理都要快。线程并不能神奇地使您的CPU更快地运行,而只是意味着额外的工作。
正如其他人指出(SLM答案,EightBitTony答案),这是一个复杂的问题,更是这样,因为你没有描述什么你做thred和怎么他们这样做。
但是,明确地抛出更多线程会使情况变得更糟。
在并行计算领域中,存在适用的阿姆达尔定律(或不能,但是不能描述问题的详细信息,所以……),并且可以提供有关此类问题的一般见解。
阿姆达尔定律的重点是,在任何程序(以任何算法)中,总有一个百分比不能并行运行(顺序部分),而还有另一个百分比可以并行运行(并行部分)[显然这两个部分的总和为100%。
这部分可以表示为执行时间的百分比。例如,严格顺序操作可能会花费25%的时间,其余75%的时间会花费在可以并行执行的操作中。
(图片来自维基百科)
阿姆达尔定律预测,对于程序的每个给定并行部分(例如75%),即使您使用越来越多的处理器来完成工作,您也只能加快执行速度(例如最多4倍)。
根据经验,在并行执行中无法转换的程序越多,使用更多执行单元(处理器)所获得的程序就越少。
考虑到您正在使用线程(而不是物理处理器),情况可能会比这更糟。请记住,可以处理线程(取决于实现和可用的硬件,例如CPU /核)共享同一物理处理器/核(这是多任务处理的一种形式,如另一个答案所示)。
这种理论上的预测(大约CPU时间)并未将其他实际瓶颈视为
在实际应用中很容易成为限制因素。
罪魁祸首应该是“上下文切换”。这是保存当前线程的状态以开始执行另一个线程的过程。如果多个线程具有相同的优先级,则需要切换它们直到执行完成。
在您的情况下,当有50个线程时,与仅运行10个线程相比,发生了许多上下文切换。
由于上下文切换而引入的这种时间开销使程序运行缓慢
ps ax | wc -l
要修复AugustBitTony的隐喻:
“为什么会这样?” 很容易回答。想象一下,您有两个游泳池,一个游泳池满了,一个空了。您想要将所有水从一个转移到另一个,并有4个桶。最有效率的人数是4。
如果你有1-3个人,那你就错过了使用一些水桶的机会。如果您有5个或更多的人,则其中至少有一个人被困在等待一个桶中。增加越来越多的人...并不能加快活动速度。
因此,您希望有尽可能多的人可以同时完成一些工作(使用存储桶)。
这里的人是一个线程,而存储桶则代表执行资源是瓶颈。如果无法执行任何操作,则添加更多线程无济于事。另外,我们应该强调,将水桶从一个人传递到另一个人通常比仅一个人将水桶以相同的距离搬运要慢。也就是说,在一个核心上轮流运行的两个线程通常完成的工作量少于运行两倍的单个线程:这是因为在两个线程之间进行切换需要额外的工作。
出于您的目的,限制执行资源(存储桶)是CPU,内核还是超线程指令管道,取决于体系结构的哪一部分是您的限制因素。还要注意,我们假设线程是完全独立的。这只是如果他们共享的情况下没有数据(并避免任何碰撞缓存)。
就像有人建议的那样,对于I / O来说,限制资源可能是有用的可排队I / O操作的数量:这可能取决于整个硬件和内核因素,但可能远远大于硬件和内核因素的数量。核心。在这里,与执行绑定代码相比成本很高的上下文切换与I / O绑定代码相比非常便宜。可悲的是,我认为如果我用桶来证明这一隐喻是完全无法控制的。
请注意,使用I / O绑定代码的最佳行为通常仍然每个管道/核心/ CPU最多具有一个线程。但是,您必须编写异步或同步/非阻塞I / O代码,而相对较小的性能改进并不总是证明额外的复杂性。
PS。我对原始走廊隐喻的问题是,它强烈建议您应该能够容纳4人,其中2人携带垃圾,2人返回以收集更多的东西。然后,您可以使每个队列几乎与走廊一样长,并且添加人员确实可以加快算法的速度(您基本上将整个走廊变成了一条传送带)。
实际上,这种情况与TCP网络中延迟和窗口大小之间关系的标准描述非常相似,这就是为什么它突然出现在我眼前。
这非常简单明了。CPU所支持的线程多于实际正在串行化而不是并行化。您拥有的线程越多,系统运行速度就越慢。您的结果实际上证明了这种现象。