fork/joinパラレルプログラミング
2006 ワード
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
public class MaxValue {
private static final int RANGE_LENGTH = 200;
private final ForkJoinPool forkJoinPool = new ForkJoinPool();
private static class MaxValueTask extends RecursiveTask<Long>{
private final long[] array;
private final int start;
private final int end;
public MaxValueTask(long[] array,int start,int end) {
// TODO Auto-generated constructor stub
this.array=array;
this.start=start;
this.end=end;
}
@Override
protected Long compute() {
long max=Long.MIN_VALUE;
if(end-start <= RANGE_LENGTH){
for(int i=start;i<end;i++){
if(array[i]>max){
max=array[i];
}
}
}else{
int mid=(start+end)/2;
MaxValueTask lowTask = new MaxValueTask(array,start,mid);
MaxValueTask highTask = new MaxValueTask(array, mid, end);
lowTask.fork();
highTask.fork();
max = Math.max(max, lowTask.join());
max=Math.max(max, highTask.join());
}
return max;
}
}
public void calculate(long[] array){
MaxValueTask task = new MaxValueTask(array, 0, array.length);
Long result = forkJoinPool.invoke(task);
System.out.println(result);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
long[] array ={2,3,5,44,1,4,5};
new MaxValue().calculate(array);
}
}
目的は、下位プラットフォーム上のマルチコアCPUとマルチプロセッサをよりよく利用して処理することであり、問題を解決するために、通常、divide and conquerアルゴリズムまたはmap/reduceアルゴリズムのmapおよびreduce操作を使用する.
一般的なスレッドプール実装に比べてfork/joinフレームワークの利点は、含まれるタスクの処理方法に現れます.
一般的なスレッドプールで、スレッドが実行中のタスクが何らかの理由で実行できない場合、スレッドは待機状態になります.
fork/joinフレームワーク実装では、あるサブ問題が別のサブ問題の完了を待つために実行を継続できない場合、そのサブ問題を処理するスレッドは、他の未実行のサブ問題をアクティブに探して実行します(待機時間を減らし、パフォーマンスを向上させます).
注意:fork/joinフレームワークを効率的に動作させるためには、各サブ問題の実装でsynchronizedキーワードや他の方法で同期することを避けるべきであり、ブロックI/O操作や共有変数に過度にアクセスするべきではない.
理想的には、各サブ問題の実装は、CPU関連の計算のみを行い、各問題の内部オブジェクトのみを使用するべきである.唯一の同期は、サブ問題と作成された問題の間でのみ発生する必要があります.