When calculating a ^ b, why parallel is not working, but parallelStream can

I want to calculate a ^ b, for example. 2 ^ 30,

public long pow(final int a, final int  b)

I used this method first

return LongStream.range(0, b).reduce(1, (acc, x) -> a * acc); // 1073741824

Got the correct result. Then I want to calculate it in parallel, so naturally I changed it to

return LongStream.range(0, b).parallel().reduce(1, (acc, x) -> a * acc); // 32

but in this case the result is equal 32. Why?

So, to support the parallel, I changed it again

return Collections.nCopies(b,a).parallelStream().reduce(1, (acc, x) -> acc * x); // 1073741824

in this case it works.

So what happened to the parallelimage?

+3
source share
2 answers

reduce , . (acc, x) -> a * acc , , .

, (x op y) op z == x op (y op z) x, y z. (x op y) op z = x*a^2 x op (y op z) = x * a.

, , , . , 1 op x == x x. 1 op x == a.

:

LongStream.range(0, b).map(x -> a).reduce(1, (u, v) -> u * v);

, .

+5

, 32.

return LongStream.range(0, b).parallel().reduce(1, (acc, x) -> a * acc); // 32

   // java.util.stream.ReduceOps.ReduceTask#onCompletion
    @Override
    public void onCompletion(CountedCompleter<?> caller) {
        if (!isLeaf()) {
            S leftResult = leftChild.getLocalResult();
            leftResult.combine(rightChild.getLocalResult()); // here to combine
            setLocalResult(leftResult);
        }

    }

    // java.util.stream.TerminalOp
    @Override
    public void combine(ReducingSink other) {
        accept(other.state);
    }
    @Override
    public void accept(long t) {
        state = operator.applyAsLong(state, t); // (acc, x)
    }

x lambda

(acc, x) -> a * acc;

leftResult.combine(2); 

-, .

+1

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


All Articles