Concurrency 如何使用多核并行在Java中并发运行图形算法
我想在大型图上同时运行一个算法,使用多核并行。我已经做了一段时间了,但是还没有找到一个好的解决方案 这就是朴素的算法:Concurrency 如何使用多核并行在Java中并发运行图形算法,concurrency,java-8,executorservice,multicore,java.util.concurrent,Concurrency,Java 8,Executorservice,Multicore,Java.util.concurrent,我想在大型图上同时运行一个算法,使用多核并行。我已经做了一段时间了,但是还没有找到一个好的解决方案 这就是朴素的算法: W - a very large number double weight = 0 while(weight < W) - v : get_random_node_from(Graph) - weight += calculate(v) 重要的是,所有线程更新相同的I和weight 谢谢。好吧,你可以把权重封装成一个元素数组,这是这类东西的一种诀窍
W - a very large number
double weight = 0
while(weight < W)
- v : get_random_node_from(Graph)
- weight += calculate(v)
重要的是,所有线程更新相同的I
和weight
谢谢。好吧,你可以把
权重
封装成一个元素数组,这是这类东西的一种诀窍;即使是由java内部完成,如下所示:
weight[0] = weight[0] + calculate(v);
但这也有问题,因为您将并行运行它。由于weight[0]
不是线程安全的,因此无法获得所需的结果。您可以使用某种类型的同步,但是java已经有了一个很好的解决方案:DoubleAdder
,它在竞争环境(和多个CPU)中的扩展性要好得多
一个微不足道的小例子:
DoubleAdder weight = new DoubleAdder();
private static int calculate(int v) {
return v + 1;
}
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
.parallel()
.forEach(x -> {
int y = calculate(x);
weight.add(y);
});
System.out.println(weight); // 54
然后是您将为此选择的随机化器的问题:get\u random\u node\u from(Graph)
。实际上,您需要获得一个随机的节点
,但同时您需要精确地获得所有节点一次。
但是,如果可以将所有节点展平到一个列表中,您可能不需要它
这里的问题是,图形通常是以递归方式遍历的,您不知道它的确切大小:
while(parent.hasChildren) {
traverse children and so on...
}
这将并行化坏数据流,您可以查看拆分器#拆分器Unknownsize
。它将从1024开始算术增长;这就是为什么我建议将节点扁平化为一个已知大小的列表;这将更好地并行化。我不确定您想要完成什么-如果要使用Java流计算整个图的权重,您只需将流的每个元素都作为图的一个节点,使用map将其映射到权重,然后对流求和。这也应该是可parellizable的。让权重
。您启动了几个计算(v)
,但在第一个权重+=calculate(v)
之后,权重变为=W
。是否应该取消其他计算,或者他们可以完成工作?如果他们能够完成他们的工作,他们可以并且应该将结果添加到weight
?@AlexeiKaigorodov,只要weight>W
所有过程都应该停止。我将编辑问题以添加更多详细信息。Callable
传递给执行者不需要是lambda。它可以是实现Callable
的任何类型,因此可以访问任何信息。感谢您的建议。但是,我已经尝试过了,并且遇到了同步问题(可能)并得到了InvalidOperationException。
while(parent.hasChildren) {
traverse children and so on...
}