man*_*olo 3 java parallel-processing recursion
我正在并行递归函数,我测得加速不佳.在调试代码时,我注意到在顺序版本中所有内核都在工作.
我在一个最小的例子中重现了这种行为,而且我的所有内核的工作负载都是大约90%.我正在使用Java 8(OpenJDK).
Java是否在我不知情的情况下自动进行并行化?Java如何做到这一点?
import java.util.Random;
import java.util.ArrayList;
class Node
{
float value;
ArrayList<Node> children;
public Node()
{
children = new ArrayList<Node>();
}
public Node(float value)
{
this.value = value;
}
public int count()
{
int count = 1;
if (children != null)
for (Node c : children)
count += c.count();
return count;
}
}
public class ProofOfConcept {
final static int N_NODES = 10000000;
final static int MAX_CHILDREN = 6;
final static Random RAND = new Random();
static Node generateTree(int nNodes)
{
if (nNodes > 1)
{
Node result = new Node();
int nChildren = 1 + RAND.nextInt(Math.min(MAX_CHILDREN, nNodes) - 1);
int nNodesPerChild = (nNodes - 1) / nChildren;
for (int i = 0; i < nChildren; ++i)
{
Node t = generateTree(nNodesPerChild);
result.children.add(t);
}
return result;
}
else
return new Node(RAND.nextFloat());
}
public static void main(String[] args)
{
Node t = generateTree(N_NODES);
System.out.println(t.count());
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:这对我来说也很奇怪.我附上了htop的截图; 正如您所看到的,我们有主进程和八个线程(每个逻辑核心一个).
编辑2:似乎GC正在并行工作.对于那些不明白为什么GC被触发的人,如果显然没有被释放的对象,你应该阅读以下参考:
当分配失败触发垃圾收集,但垃圾收集没有释放足够的空间时,垃圾收集器会扩展存储堆.在堆扩展期间,垃圾收集器从为堆保留的最大存储量(-Xmx选项指定的数量)中获取存储,并将其添加到堆的活动部分(从 - 指定的大小开始) Xms选项).堆扩展不会增加JVM所需的存储量,因为-Xmx选项指定的最大存储量已在启动时分配给JVM.如果-Xms选项的值为应用程序的堆的活动部分提供了足够的存储空间,则垃圾收集器根本不必执行堆扩展.
不,Java并没有神奇地使你的代码并行.
如果您在所有核心上看到90%的利用率,则可以是操作系统,其他进程或JVM进行后台工作.它可能是JVM使用并行GC利用所有核心来收集垃圾.