我正在并行化一个非常复杂的程序,以加快速度。为此,我大部分时间都使用ExecutorService
。到目前为止它工作得很好,但后来我注意到只有一行代码使我的程序运行速度尽可能快一半。它是exactScore.get()
的行。
我不知道为什么,但它有时需要更多的0.1秒来获得Future Object的双倍值。
这是为什么?如何处理它运行得更快?在多线程中有没有办法直接在Double[]
中编写?
感谢
int processors = Runtime.getRuntime().availableProcessors();
ExecutorService service = Executors.newFixedThreadPool(processors);
// initialize output
Double[] presortedExScores = new Double[sortedHeuScores.length];
for(int i =0; i < sortedHeuScores.length; i++ ){
final int index = i;
final Collection<MolecularFormula> formulas_for_exact_method = multimap.get(sortedHeuScores[i]);
for (final MolecularFormula formula : formulas_for_exact_method){
Future<Double> exactScore = service.submit(new Callable<Double>() {
@Override
public Double call() throws Exception {
return getScore(computeTreeExactly(computeGraph(formula)));
}
});
presortedExScores[index] = exactScore.get();
}
}
答案 0 :(得分:2)
这是可以预料的。那不是“慢”;它只是在做它的工作。
来自get()的javadoc:
如果需要等待计算完成,然后检索其结果。
长话短说:您似乎不理解您在代码中使用的概念。 未来的想法是,它在某个时候做某事。
通过调用get()
你表达:我不介意等待现在,直到该计算的结果“落后于”Future可用。
因此:您必须退后一步,再次查看您的代码;了解你的不同“活动线索”是如何运作的;以及他们如何/何时回到一起。
想到一个想法:现在,您正在循环中创建Future对象;在创建Future之后,直接在其上调用get()
。这与创建多个期货的想法完全矛盾。换句话说:而不是去:
foreach X
create future X.i
wait/get future X.i
你可以做点什么
foreach X
create future X.i
foreach X
wait/get for future X.i
换句话说:让你的未来真正并行做事;而不是强制执行顺序处理。
如果这对“足够”没有帮助,那就说:你必须看看你的整体设计,并确定是否有办法进一步“拉开”事物。现在所有活动都“密切”在一起;并且惊讶:当你同时做大量的工作时,这需要时间。但正如你可能猜到的那样:这样的重新设计可能需要做很多工作;如果不了解更多关于你的问题/代码库的话,几乎是不可能的。
更复杂的方法是你编写代码,其中每个Future都有表达“我完成”的方式 - 然后你将“只”启动所有期货;并等到最后一个回来。但正如所说;我不能在这里为你设计一个完整的解决方案。
另一个非常重要的外卖:不要盲目地使用一些“发生”工作的代码。编程的一个要素是理解源代码中使用的每个和任何概念。您应该非常清楚代码在之前运行它并查找“哦,get()
使事情变得缓慢”。