【问题标题】:Reason for optimum number of threads最佳线程数的原因
【发布时间】:2016-09-19 12:25:49
【问题描述】:

我想知道我写的是否正确,并获得任何进一步的细节或说明(特别是上下文切换的描述):

我的 机器上(使用 Intel Core i7),我有四个内核,每个内核提供两个 硬件线程(例如处理器,使用称为 超线程)。尽管这是“最近”机器上的常见配置 (在撰写本文时),您可能会看到不同的结果——以及 并行Stream 程序的等效默认线程数。

事实证明,“通用”的最佳线程数是 可用的处理器(这可能不适用于特定问题)。这来了 来自线程间上下文切换的代价:存储当前状态 被挂起的线程并检索另一个线程的当前状态 从它进入暂停的地方开始执行。如果您有八个处理器 和八个线程,JVM 在运行八个线程时永远不必切换上下文 任务。如果您的任务少于处理器的数量,那么它不会 帮助分配更多线程。

注意:我将此与并行流和Executors.newWorkStealingPool() 产生(在我的机器上)8 个线程的原因联系起来。

注意2:当你调用Runtime.getRuntime().availableProcessors()时,它在我的机器上返回8。所以我在描述“Java 认为的处理器”。

【问题讨论】:

  • 这通常是不正确的。特别是,如果其中一些线程在任何给定时间什么都不做,那么有更多线程来使用空闲时间是有利的。
  • 如果您要说“最佳线程数”,那么您可能应该说for what。您所描述的可能是 CPU 密集型计算的最佳线程数,具有无限的并行机会,作为机器上的唯一进程运行,但这并不意味着它是其他应用程序的最佳线程数。
  • “硬件线程”不是“处理器”。 “核心”是“处理器”。超线程内核创建了两个虚拟处理器的错觉,因为它有两套完整的上下文寄存器,并且它可以在基本上零时间内在两个上下文之间来回切换。根据复杂程度,它可能有限同时处理两者的能力(最常见的是,通过代表一个线程执行算术运算,而另一个线程正在等待从记忆。)
  • 我重写了有问题的两段。
  • 我认为你应该看看en.wikipedia.org/wiki/Amdahl%27s_law 这是对你问题的一种理论化。只是,文章中所说的,请理解为“并行计算单元的数量”,例如逻辑核。事实上,由于现代 CPU 的体系结构非常复杂,因此您始终可以拥有加速的上限。例如,一些指令可以并行完成,而另一些则不能。无论如何,阿姆达尔定律可以成为一个很好的经验法则:)

标签: java multithreading concurrency


【解决方案1】:

事情没那么简单;很大程度上取决于线程在做什么。如果您的线程都是计算密集型的,则最佳线程数可能与处理器内核数相同,以避免上下文切换的开销。但是,如果您的线程执行 I/O,或者偶尔在资源上被阻塞,那么线程数多于内核数可能是有利的,以避免在线程阻塞时浪费内核数。

此外,英特尔超线程通常不会增加计算能力;该功能在硬件级别维护额外的线程上下文,但不会增加计算能力。因此,对于计算密集型线程,最好将线程数与物理内核数相匹配,而忽略超线程。当线程偶尔被阻塞时,超线程主要是有用的,因为当一个线程被阻塞时,可以避免大部分上下文切换到处理器上的另一个超线程的成本。

注意:关于添加到问题中的附加说明,Java 将每个超线程“视为”处理器这一事实基本上是英特尔过度炒作超线程引入的错误;当活动线程的数量是物理处理器的数量而不是超线程的数量时,计算吞吐量会最大化,因此具有机器自身的工作窃取池在目标线程数量等于物理处理器数量的情况下效果最佳。 Java 的默认设置在大多数处理器上运行良好,但在具有超线程的 Intel 处理器上不是很理想。如果您对其他详细信息感兴趣,我建议您查看我对另一个问题的回答,该问题描述了我针对英特尔处理器上的最佳计算线程数执行的测试:

Multithreading - are the multi-core processors really doing parallel processing?

【讨论】:

  • 我们的cmet同时发生;请参阅上面的第一个注释。我试图描述为什么流和 workStealingPools(可能还有一些我还没有发现的其他东西)选择处理器数量作为最佳线程数。这个数字似乎很受欢迎,但我试图弄清楚“为什么”——根据我所读到的内容,我认为这是上下文切换的成本,但也可能是其他原因。
  • 添加了一段回应您的笔记。不过,我的基本答案保持不变。
  • 我认为值得在这里重复 Ollie Jones 的评论:““超线程”是对高效上下文切换的硬件支持,对于需要中断高优先级非计算密集型线程的工作负载最有利优先级较低的。这使图形用户界面更具响应性。”
  • 还有,egads。有没有简单答案的并发问题?确实是“泄漏的抽象”。我想我需要在这些细节中加入一些重要的脚注。
  • 尽管如此。计算机实际上运行的线程远远多于 4 或 8 个线程——它不仅在运行您的 Java 应用程序,而且还在您的计算机上执行其他所有操作。许多操作系统线程。所以看起来超线程提供的更快的上下文切换最终会很有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多