C#最大线程数

4

我刚开始使用线程,很快就遇到了一个非常普遍的问题:有太多线程会造成什么影响?
经过一些研究,我变得更加困惑了。

任务
我有16个核心和一个生成1000个对象的应用程序,尽管构造参数保持一致。根据msdn文档和Maximum number of threads,创建1000个线程通常会创建巨大的开销,破坏多线程的性能优势。此外,我必须在3.5 NET 32位限制内(Maximum number of threads in a .NET app?)。

问题1
对于这样一个单边任务,是否可能在计算机上创建比核心更多的线程?.NET是否在优化其中的某些内容?我应该使用的最大线程数是多少?

问题2
是否有简单美观的解决方案,而不是将其排队并限制资源?类似于信号量,我创建了所有1000个线程,但立即使线程处于非活动状态,以便不分配默认线程堆栈?


3
线程池是一个有用的概念。 - Chris O
4
不应创建太多线程,应该只创建与核心数相同数量的线程,并重复使用线程来完成多个任务。 - Marko
4
你的问题中缺少了你认为线程起到的作用。为什么你认为需要1000个线程来创建1000个对象? - CodeCaster
第一个问题已经有了很好的重复。第二个问题(实际上不应该在同一篇文章中提出...)目前非常广泛,不太可能得到具体的答案 - 无论如何,请考虑将其作为单独的问题提交,并附上指向此问题的链接以及关于您希望通过多线程进行优化的具体说明。 - Alexei Levenkov
3个回答

11
是的,你可以(而且很可能应该)创建比核心数量更多的线程,因为操作系统调度程序会在活动线程之间进行切换,即使没有其他东西在等待该核心。然而,你也不想创建1000个单独的线程。相反,创建一些线程并将工作分配给它们,这样每个线程可以处理完整任务中的多个项目。
我发现一个好的经验法则是每个逻辑核心使用两个线程(这包括超线程核心...如果你有一个具有超线程的8核CPU,即16个逻辑核心,那么创建32个线程)。这样做的目的是尽可能减少调度程序中断/上下文切换的次数,同时保持所有核心都忙于主要处理你的任务。考虑到即使没有其他活动在逻辑核心上,调度程序中断仍然会发生,为该核心准备两个活动线程意味着调度程序很可能只会将你程序中的空闲线程放入其中。即使该核心有其他活动,现在也很可能选择执行你的线程。超过这个数量可能会导致比必要的更多的上下文切换,从而影响性能。
简而言之,每个核心的第二个线程的成本很低(因为上下文切换仍然会发生),但回报潜力很高(整个调度程序块在处理您的应用程序而不是其他任务时)。随着每个核心添加更多线程,成本会增加,潜在好处会减少。
但这只是我的(非常有限的)经验。这是非常概括的,不适合用于更多的参考。为了获得最佳性能,您真的需要测试不同线程数量下应用程序的行为。
最后,在.NET世界中,值得一提的是线程池和异步任务。这不是深入讨论这些主题的最佳场所,但研究它们绝对值得您的时间。

4

计算机上是否可能创建比核心更多的线程?

是的,这是可能的。

.NET 是否进行了优化? 我应该使用多少线程作为最大值?

实际上,在99.99%的情况下,您不必关心线程数量,因为您...在99.99%的情况下不得手动创建线程。如果必须保留.NET 3.5,请改用ThreadPool。如果您的版本为4.0或更高版本,则使用任务

除了使用受限资源对其进行排队外,是否有简单美观的解决方案?

实际上,没有。您无法跨越物理可用资源,这是瓶颈。


3
基本上,随着线程数量的增加,新线程的性能百分比会越来越少。10个线程并不比1个线程运行10倍更快。而且,当你运行的线程数超过核心数时,你得不到任何有意义的东西。经验法则是,对于性能要求较高的代码,请使用线程让其在后台运行,而不是在UI线程上运行,以避免阻塞UI响应。如果您想优化已经非UI阻塞的代码,那么可以查看目标机器上的核心数,并创建一些线程来帮助重型算法,如果有意义的话。请记住,编写多线程代码要比单线程代码难调试、难维护和难编写得多。因此,只有在实验和学习时才这样做,否则只有在您真正需要将一些额外的功率压缩到应用程序中时才这样做。
答案1:是的,可以创建比核心更多的线程,但几乎没有任何意义。
答案2:不要创建1000个线程来创建1000个对象!那不美观。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接