常规 - 线程池中的线程数

时间:2010-02-11 04:25:14

标签: multithreading

我和一位朋友正在讨论线程池中的线程数应该是处理器数+ 1还是处理器数。

我只选择了处理器数量,因为可以将偶数个线程分配给每个处理器,并且他选择处理器数量为+1,因为他认为这将有助于他优化性能。

谁是对的?

4 个答案:

答案 0 :(得分:4)

你们两个。

正确的答案是:你需要一些产生最佳整体效果的线程。

您添加的每个帖子都有成本。这是一个很小的成本,但它绝对是一个成本。在线程池中放置30,000个线程,并观察您的系统停止运行(如果他们都在做某事)。

但是每个帖子都会在理论上节省一些(整体)时间。

从概念上讲,您可以绘制该关系并生成一系列线程,这些线程将在给定某些资源限制的情况下为您提供所需的结果。正确的线程数在某个范围内。

注意:我说“整体结果”。这不一定是“最快的结果”。一个线程可以在10分钟内完成任务。 100个线程可以在15秒内完成。 1000个线程可以在10秒内完成,因为您开始达到针对特定问题的争用限制。这是一个更好的整体结果吗? 10到15秒之间可能没有真正的差异,但1000个线程可能会使用更多内存。

请记住,并非所有线程都受CPU限制,因此在很多情况下完全有理由拥有比内核数量更多的线程,因为在执行任务的某个时刻线程可能会在等待某些事情发生时休眠(网络通信,磁盘读取,等等。)

答案 1 :(得分:1)

都不是。

操作系统的内核(除非通过关联设置明确指示)可以并将在系统中的可用内核上迁移该进程。

如果您查看System.Threading.ThreadPool(MSDN),默认情况下,Microsoft会为每个可用核心创建250个线程。重用空闲线程比创建/销毁(冲洗和重复)线程“更便宜”。

答案 2 :(得分:1)

如果所有线程都受CPU限制且没有进行I / O操作,那么通常可以获得具有完全CPU数量的最佳结果。运行超过CPU的数量会导致频繁的上下文切换(这会减慢速度)并且运行较少会使一些CPU闲置。

如果线程使用大量RAM,则可能需要少于CPU的数量以避免进入交换。这通常是在并行编译C ++代码时发生的,因为GCC(否则会严重受CPU限制)会使用大量RAM进行模板实例化。

如果线程阻塞I / O(通常是磁盘,但也可能是网络或其他外部资源),则可能需要超过CPU的数量,以保持CPU完全占用,但另一方面你可能想要少于那个以避免I / O窒息(机械硬盘特别是当他们需要同时读/写多个位置时减速)。

如果系统有任何实时要求(例如游戏或视频播放器),则应保持一个CPU大部分空闲(以允许频繁的上下文切换和交互)。

所以,正如其他人所说,没有简单的答案。在上面的所有示例中,我假设系统上没有其他程序在运行,使用任何大量的CPU(这种情况经常出乎意料)。如果还有其他CPU用户,请在计算中考虑(例如,通过减少可用的CPU数量)。

对于主要受CPU限制的情况,唯一有用的“快速规则”是N-1,N和N + 1(其中N是可用CPU的数量),具体取决于所提到的因素。对于严重磁盘I / O限制情况,只应使用一个线程(每个HDD)。

答案 3 :(得分:0)

答案是'这取决于'。

您正在空闲系统上进行纯计算数学,然后答案是“理论上”每个核心一个线程。实际上,系统“从不”闲置,少量的超额订购会有所帮助。

准确的超额订阅量取决于线程“计算”与阻止等待I / O(网络,文件,用户输入)的频率。

如果您正在进行网络或文件I / O添加少量线程将有所帮助,因为请求可以排队并一起提交,如果添加太多线程,那么您将只是泛滥I / O系统或控制器有效地结束了锁定传送。

.NET 4添加了hill climbing algorithm以帮助检测线程池中需要多少线程才能以最佳方式执行。

类似地,Windows7添加用户模式预定线程,在阻塞发生时提供呼叫黑色通知,以便可以明确地完成此操作(Concurrency Runtime利用此功能)。

如果您只是在寻找快速回答,那么尝试2N - 1用于非计算绑定工作负载,其中N小于< 8。

-Rick