Java 8 流串行与并行性能

标签 java performance java-8 java-stream

在我的机器上,下面的程序打印:

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/

相关文章:

c++ - htop 和 OpenMP 线程

java - 如何在 Java 8 中的两个流之间进行搜索

java - 如何获取 Iterable<Student> 集合中事件日期字段中事件日期最高的对象的唯一列表

java - 为什么异常完成前调用get()会等待异常执行?

java - 关于 JDBC 资源和 JDBC 连接池 Glassfish 的一些混淆

Java/Android Studio - 协变返回类型 - "subclass"中的方法与 "baseclass": attempting to use incompatible return type 中的方法冲突

java - 静态和非静态方法的同步块(synchronized block)

java - 哪个是最优的?

java - IBM 移动第一 : Invoking adapter from Java- InvokeProcedure

swift - 找到一个数的所有因子的最有效方法?