我在多核系统上面临可扩展性问题。我的应用程序在一台4个物理核心、8个逻辑核心的机器上并行处理科学数据,并激活了超线程。我们启动了8个JVM,每个逻辑核心一个(为了避免JVM的开销,我们可能最终会切换到一个JVM)
问题是,最多4个核心的可扩展性几乎是线性的,但通过再添加4个"逻辑核心",我们几乎无法获得10-20%的性能。
我通过分析应用程序分析了线程的行为,没有发现锁或线程等待太多。我还检查了pidstat,没有发现过多的上下文切换开销。更确切地说,java进程上几乎没有上下文切换。CPU使用率非常高,几乎达到100%,这似乎也可以
我的问题是,在超过物理内核的数量后,如何检测和分析这种糟糕的可扩展性的原因。我可以使用哪些工具和方法来检测哪里是争用,我应该在哪里查看,以及我可以在不改变应用程序架构的情况下以某种方式修复它吗(例如,切换到每台机器一个JVM)
感谢
请注意,超线程并不是单核容量的两倍。事实上,当"超线程"打开时,有些任务的性能会更差
收益将在很大程度上取决于工作的性质——更多的管道停滞将意味着有更多的机会安排另一个流程来代替停滞的流程。
举个例子:在超线程性能方面,完全随机访问内存将比在同一缓存行内进行的非常快速的cpu密集型计算产生更多的收益。
以下是两个硬件线程共享的东西,因此任何线程都会产生限制任何增益的争用:
- 缓存
- 分支预测资源
- 指令获取和解码
- 执行单位(整数和浮点)
另一个观察结果是,操作系统必须支持SMT/HT,否则它将无法将任何内容调度到其他核心中,或者将调度错误的任务。
当操作系统支持时,仍然有机会在文件句柄或网络套接字等方面发生操作系统争用。工作的性质越是">令人尴尬的并行性",就越有机会限制这种争论。然而,如果你的工作涉及到对同一系统资源的阅读和/或写作,你将体验到更少的收获。
一旦您将所有这些任务放入一个JVM中,您的并行级别将是:
int cores = Runtime.getRuntime().availableProcessors();