在我的机器上,下面的程序打印:
OptionalLong[134043]
PARALLEL took 127869 ms
OptionalLong[134043]
SERIAL took 60594 ms
我不清楚为什么串行执行程序比并行执行程序更快。我在一个相对安静的 8gb
盒子上给了两个程序 -Xms2g -Xmx2g
。有人可以澄清发生了什么吗?
import java.util.stream.LongStream;
import java.util.stream.LongStream.Builder;
public class Problem47 {
public static void main(String[] args) {
final long startTime = System.currentTimeMillis();
System.out.println(LongStream.iterate(1, n -> n + 1).parallel().limit(1000000).filter(n -> fourConsecutives(n)).findFirst());
final long endTime = System.currentTimeMillis();
System.out.println(" PARALLEL took " +(endTime - startTime) + " ms");
final long startTime2 = System.currentTimeMillis();
System.out.println(LongStream.iterate(1, n -> n + 1).limit(1000000).filter(n -> fourConsecutives(n)).findFirst());
final long endTime2 = System.currentTimeMillis();
System.out.println(" SERIAL took " +(endTime2 - startTime2) + " ms");
}
static boolean fourConsecutives(final long n) {
return distinctPrimeFactors(n).count() == 4 &&
distinctPrimeFactors(n + 1).count() == 4 &&
distinctPrimeFactors(n + 2).count() == 4 &&
distinctPrimeFactors(n + 3).count() == 4;
}
static LongStream distinctPrimeFactors(long number) {
final Builder builder = LongStream.builder();
final long limit = number / 2;
long n = number;
for (long i = 2; i <= limit; i++) {
while (n % i == 0) {
builder.accept(i);
n /= i;
}
}
return builder.build().distinct();
}
}
最佳答案
我们可以让并行执行变得更容易,但我们不一定能让并行变得容易。
您代码中的罪魁祸首是限制+并行的组合。实现 limit() 对于顺序流来说是微不足道的,但对于并行流来说相当昂贵。这是因为限制操作的定义与流的遇到顺序相关联。具有 limit() 的流在并行时通常比在顺序中慢,除非每个元素完成的计算非常高。
您对流源的选择也会限制并行性。使用 iterate(0, n->n+1)
可以得到正整数,但是 iterate
基本上是顺序的;在计算出第 (n-1) 个元素之前,您无法计算第 n 个元素。所以当我们尝试拆分这个流时,我们最终会拆分(首先,休息)。尝试使用 range(0,k)
代替;这拆分得更好,通过随机访问整齐地分成两半。
关于Java 8 流串行与并行性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24027247/