今更ながらFork/Joinフレームワークを使ってみた
[java][paiza]PaizaのAランクに挑戦しました。
気が乗ったときに行っているPaizaですが、
先日Aランクに挑戦しました、が
大規模データのテストケースで実行タイムオーバーになってしまったこと。
そういえば今まで大規模データを扱って、並列処理とかしたことがなかったなぁ、ってことで
簡単なFork/Joinフレームワークで並列処理を試してみた。
Fork/Joinフレームワークを使ってみる。
1からintの最大値-1までを計算するよう、以下の処理を作成。
まずは素直に与えられたパラメータ(From~To)を順に計算していく単純なプログラム。
与えるパラメータは以下の通り
rangeFrom : 1
rangeTo : intの最大値-1 (2147483646)
SimpleCalculate
package fork_join; public class SimpleCalculate { public long calculate(int rangeFrom, int rangeTo) { long sum = 0; for (int i = rangeFrom; i <= rangeTo; i++) { sum += i; } return sum; } }
続いて、計算対象が一定数を超える場合にFork/Joinによる並列処理を行う。
ForkCalculate
package fork_join; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask; public class ForkCalculate { public long calculate(int rangeFrom, int rangeTo){ ForkJoinPool pool = new ForkJoinPool(); MyTask task = new ForkCalculate().new MyTask(rangeFrom, rangeTo); pool.execute(task); return task.join(); } public class MyTask extends RecursiveTask<Long>{ final int start; final int end; final static int FORK_LIMIT = 100000; //処理分割の閾値(計算対象件数がこれを上回る場合処理分割) public MyTask(int start, int end) { this.start = start; this.end = end; } @Override protected Long compute() { int calcNum = end - start; int half = calcNum / 2; //計算対象が閾値を上回る場合、処理を分割 if(calcNum > FORK_LIMIT){ MyTask task1 = new MyTask(start, start+half); task1.fork(); MyTask task2 = new MyTask(start + half+1, end); return task2.compute() + task1.join(); } //閾値を下回る場合は、そのまま計算 else{ long sum = 0; for(int i = start; i <= end; i++){ sum += i; } return sum; } } } }
ちなみに実行結果は...
メソッド名 | 処理時間 |
---|---|
SimpleCalculate#calculate | 1764.6537ms |
ForkCalculate#calculate | 676.5478ms |
一応実行速度てきには1/3近くにはなったが、
それでも0.7秒程かかってしまっている。
Fork/Joinの使い方が誤っているのか、
それとも他に正しいやり方があるのか。。。
とりあえず、現状ここまでとしておこう。