【问题标题】:Single-threaded java program loads multiple cores单线程java程序加载多核
【发布时间】:2017-05-27 09:56:22
【问题描述】:

我们有一个单线程设计的计算要求高的 Java 程序(科学研究)。然而,在执行时,它加载了超过 1 个 CPU 内核(我们注意到这一点很困难——集群作业调度程序杀死了我们的程序,因为它加载了比请求更多的内核)。我们在 linux(Debian、Ubuntu)和 windows (7) 上都遇到过这种奇怪的现象。

我知道 java/jvm(垃圾收集器)添加了几个后台线程,因此即使是单线程程序也可以加载多个内核,但我怀疑这些后台进程是否可以加载另一个或两个完整的内核。

我想知道是什么原因造成的。感谢您的任何提示。如有任何细节,请随时询问,虽然我不能在这里发布代码(首先,它的代码相当多,其次,它仍在研究中,我还不能发布任何东西)。

【问题讨论】:

  • 要求您发布所有代码是愚蠢的。但是,如果您获得一段运行计算的代码,它将有所帮助。此外,查看运行程序的 JVM 参数也很有用。
  • 内存问题怎么办?当您在内存上执行大量操作并且在某些时候内存不足时,垃圾收集器可能会启动并大量使用 cpu。
  • 请注意,由于优化,操作系统和 JVM 都可以选择要处理的内核数。递归和/或 GPU 呢?硬盘读取?

标签: java cpu-usage


【解决方案1】:

首先让我对你不得不在这样一个环境中运行你的程序表示哀悼.但是让我们继续这个问题。

当我暂停一个随机的单线程 java 程序并查看调试器的线程列表时,那里大约有六个线程。这就是 JVM 的工作方式。至少有一个用于垃圾收集的线程,另一个用于运行终结器的线程,以及其他各种东西,其中大部分我什至不知道它们的用途是什么。几十年前,我们失去了准确了解我们机器中正在发生什么的游戏。

您可以使用一些选项来告诉 JVM 减少其线程的使用,例如在与您的程序相同的线程中运行垃圾收集,但我不知道它们,所以您会需要查找它们,坦率地说,我怀疑它会产生很大的不同。总会有你无法控制的线程。

因此,您似乎将不得不配置自己的工作以不使用多个内核。我在工作中完成了它,并取得了一些成功,但今天是星期六,所以我无法访问我使用的脚本文件,所以我将尝试帮助我记住的任何内容。

您正在寻找的概念是“进程线程亲和性”和“NUMA”。

在 Windows 下,start 命令(内置在 cmd.exe 中)允许您指定运行进程的逻辑 CPU(即内核)的数量。 start /affinity 1 myapp 将在核心 1 上运行 myapp

在 Linux 下,至少有几个不同的命令允许您在有限的内核子集上启动进程。我知道的一个是taskset,另一个是numactl

【讨论】:

  • 更不用说(至少在 Windows 上)任务调度程序可能会在 IO 或其他类型的等待之后重新调度不同内核上的单个线程。
【解决方案2】:

set of parameters 供你玩的 JVM。对于 Java 7 及更早版本:

  • -XX:ParallelGCThreads=n 设置垃圾收集器并行阶段使用的线程数。
  • -XX:ConcGCThreads=n 并发垃圾收集器将使用的线程数

对于 Java 8,还有其他取决于操作系统的选项。您可以在 Windows here 上看到它们。一些你可能会觉得有帮助的:

  • -XX:CICompilerCount=threads 设置用于编译的编译器线程数
  • -XX:ConcGCThreads=threads 设置用于并发 GC 的线程数。 默认值取决于 JVM 可用的 CPU 数量(!您的问题的可能原因!)
  • -XX:ParallelGCThreads=threads 设置年轻代和老年代用于并行垃圾回收的线程数。 默认值取决于 JVM 可用的 CPU 数量
  • -XX:+UseParNewGC 启用在年轻代中使用并行线程进行收集。默认情况下,此选项被禁用(但可能由于其他选项而启用

如果您向我们提供更多信息,那么答案会更有帮助和信息量更大

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-07
    • 2019-02-20
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    • 2013-12-17
    • 2011-08-03
    相关资源
    最近更新 更多