如何检测多核 scalability/contention 问题

How to detect multicore scalability/contention issues

我在多核系统上遇到了可扩展性问题。我的应用程序正在 4 个物理核心机器上并行处理科学数据,8 个逻辑核心激活了超线程。我们启动 8 个 JVM,每个逻辑核心一个(我们可能最终会切换到一个 JVM 以避免 JVM 的开销)

问题是可扩展性几乎是线性的,最高可达 4 个内核,但是通过再添加 4 个内核,我们几乎无法获得 10-20% 的性能 "logical cores"。

我通过分析应用程序来分析线程行为,我没有看到任何锁或等待太多的线程。我还检查了 pidstat 并且我没有看到例如过多的上下文切换开销。更准确地说,java 进程几乎没有上下文切换。 CPU 使用率非常高,几乎达到 100%,这似乎还可以。

我的问题是如何检测和分析超出物理内核数量后扩展性差的原因。我可以使用哪些工具和方法来检测争用的位置,我应该在哪里查看以及我是否可以在不改变应用程序架构的情况下以某种方式修复它(例如每台机器切换到一个 JVM)

谢谢

请注意,超线程并不是将单核的容量翻倍。事实上,有些任务在超线程开启时性能更差。

收益将在很大程度上取决于工作的性质——更多的流水线停顿意味着有更多机会安排另一个进程来代替停滞的进程。

举个例子:在超线程性能方面,完全随机访问内存比在同一缓存行中进行非常快速的cpu密集计算会产生更多。

以下是两个硬件线程共享的东西,因此任何一个都会产生限制任何收益的争用:

  • 缓存
  • 分支预测资源
  • 取指令和解码
  • 执行单位(整数和浮点数)

另一个观察结果是操作系统必须支持 SMT/HT 否则它将无法将任何内容调度到额外的内核中或调度错误的任务。

当 OS 支持时,仍然有可能 OS 争用 诸如文件句柄或网络套接字之类的东西。工作的性质越是“令人尴尬的可并行化”,就越有可能限制这种争论。但是,如果您的工作涉及读取 and/or 写入相同的系统资源,您将获得更少的收益。

将所有这些任务放入 1 个 JVM 后,您的并行度将是:

int cores = Runtime.getRuntime().availableProcessors();