Why is parallel flow slower?

I played with endless streams and made this benchmarking program. Basically, the larger the number you provide, the faster it will end. However, I was amazed to find that using a parellel stream resulted in exponentially worse performance compared to a sequential stream. Intuitively, one would expect an infinite stream of random numbers to be generated and evaluated much faster in a multi-threaded environment, but this does not seem to be the case. Why is this?

    final int target = Integer.parseInt(args[0]);
    if (target <= 0) {
        System.err.println("Target must be between 1 and 2147483647");
        return;
    }

    final long startTime, endTime;
    startTime = System.currentTimeMillis();

    System.out.println(
        IntStream.generate(() -> new Double(Math.random()*2147483647).intValue())
        //.parallel()
        .filter(i -> i <= target)
        .findFirst()
        .getAsInt()
    );

    endTime = System.currentTimeMillis();
    System.out.println("Execution time: "+(endTime-startTime)+" ms");
+4
source share
3 answers

, , . 60x , . API, :-). :

Math.random()

java.util.Random. Random :

java.util.Random . java.util.Random , , . ThreadLocalRandom .

, , , . ThreadLocalRandom ( ), . .

+6

. , , .

, - , . , , 100 ( ). , , .

.

long start = System.nanoTime();
int value = (int) (Math.random() * (target+1L));
long time = System.nanoTime() - value;
// don't time IO as it is sooo much slower
System.out.println(value);

. , . 2-5 .

0

Following the advice of the various answers, I think I fixed them. I'm not sure what the exact bottleneck was, but on the i5-4590T the parallel version with the following code is faster than the serial version. For brevity, I have included only the relevant parts (refactored) of the code:

static IntStream getComputation() {
    return IntStream
            .generate(() -> ThreadLocalRandom.current().nextInt(2147483647));
}

static void computeSequential(int target) {
    for (int loop = 0; loop < target; loop++) {
        final int result = getComputation()
                    .filter(i -> i <= target)
                    .findAny()
                    .getAsInt();
        System.out.println(result);
    }
}

static void computeParallel(int target) {
     IntStream.range(0, target)
                .parallel()
                .forEach(loop -> {
                    final int result = getComputation()
                        .parallel()
                        .filter(i -> i <= target)
                        .findAny()
                        .getAsInt();
                    System.out.println(result);
                });
}

EDIT: I should also note that I put everything in a loop to get more work time.

0
source

Source: https://habr.com/ru/post/1665233/


All Articles