Как использовать ForkJoinPool для использования нескольких ядер в java? - PullRequest
0 голосов
/ 09 февраля 2020

Итак, я пытаюсь понять, как работает ForkJoinPool. Я пытаюсь добиться лучшей производительности, используя это для большого массива около 2 миллионов элементов, а затем добавляю их взаимно. Я понимаю, что ForkJoinPool.commpnPool (). Invoke (task); Вызывает compute (), который разветвляет задачу в двух задачах, если она не меньше, а затем вычисляет и затем присоединяет их. Пока что мы используем два ядра.

Но если я хочу выполнить это на нескольких ядрах, как мне это сделать и добиться в 4 раза лучшей производительности, чем при обычном однопоточном запуске? Ниже мой код для ForkJoinPool () по умолчанию:

@Override
        protected void compute() {
            // TODO
            if (endIndexExclusive - startIndexInclusive <= seq_count) {
                for (int i = startIndexInclusive; i < endIndexExclusive; i++)
                    value += 1 / input[i];
            } else {

                ReciprocalArraySumTask left = new ReciprocalArraySumTask(startIndexInclusive,
                        (endIndexExclusive + startIndexInclusive) / 2, input);
                ReciprocalArraySumTask right = new ReciprocalArraySumTask((endIndexExclusive + startIndexInclusive) / 2,
                        endIndexExclusive, input);
                left.fork();
                right.compute();
                left.join();
                value = left.value + right.value;
            }
        }
    }


protected static double parArraySum(final double[] input) {
        assert input.length % 2 == 0;

        double sum = 0;

        // Compute sum of reciprocals of array elements
        ReciprocalArraySumTask task = new ReciprocalArraySumTask(0, input.length, input);
        ForkJoinPool.commonPool().invoke(task);
        return task.getValue();
    }

//Here I am trying to achieve with 4 cores
protected static double parManyTaskArraySum(final double[] input,
                                                final int numTasks) {
        double sum = 0;
        System.out.println("Total tasks = " + numTasks);
        System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", String.valueOf(numTasks));
        // Compute sum of reciprocals of array elements
        int chunkSize = ReciprocalArraySum.getChunkSize(numTasks, input.length);
        System.out.println("Chunk size = " + chunkSize);
        ReciprocalArraySumTask task = new ReciprocalArraySumTask(0, input.length, input);
        ForkJoinPool pool = new ForkJoinPool();
//        pool.
        ForkJoinPool.commonPool().invoke(task);
        return task.getValue();
    }

1 Ответ

1 голос
/ 09 февраля 2020

Вы хотите использовать 4 ядра, но вы даете работу, для которой потребуется только два ядра. В следующем примере методы getChunkStartInclusive и getChunkEndExclusive дают диапазон для начального и конечного индексов каждого чанка. Я полагаю, что следующий код может решить вашу проблему и дать вам некоторую идею реализации.

protected static double parManyTaskArraySum(final double[] input,
        final int numTasks) {
    double sum = 0;
    System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", String.valueOf(numTasks));
    List<ReciprocalArraySumTask> ts = new ArrayList<ReciprocalArraySumTask>(numTasks);

    int i;
    for (i = 0; i < numTasks - 1 ; i++) {
        ts.add(new ReciprocalArraySumTask(getChunkStartInclusive(i,numTasks,input.length),getChunkEndExclusive(i,numTasks,input.length),input));
        ts.get(i).fork();
    }
    ts.add( new ReciprocalArraySumTask(getChunkStartInclusive(i, numTasks, input.length), getChunkEndExclusive(i, numTasks, input.length), input));
    ts.get(i).compute();

    for (int j = 0; j < numTasks - 1; j++) {
        ts.get(j).join();
    }

    for (int j = 0; j < numTasks; j++) {
        sum += ts.get(j).getValue();
    }
    return sum;
}
...