【问题标题】:Performance problems using new fork join framework of jdk 7使用 jdk 7 新的 fork join 框架的性能问题
【发布时间】:2012-08-02 07:47:13
【问题描述】:

我正在使用 jdk 7 的新 forkjoin 框架。 我有一个任务,必须使用不同的参数执行多次。

此任务扩展RecursiveTask。有100多个任务要执行,可以同时执行。这些任务是独立的,因此不需要任何同步。 因此,我首先创建了所需的任务并将它们传递给 forkjoin 线程池。 但是应用程序变得比没有任何并行性的情况下运行它要慢。

我的第一个想法是,我创建了很多线程。这就是为什么我尝试回收线程以减少对象创建开销,但这对性能没有影响。使用 reinitialize() 方法回收 im。此外,通过回收,性能比没有任何并行性的情况下运行要慢。

任务中执行的操作不是微不足道的,运行线程的持续时间从 5 到 150 毫秒。该应用程序在双核机器上运行,我使用 ubuntu 和 oracle jdk 7。

【问题讨论】:

  • 您是否构建了一个简单的程序,它只是简单地分叉一个任务并等待它完成,线程做零工作,以了解上下文切换时间?你知道那是什么时候吗?
  • ...您会注意到使用 2 个处理器时,您的加速比最多为 2 倍。您确定需要 100 个独立任务吗?
  • 我会尝试你的第一条评论 :) 如上所述,我不再使用 100 个独立线程。我创建了固定数量的线程,它们是扩展 RecursiveTask 的对象,如许多示例所示,例如2. 然后我设置这些对象的参数并将它们传递给池,以同时运行。之后我重新设置参数,只要元素可用,就必须执行任务。
  • 5 到 150 毫秒的持续时间还不够,要使用线程吗?
  • 与管理并行性相比,重要的是您可以完成的工作量。如果分叉需要 50 毫秒,而你有 50 毫秒的工作要做,那么你的效率只有 50%。与一个 CPU 相比,使用两个 CPU 最多可以达到收支平衡。因此,了解您的开销很重要。我不知道 Java 分叉需要这么长时间(根本没有经验),这对我来说似乎是一个不合理的高数字。因此建议对其进行测量。

标签: java multithreading performance parallel-processing fork-join


【解决方案1】:

CoopSoft 的 Edward Harned 发现用 Java 实现的 Fork/Join 设计存在许多问题。

特别是,“工作窃取”存在高度争用,并且在将工作分散到多个处理器时效率低下。递归分解也不是特别有效。

如果您的任务不是递归的——你说有 100 个,并且它们可以同时执行——那么使用 ThreadPoolExecutor 的更简单的方法可能更有效。

见:

【讨论】:

  • 这是另一篇好文章,它给出了更平衡的 IMO 观点:moi.vonos.net/java/forkjoin。 FJP 的一些经验法则似乎是: 1. 避免使用公共池,因为 JVM/库可能正在使用它。 2. 避免在线程中阻塞,因为 FJP 是固定大小的(仅限 CPU 绑定的任务) 3. 设置从递归切换到串行的阈值,否则您可能会炸毁堆栈,因为每个 join() 都在同一个中运行新任务线。所以我认为 FJP 最适合 CPU 密集型的分并合并,深度较浅但分支较大(即许多任务)
猜你喜欢
  • 2013-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-09
  • 1970-01-01
  • 1970-01-01
  • 2018-08-02
相关资源
最近更新 更多