我们有一个计算要求很高的java程序(科学研究),它被设计为单线程。然而,在执行时,它加载的 CPU 核心远远多于 1 个(我们注意到这一点很困难 - 集群作业调度程序杀死了我们的程序,因为它加载的核心比请求的多)。我们在 Linux(Debian、Ubuntu)和 Windows(7)上都遇到了这种奇怪的现象。
据我了解,java/jvm(垃圾收集器)添加了多个后台线程,因此即使单线程程序也可以加载多个核心,但我怀疑这些后台进程是否可以加载另一个完整的核心或两个。
我询问可能是什么原因造成的。感谢您的任何提示。请随意询问任何细节,尽管我不能在这里发布代码(首先,代码相当多,其次,它仍在研究中,我还不能发布任何内容)。
最佳答案
首先让我对您不得不在这样的环境中运行您的程序表示哀悼,在这种环境中,有人发现终止尝试使用多个核心的作业比限制作业仅使用一个核心更能满足您的智力需求。但让我们继续讨论这个问题。
当我暂停一个随机的单线程 java 程序并查看调试器的线程列表时,其中大约有六个线程。这就是 JVM 的工作原理。至少有一个线程用于垃圾收集,另一个线程用于运行终结器,以及各种其他东西,其中大部分我什至不知道它们的用途是什么。几十年前,我们在准确了解机器中发生了什么的游戏中失败了。
您可能可以使用一些选项来告诉 JVM 减少线程的使用,例如在与您的程序相同的线程中运行垃圾收集,但我不记得它们,所以您会需要查找它们,坦率地说,我怀疑这会产生很大的影响。总会有一些线程是您无法控制的。
因此,您似乎必须将自己的作业配置为不使用多个核心。我在工作中做到了这一点,并取得了一些成功,但今天是星期六,所以我无法访问我使用的脚本文件,所以我将尝试并帮助我记住的任何事情。
您正在寻找的概念是“进程线程关联”和“NUMA”。
在 Windows 下,start
命令(内置于 cmd.exe 中)允许您指定运行进程的逻辑 CPU(换句话说,核心)的数量。 start/affinity 1 myapp
将运行 myapp
将其限制在核心 1 上。
在 Linux 下,至少有几个不同的命令允许您在有限的核心子集上启动进程。我知道的一个是 taskset
,另一个是 numactl
。
关于java - 单线程java程序加载多核,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44215439/