Выполнение длительной задачи с использованием fork-join занимает почти то же время, что и однопоточная программа - PullRequest
0 голосов
/ 25 декабря 2018

Я пытаюсь преобразовать каждый элемент массива длиной 10,00,00,000.Мой первый подход заключается в использовании одного потока в простом основном методе.Мой следующий подход заключается в использовании java-структуры fork-join путем деления массива на 10 000 000.Но общее время, необходимое для преобразования массива, практически одинаково в обоих подходах.

public class SerialComputation {

    public static void main(String[] args) {
        Integer[] array = new Integer[100000000];

        for (int i = 0; i < array.length; i++) {
            array[i] = new Random().nextInt(100);
        }
        System.out.println("First 10 elements before transformation:");
        Arrays.asList(array).stream().limit(10).forEach(d -> System.out.print(d + " "));
        System.out.println();

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < array.length; i++) {
            array[i] *= 2;
        }
        long endTime = System.currentTimeMillis();
        System.out.println("First 10 elements after transformation:");
        Arrays.asList(array).stream().limit(10).forEach(d -> System.out.print(d + " "));
        System.out.println();
        System.out.println("Total time taken: " + (endTime - startTime));
    }   
}


class ParallelComputation {
    public static void main(String[] args) {
        Integer[] array = new Integer[100000000];

        for (int i = 0; i < array.length; i++) {
            array[i] = new Random().nextInt(100);
        }
        System.out.println("First 10 elements before transformation:");
        Arrays.asList(array).stream().limit(10).forEach(d -> System.out.print(d + " "));
        System.out.println();

        ForkJoinTask<?> forkJoinTask = new TransformTask(0, array.length, array);
        ForkJoinPool pool = new ForkJoinPool();
        long startTime = System.currentTimeMillis();
        pool.invoke(forkJoinTask);
        long endTime = System.currentTimeMillis();

        System.out.println("First 10 elements after transformation:");
        Arrays.asList(array).stream().limit(10).forEach(d -> System.out.print(d + " "));
        System.out.println("Total time taken: " + (endTime - startTime));
    }
}

class TransformTask extends RecursiveAction {

    private static final long serialVersionUID = 1L;
    private int start;
    private int end;
    private Integer[] array;

    public TransformTask(int start, int end, Integer[] array) {
        this.start = start;
        this.end = end;
        this.array = array;
    }

    @Override
    protected void compute() {

        if (end - start <= 1000000) {
            for (int i = start; i < end; i++) {
                array[i] *= 2;
            }
        } else {
            int middle = start + ((end - start) / 2);
            System.out.println("start:" + start + "middle:" + middle + "end:" + end);
            invokeAll(new TransformTask(start, middle, array), new TransformTask(middle, end, array));
        }  
    }  
}

Я ожидаю, что ParallelComputation вычислит результат намного быстрее, чем SerialComputation.Но оба делают работу почти одновременно.Я использую машину с процессором Intel Core i7 с Windows 10.

1 Ответ

0 голосов
/ 25 декабря 2018

Я не могу комментировать реализацию TransformTask, но это:

static long parallelStreamComputation() {

    Integer[] array = new Integer[100000000];

    for (int i = 0; i < array.length; i++) {
        array[i] = new Random().nextInt(100);
    }

    long startTime = System.currentTimeMillis();
    Arrays.stream(array).parallel().mapToInt( i -> i*2).toArray();
    long endTime = System.currentTimeMillis();
    return endTime-startTime;
}

Было измерено примерно в 10 раз быстрее.

...