Fork join没有提供更好的性能

时间:2017-02-08 14:20:47

标签: java java-8 java-7 fork-join

我正在尝试检查以下代码的性能,但每次进行顺序操作时都会提供比fork join更好的性能。

问题我想找到最大整数:

public class GetMaxIntegerProblem {

    private final int[] intArray;
    private int start;
    private int end;
    private int size;

    public GetMaxIntegerProblem(int[] intArray, int start, int end) {
        super();
        this.intArray = intArray;
        this.start = start;
        this.end = end;
        size = end - start;
    }

    public int getMaxSequentially() {
        int max = Integer.MIN_VALUE;
        for (int i = start; i < end; i++) {
            int n = intArray[i];
            max = n > max ? n : max;
        }
        return max;
    }

    public int getSize() {
        return size;
    }


    public GetMaxIntegerProblem getMaxIntegerSubProblem(int subStart, int subEnd) {
        return new GetMaxIntegerProblem(this.intArray, start + subStart, start + subEnd);
    }
}

我对fork join的操作:

import java.util.concurrent.RecursiveAction;


public class GetMaxIntegerAction extends RecursiveAction {
    private final int threshold;
    private final GetMaxIntegerProblem problem;
    private int result;

    public GetMaxIntegerAction(int threshold, GetMaxIntegerProblem problem) {
        super();
        this.threshold = threshold;
        this.problem = problem;
    }

    @Override
    protected void compute() {
        if (problem.getSize() < threshold) {
            result = problem.getMaxSequentially();
        } else {
            int midPoint = problem.getSize() / 2;
            GetMaxIntegerProblem leftProblem = problem.getMaxIntegerSubProblem(0, midPoint);
            GetMaxIntegerProblem rightProblem = problem.getMaxIntegerSubProblem(midPoint + 1, problem.getSize());
            GetMaxIntegerAction left = new GetMaxIntegerAction(threshold, leftProblem);
            GetMaxIntegerAction right = new GetMaxIntegerAction(threshold, rightProblem);
            invokeAll(left, right);
            result = Math.max(left.result, right.result);
        }

    }

}

我的主要测试程序:

import java.util.Random;
import java.util.concurrent.ForkJoinPool;

public class GetMaxIntegerMain {

    public GetMaxIntegerMain() {
        // TODO Auto-generated constructor stub
    }

    private Random random = new Random();

    private void fillRandomArray(int[] randomArray) {
        for (int i = 0; i < randomArray.length; i++) {
            randomArray[i] = random.nextInt(10000);
        }
    }


    /**
     * @param args
     */
    public static void main(String[] args) {
        GetMaxIntegerMain mainexcution=new GetMaxIntegerMain();
        int arrayLength = 10_00_000;
        int array[] = new int[arrayLength];
        mainexcution.fillRandomArray(array);
        GetMaxIntegerProblem problem=new GetMaxIntegerProblem(array, 0, array.length);
         //No. of times sequential & 
        //Parallel operation should be performed to warm up HotSpot JVM
        final int iterations = 10;
        long start = System.nanoTime();
        int maxSeq=0;
        for (int i = 0; i < iterations; i++) {
            maxSeq=problem.getMaxSequentially();
         }
        long endSeq=System.nanoTime();
        long totalSeq=endSeq-start;
        System.out.println(" time for seq "+(endSeq-start));

        System.out.println("Number of processor available: " + Runtime.getRuntime().availableProcessors());
        //Default parallelism level = Runtime.getRuntime().availableProcessors()
        int threads=Runtime.getRuntime().availableProcessors();
        ForkJoinPool fjpool = new ForkJoinPool(64);

        long startParallel = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            GetMaxIntegerAction action=new GetMaxIntegerAction(5000, problem);  
            fjpool.invoke(action);
        }
        long endParallel = System.nanoTime();
        long totalP=endParallel-startParallel;
        System.out.println(" time for parallel "+totalP);
        double speedup=(double)(totalSeq/totalP);
        System.out.println(" speedup "+speedup);
        System.out.println("Number of steals: " + fjpool.getStealCount() + "\n");


    }

}

每次运行此代码时,我都会获得forkjoin特定代码需要400%的时间。我尝试了各种阈值组合,但我没有取得成功。

我在Windows 10 Intel Core i3处理器3.3 GHz 64位上运行此代码

如果有人可以就这个问题提供一些指示,那将会很有帮助。

1 个答案:

答案 0 :(得分:0)

在使用fork join时,很多情况下你不应该期望更好的性能,因为分叉和连接的开销可能会变得非常大。例如,请参阅此演讲(主要是下半部分)https://www.youtube.com/watch?v=2nup6Oizpcw