我在.NET 3.5控制台应用程序中有一些令人尴尬的可并行化工作,我想利用超线程和多核处理器。 如何选择最佳数量的工作线程,以便在任意系统上使用其中任何一种?例如,如果它是双核,我将需要2个线程;四核我想要4个线程。我最终得到的是确定处理器特性,以便我知道要创建多少线程。
我不是在问如何分割工作,也不是如何进行线程处理,我问如何确定这个控制台应用程序运行的任意机器上的“最佳”线程数。
答案 0 :(得分:15)
我建议你不要自己决定。使用ThreadPool让.NET为您管理线程。
答案 1 :(得分:9)
如果这是你唯一的事情,你可以使用Environment.ProcessorCount。但通常使用ThreadPool确实是更好的选择。
.NET线程池还有一些规定,有时会分配更多线程而不是核心,以便在许多线程等待I / O完成的某些情况下最大化吞吐量。
答案 2 :(得分:4)
正确的数字显然是42。
现在严肃的说明。只需使用线程池。
1)如果您有一个冗长的处理任务(即CPU密集型),可以将其划分为多个工件餐,那么您应该对任务进行分区,然后将所有单个工作项提交给{ {3}}。线程池将以动态方式拾取工作项并开始搅拌,因为它具有自我监控功能,包括根据需要启动新线程,可以是ThreadPool,而不是在开发时预先计算数字。虽然您的处理任务的正确分区大小可以考虑可用的CPU数量,但正确的答案在很大程度上取决于任务的性质以及在此阶段甚至不值得谈论的数据(此外主要关注点应该是您的configured at deployment by administrators according to the deployment site requirements,内存位置和互锁缓存争用,并且只有在核心数量之后才有。)
2)如果您正在进行I / O(包括数据库调用),那么您应该使用异步I / O并完成ThreadPool中称为完成例程的调用。
这两个是你应该拥有多个线程的唯一有效理由,并且使用ThreadPool可以最好地处理它们。其他任何事情,包括根据'请求'或'连接'启动一个线程实际上是Win32 API世界中的反模式(fork是* nix中的有效模式,但绝对不在Windows上)。
对于更专业,更方式,更详细的讨论主题,我只能推荐Rick Vicik关于这个主题的论文:
答案 3 :(得分:3)
鉴于你完全受CPU约束,一个好的经验法则是processorCount+1
。
那是 +1 ,因为你总会得到一些启动/停止/中断的任务,而n
任务几乎永远不会完全填满n
个处理器。
答案 4 :(得分:3)
最佳数字只是处理器数量。最理想的是,您总是会在CPU(逻辑或物理)上运行一个线程,以最大限度地减少上下文切换以及与之相关的开销。
这是否正确的数字取决于(正如每个人所说的)你正在做的事情。线程池(如果我理解正确的话)几乎尝试使用尽可能少的线程,但每次线程阻塞时都会旋转另一个线程。
阻止永远不是最佳的,但如果您正在进行任何形式的阻止,那么答案将会发生巨大变化。
获得良好(不一定是最佳)行为的最简单和最简单的方法是使用线程池。在我看来,它真的很难比线程池做得更好,所以这只是最好的起点,如果你能证明为什么不够好就只考虑别的东西。
答案 5 :(得分:2)
唯一的方法是基于性能数据的数据和代码分析的组合。
不同的CPU系列和速度与内存速度相比系统上的其他活动都会使调整不同。
可能有一些自我调整是可能的,但这意味着要进行某种形式的现场表演调整和自我调整。
答案 6 :(得分:2)
甚至比ThreadPool更好,使用TPL中的.NET 4.0 Task实例。任务并行库建立在.NET 4.0框架的基础之上,它将实际确定为您尽可能高效地执行任务的最佳线程数。
答案 7 :(得分:1)
我最近阅读了一些内容(例如,请参阅this question的已接受答案)。
简单的答案是你让操作系统决定。它可以更好地决定什么是最优的。
关于类似主题有很多问题 - 搜索“最佳数字主题”(不带引号)会给你几页结果。
答案 8 :(得分:1)
我会说这也取决于你在做什么,如果你制作一个服务器应用程序然后通过Environment.ProcessorCount或线程池使用你所能从CPU中获得的所有东西都是个好主意。 但是,如果这是在桌面或不专用于此任务的计算机上运行,您可能希望保留一些CPU空闲,以便机器为用户“运行”。
答案 9 :(得分:0)
可以说,选择最佳线程数的真正方法是让应用程序对自身进行分析,并根据提供最佳性能的内容自适应地改变其线程行为。
答案 10 :(得分:0)
我写了一个使用多个线程的简单数字运算应用程序,并发现在我的四核系统上,它使用6个线程在固定时间内完成了大部分工作。
我认为确定的唯一真正方法是通过试验或剖析。
答案 11 :(得分:0)
除了处理器计数之外,您可能还想通过计算GetProcessAffinityMask函数返回的关联掩码中的位来考虑进程的处理器关联。
答案 12 :(得分:0)
如果线程运行时没有过多的i / o处理或系统调用,那么线程数(主线程除外)通常等于系统中的处理器/内核数,否则你可以尝试通过测试来增加线程数。