短版在标题中。
长版:我正在开发一个使用 Java 进行科学优化的程序。程序的工作量可以分为并行和串行阶段——并行阶段意味着正在执行高度可并行化的工作。为了加速程序(它运行数小时/数天),我创建了与我正在使用的机器上的 CPU 内核数相等的线程数——通常是 4 或 8 个——并在它们之间分配工作。然后我在进入串行阶段之前启动这些线程并加入()它们。
到目前为止,一切都很好。困扰我的是,并行阶段的 CPU 利用率和加速远未接近“理论最大值”——例如,如果我有 4 个内核,我预计会看到 350-400% 的“利用率”(如顶部报告)但相反,它在 180 到 310 之间反弹。仅使用一个线程,我得到 100% 的 CPU 利用率。
我所知道的线程不能全速运行的唯一原因是: - 由于 I/O 阻塞 - 由于同步而阻塞
在我的并行线程中没有任何 I/O 发生,也没有任何同步——线程共享的唯一数据结构是只读的,并且是基本类型或(非并发)集合。所以我正在寻找其他解释。一种可能性是多个线程反复阻塞垃圾收集,但这似乎只在内存压力的情况下才有意义,而且我分配的内存远高于所需的最大堆空间。
任何建议,将不胜感激。
更新:以防万一有人好奇,经过更多调查后,我调整了代码以获得一般性能并看到更好的利用率,即使我所做的任何更改都与同步无关。然而,一些变化应该会导致更少的新堆分配,特别是我摆脱了一些迭代器和临时盒装数字的使用(用于高性能 Java 计算的 CERN“Colt”库在这里很有用:它提供了像 IntArrayList 这样的集合, DoubleArrayList 等用于基本类型。)。所以我认为垃圾收集可能是罪魁祸首。