java - 并行化 : What causes Java threads to block other than synchronization & I/O?

标签 java multithreading parallel-processing

简短版本在标题中。

长版: 我正在研究一个使用 Java 进行科学优化的程序。程序的工作负载可以分为并行和串行阶段——并行阶段意味着正在执行高度并行化的工作。为了加速程序(它运行数小时/数天),我创建了多个线程,这些线程的数量等于我正在使用的机器上的 CPU 核心数量——通常是 4 或 8 个——并在它们之间分配工作。然后我启动这些线程并加入()它们,然后再进入串行阶段。

到目前为止一切顺利。困扰我的是并行阶段的 CPU 利用率和加速比“理论最大值”还差得很远——例如如果我有 4 个内核,我希望看到 350-400% 的“利用率”(如 top 所报告),但它在 180 到 310 之间反弹。仅使用一个线程,我获得 100% 的 CPU 利用率。

据我所知,线程无法全速运行的唯一原因是: -由于 I/O 而阻塞 -由于同步而阻塞

我的并行线程中没有发生任何 I/O,也没有任何同步——线程共享的唯一数据结构是只读的,并且是基本类型或(非并发)集合。所以我正在寻找其他解释。一种可能性是多个线程反复阻塞以进行垃圾回收,但这似乎只有在内存压力大的情况下才有意义,而且我分配的内存远远超过所需的最大堆空间。

如有任何建议,我们将不胜感激。

更新:以防万一有人好奇,经过更多调查后,我调整了代码以获得一般性能并看到更好的利用率,即使我所做的任何更改都与同步无关。然而,一些变化应该会导致更少的新堆分配,特别是我摆脱了一些迭代器临时盒装数字的使用(欧洲核子研究中心的“Colt”库高性能 Java 计算在这里很有用:它为基本类型提供了 IntArrayList、DoubleArrayList 等集合。)所以我认为垃圾收集可能是罪魁祸首。

最佳答案

所有图形操作都在 swing 中的单个线程上运行。如果它们正在呈现到屏幕上,它们将有效地争夺对该线程的访问权。

如果您在 Windows 上运行,无论如何,所有图形操作都在单个线程上运行。其他操作系统也有类似的限制。

实际上有时很难获得适当的线程工作线程粒度,有时很容易使它们太大或太小,这通常会使所有内核的使用率低于 100%。

如果您没有渲染太多的图形用户界面,最有可能的罪魁祸首是您对一些共享资源的争夺比您想象的要多。使用 jprofiler 等分析器工具很容易看到这一点。 bea 的 jrockit 等一些 VM 甚至可以开箱即用地告诉您这一点。

这是您不想凭猜测行事的地方之一。获取分析器!

关于java - 并行化 : What causes Java threads to block other than synchronization & I/O?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/333280/

相关文章:

r - 在 R 中并行执行 glmnet

.net - Parallel.ForEach 具有有序输入?

python - IPython 并行 LoadBalancedView GIL

java - 当元素过期时具有信令功能的过期映射

java - 如果数据库不为空,则在应用程序开始时下载数据

java - 多线程不起作用。什么是不正确的?

java - 重入锁定条件

Java - 应用程序在 Thread.sleep 方法上崩溃

java - 使用正则表达式提取捕获组

java - Android Studio 中的错误 : setContentView(R.layout.main)