我写了一个并行的java程序。它通常工作:
- 它需要 a
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
笔记:
- JVM 预热时间已被消除(前 50 次运行)。
- 该时间不包括线程开始/加入时间。
当线程数超过 8 个时,内存带宽似乎成为瓶颈。
在这种情况下,如何进一步提高性能?我的并行 Java 程序中是否存在任何设计问题?
为了检查这个可伸缩性问题的原因,我在方法中插入了一个(无意义的计算)循环process(inputs[i])
。这是新数据:
Threads# 1 thread 10 threads
Time(ms) 41000 4330
新数据显示了 10 个线程的良好可扩展性,这反过来证实了原始(没有无意义的循环)存在内存问题,因此其可扩展性仅限于 8 个线程。
但是无论如何要规避这个问题,例如将数据预加载到每个内核的本地缓存中,还是批量加载?