2017-05-27 59 views
1

我们有一个计算要求严格的java程序(科学研究),它被设计为单线程。但是,在执行时,它加载的CPU核心远远超过1个(我们注意到这是困难的方式 - 集群作业调度程序因为装载了比请求更多的内核而杀死了我们的程序。我们在linux(Debian,Ubuntu)和windows(7)上遇到了这个奇怪的现象。单线程Java程序加载多个内核

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

我问任何想法可能会导致这种情况。感谢任何提示。尽管我不能在这里发布代码(首先,它有很多代码,其次,它仍在研究中,我还不能发布任何东西),所以请随时索要任何细节。

+0

这是愚蠢的问你发布**全部**代码。但是如果你得到一段运行计算的代码,它将会有所帮助。另外,查看您运行该程序的JVM参数会很有用。 – ADS

+0

内存问题呢?当你在内存上执行大量操作时,在某些时候内存不足,那么垃圾收集器可能会启动并大量使用cpu。 – gawi

+0

请注意,由于优化,OS和JVM都可以选择要处理的内核数量。递归和/或GPU如何?硬盘读数? – ADS

回答

2

让我首先向您表示我的哀悼,因为不得不在一个人们发现它在智力上更符合要求的情况下运行您的程序,以杀死尝试使用多个内核的作业,而不是将作业限制为仅使用一个内核。但让我们继续讨论这个问题。

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

可能有一些选项可以用来告诉JVM减少其对线程的使用,例如在与程序相同的线程中运行垃圾收集,但我不认识它们,所以你将需要查看它们,坦率地说,我怀疑它会有什么不同。总会有你无法控制的线程。

所以,看起来你将不得不配置你自己的工作不使用多个核心。我已经在工作中取得了成功,但今天是星期六,所以我无法访问我使用的脚本文件,所以我会尝试帮助记住我所记下的任何内容。

您正在查找的概念是“流程线程关联”和“NUMA”。

在Windows下,start命令(内置于cmd.exe)允许您指定逻辑CPU(换句话说,核心)的数量来运行您的进程。 start /affinity 1 myapp将运行myapp限制它在核心1上。

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

+0

更不用说(至少在Windows上),任务调度程序可能会在IO或其他类型的等待之后重新调度不同核心上的单个线程。 –

1

对于JVM你可以玩set of parameters。对于Java 7和更早版本:

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

对于Java 8有依赖于操作系统的另一个选择。你可以看到他们的Windows here。有些你能找到有用的:

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

如果您向我们提供更多的信息,然后答案会比较有用的信息