2016-05-13 10 views
1

フォークジョインの仕組みの詳細を理解しようとしています。フォークジョイン:すべてのサブタスクをフォークするか、現在のスレッドに1つ残す

ウィキペディアには、左半分がフォークされ、右半分が現在のスレッドによって処理されるmerge-sortの例があります。

mergesort(A, lo, hi): 
    if lo < hi:      // at least one element of input 
     mid = ⌊(hi - lo)/2⌋ 
     fork mergesort(A, lo, mid) // process (potentially) in parallel with main task 
     mergesort(A, mid, hi)  // main task handles second recursion 
     join 
     merge(A, lo, mid, hi) 

私はすべてのサブタスクフォークを見て、その結果を待つましたが、ほとんどのJavaの例:スレッドではなく、有益な何かをするので、

for (Document document : folder.getDocuments()) { 
    DocumentSearchTask task = new DocumentSearchTask(document, searchedWord); 
    forks.add(task); 
    task.fork(); 
} 
for (RecursiveTask<Long> task : forks) { 
    count = count + task.join(); 
} 
return count; 

は、ウィキペディアの例は、私に多くの意味がありますサブタスクをブロックして待機しています。

一方、すべてのタスクをフォークすると、再帰を回避してStackOverflowErrorを取得できません。

タスクを分割する好ましい方法とその理由は何ですか?

+0

あなたのご質問は何ですか? –

+0

更新、ありがとうございました – damluar

答えて

1

私は、すべてのサブタスクを同じ方法でフォークして処理することをお勧めします。ここではいくつかの理由があります:Javaで

  1. ForkJoinPoolExecutorServiceを実装しています。 ExecutorServiceのすべてのメソッドは、の非同期です。その理由は、バックグラウンドで非同期にいくつかの計算を開始することができますが、メインスレッドは計算の結果が必要になるまで他の有用な作業を行うことができます。より多くの非同期タスクが生成されます。

  2. 理由は簡単です。コードは、タスクに特定の非対称性を導入するのではなく、すべてのサブ問題を同じ方法で処理すると、より洗練されたものになります。

  3. メインスレッドでの演算の一部をフォークしたり、実行しても実際には利点はありません。すべてのタスクをフォークして結合を待つと、メインスレッドは待機状態になり、ほとんどリソースを消費せず、ワーカースレッドはプロセッサを完全に利用できるようになります。

厳しい選択ではなく、もっと重要なことです。上記の潜在的なスタックオーバーフローを除いて、機能的に同等です。

私はウィキペディアの作者に話すことはできませんが、彼女は説明のために単純なものを保つことを試みていたか、フォーク/ジョインがJavaのように単純ではない抽象的な言語のバックグラウンドを持っていたと思います。


更新:ブロックに関してはあまりにも多くのスレッドが、これはForkJoinPoolと心配ではありません。 hereで説明したように、ForkJoinPoolについての特別なことは、実際にはjoinコールの中で仕事が盗まれるということです。

+0

私の懸念は、待機しているスレッドの数が多いことです。しかし、Doug Leaの論文では、「ワーカースレッドが結合操作に遭遇すると、ターゲットタスクが(isDone経由で)完了したことがわかるまで、他のタスクを処理します。だから、私はすべてのサブタスクをフォークするのがより一貫性のある方法だと思う。 – damluar

+0

はい、興味のあるリンクで回答を更新しました。私は、両方のバージョンの 'join'がForkJoinPool joinであることを暗黙的に仮定しました。他の同期は本当にブロックされますが、ForkJoinPoolだけが特別です。 – Mifeet

関連する問題