2017-01-16 32 views
2

私はそれをより速くするために非常に複雑なプログラムを並列化しています。このために私はほとんどの時間をExecutorServiceで使います。これまではかなりうまくいっていましたが、コードのほんの1行でプログラムが半分の速さで実行されることに気付きました。 exactScore.get()の行です。ExecutorService Future ::非常に遅い

私は理由はわかりませんが、未来オブジェクトの2倍の値を取得するために0.1秒以上かかることがあります。

これはなぜですか?どのように私はそれが速く実行されますそれを処理できますか?マルチスレッド中に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(); 
     } 

    } 

答えて

2

これは予想されます。それは "遅い"ではない。それは仕事をしているだけです。 get()のJavadocから

待機必要に応じて完了する計算のため、そしてその結果を取得します。

短いストーリー:コードで使用している概念を理解できていないようです。 未来というアイデアは、将来何かの点でのものを実行するということです。

get()を呼び出すと、次のように表現されます。に送信すると、その計算の結果が「今後」利用可能になるまで表示されます。

したがって、もう一度元に戻ってコードを調べる必要があります。あなたのさまざまな「活動の糸」が本当にどのように働くかを理解する。どのように/いつ彼らが戻ってくるのか。

考えてみましょう:今、あなたはあなたの未来のオブジェクトをループで作成しています。未来を作成した直後に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 

ような何かを行うことができます:あなたの未来は本当に並行して物事を行うことができ、 逐次の処理を実行する代わりに、

それが "十分"に役立たないならば、あなたは全体のデザインを見て、さらに物事を「引き離す」方法があるかどうかを判断しなければなりません。今、すべての活動は「密接に」起こります。驚き:同時に多くの仕事をすると時間がかかります。しかし、あなたが推測しているように:そのような再設計は多くの仕事になる可能性があります。あなたの問題/コードベースについてもっと知らなくても不可能に近づいています。

もっと洗練されたアプローチは、それぞれの未来が「私は終わった」という表現方法を持っているコードを書くことです。そして、あなたはすべての未来を「ただ」始めるでしょう。最後のものが戻ってくるまで待ってください。しかし、言ったように。私はここであなたのために完全なソリューションを設計することはできません。

もう1つ重要なことはここにあります。「動作する」コードを盲目的に使用しないでください。プログラミングの本質は、それぞれと、ソースコードで使用されているの概念を理解することです。 の前にが実行されていて、「ああ、そのget()は遅くなります」ということを見つけるのは、かなり良いアイデアです。

+0

私はすでにforループでそれを取得しようとしないと良いでしょうか?私がexactScor.getが完了するまで、あなたが正しくあなたを理解すれば、他のエグゼキュータはジョブを取得しないため(この時点では新しいマルチスレッドは存在しません)。 – user312549

+0

私の様々なアップデートをご覧ください。 2つのループで物事を分割することができます。それは本当に単純なSOの質問/回答の議論を超えていることに依存しています。 – GhostCat