Runtime.getRuntime().availableProcessors() 返回 1,即使 ECS AWS 上有许多可用内核

Runtime.getRuntime().availableProcessors() returning 1 even though many cores available on ECS AWS

我正在 运行通过 Docker 在 AWS 的 ECS 上执行任务。该任务进行了一些 CPU 绑定的计算,我希望并行进行 运行。我用 Runtime.getRuntime().availableProcessors() 中指定的线程数启动了一个线程池,它在我的 PC 上本地运行良好。出于某种原因,在 AWS ECS 上,这总是 returns 1,即使有多个内核可用。因此我的计算运行是串行的,并没有利用多核。

例如,现在,我在 "t3.medium" 实例上有一个任务 运行ning,根据 docs,它应该有 2 个核心。

当我执行以下代码时:

System.out.println("Java reports " + 
    Runtime.getRuntime().availableProcessors() + " cores");

然后日志中显示以下内容:

Java reports 1 cores

我没有在 ECS 的任务定义中指定 cpu 参数。我在 ECS 管理控制台的任务列表中看到它有一个 "CPU" 列,它为我的任务读取 0。我还注意到,在实例列表(= VM)中,它将 "CPU available" 列为 2048,这可能与 VM 具有 2 个内核的事实有关。

我希望我的 Java 程序能够查看 VM 必须提供的所有内核。 (通常情况下 Java 程序 运行 在没有 Docker 的计算机上运行。

我该怎么做?

感谢评论中的@stdunbar 为我指明了正确的方向。

编辑:感谢评论中的@Imran。如果你启动了很多线程,它们绝对会被调度到多个核心。这个答案只是关于让 Runtime.getRuntime().availableProcessors() 到 return 正确的值。许多 "thread pools" 启动与该方法 returns 一样多的线程:它应该 return 可用的内核数。

似乎有两种主要解决方案,但都不是理想的解决方案:

  • 在任务定义中设置cpu参数。例如,如果您有 2 个内核并想同时使用它们,则必须在任务定义中设置 "cpu":2048。这不是很方便,原因有二:

    • 如果选择更大的实例,则必须确保更新此参数。

    • 如果你想同时有两个任务 运行ning,这两个任务可以偶尔使用所有核心进行短期活动,AWS 不会在一个 2 核上安排两个任务系统 "cpu":2048。从 CPU 的角度来看,它表示 VM 是 "full"。这违背了分时(Unix 等)理念,即每个任务都按需执行(例如,想象一下在台式 PC 上,如果你 运行 Word 和 Excel 在双核计算机上,并且Windows 不允许您启动任何其他任务,因为 Word 可能 需要一个核心,而 Excel 可能 也这样做,所以如果另一个程序 可能 同时需要所有核心,那么核心就不够了。)

  • 使用 JDK 10 中的 -XX:ActiveProcessorCount=xx JVM 选项,如 here 所述。这不方便,因为:

    • 如上,如果您更改实例类型,则必须更改该值。

我写了一篇更长的博客 post 在这里描述我的发现:https://www.databasesandlife.com/java-docker-aws-ecs-multicore/