如果并行Java程序受内存限制,如何提高性能?

Jac*_*kWM 1 java parallel-processing optimization multithreading bandwidth

我写了一个并行java程序.它通常工作:

  • 它需要一个String input输入;
  • 然后input切成String inputs[numThreads]均匀;
  • 每个都inputs[i]被分配来thread_i处理,并生成results[i];
  • 在所有工作线程完成之后,main线程合并results[i]result.

10核(物理核)机器上的性能数据如下.

Threads#    1 thread    2 threads   4 threads   8 threads   10 threads
Time(ms)       78           41          28          21           21
Run Code Online (Sandbox Code Playgroud)

注意:

  • JVM预热时间已经消除(前50次运行).
  • 时间不包括线程开始/加入时间.

当存在超过8个线程时,内存带宽似乎成为瓶颈.

在这种情况下,如何进一步提高性能?我的并行Java程序中是否存在任何设计问题?

为了检查这个可伸缩性问题的原因,我在process(inputs[i])方法中插入了一个(无意义的计算)循环.这是新数据:

Threads#    1 thread      10 threads
Time(ms)     41000          4330
Run Code Online (Sandbox Code Playgroud)

新数据显示了10个线程的良好可伸缩性,这反过来证实了原始(没有无意义的循环)存在内存问题,因此其可伸缩性限制为8个线程.

但无论如何要绕过这个问题,比如将数据预先加载到每个核心的本地缓存中,还是批量加载?

Gra*_*ray 6

我发现你不太可能在这里遇到内存带宽问题.您的运行时间很可能很短,当您接近0时,您只是主要计算线程启动/关闭或热交换器编译器优化周期.从运行如此短的Java任务中获取相关的时序信息几乎毫无价值.最初运行的hotswap编译器和其他优化通常会在类的生命早期主导CPU使用率.我们的生产应用程序仅在实时服务运行几分钟后才能稳定.

如果您可以通过添加更多输入数据或通过反复计算相同结果来显着增加运行时间,则可以更好地了解最佳线程数是什么.

编辑:

既然你已经在更长的时间内为1和10个线程添加了时序,那么我认为你不受任何限制,因为时间似乎是相当线性的 - 有一些线程开销.41000/10 = 4100对10线程4330.

很好地演示了线程可以对CPU绑定应用程序做什么.:-)