当前位置: 首页 > 面试题库 >

为什么并行流较慢?

尉迟哲瀚
2023-03-14
问题内容

我在玩无限的流,并制作了该程序进行基准测试。基本上,您提供的数字越大,完成的速度就越快。但是,令我惊讶的是,与顺序流相比,使用并行流导致的性能成倍下降。凭直觉,人们期望在多线程环境中生成和评估无限快的随机数流,但是事实并非如此。为什么是这样?

    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");

问题答案:

我完全同意其他评论和答案,但实际上,如果目标很低,您的测试会表现得很奇怪。在我的普通笔记本电脑上,当给出非常低的目标时,并行版本平均要慢60倍。这种极端的差异无法用流API中的并行化开销来解释,所以我也很惊讶:-)。IMO的罪魁祸首就在这里:

Math.random()

在内部,此调用依赖于的全局实例java.util.Random。在Random的文档中这样写:

java.util.Random的实例是线程安全的。但是,跨线程并发使用同一java.util.Random实例可能会引起争用并因此导致性能下降。考虑在多线程设计中改用ThreadLocalRandom。

因此,我认为与顺序执行相比,并行执行的真正糟糕的性能是由线程竞争以随机方式而不是其他任何开销来解释的。如果ThreadLocalRandom改用(按照文档中的建议),则性能差异不会那么明显。另一种选择是实施更高级的号码供应商。



 类似资料:
  • 考虑到我有2个CPU核心的事实,并行版本不是应该更快吗?有人能给我一个提示为什么并行版本比较慢吗?

  • 问题内容: 我正在使用Java 8的流,无法理解我得到的性能结果。我有2个核心CPU(Intel i73520M),Windows 8 x64和64位Java 8 Update5。我正在对String的流/并行流进行简单映射,发现并行版本要慢一些。 考虑到我有2个CPU内核,并行版本是否应该更快?有人可以提示我为什么并行版本比较慢吗? 问题答案: 确实有几个并行发生的问题。 首先是并行解决问题总是

  • 我正在使用parallelStream并行上传一些文件,有些是大文件,有些是小文件。我注意到并不是所有的工人都被使用。 一开始一切都运行良好,所有线程都被使用(我将并行选项设置为16)。然后在某一点上(一旦它到达更大的文件),它只使用一个线程 简化代码: uploaderPool是一个ArrayBlockingQueue。日志: 似乎所有的工作(列表中的项目)都分布在16个线程中,委托给一个线程的

  • 问题内容: 为什么总是以随机顺序打印数字,而始终从原始顺序收集元素,即使是从并行流中呢? 输出: 问题答案: 这里有两种不同的“排序”,使讨论变得混乱。 一种是 遇到顺序 ,该 顺序 在流文档中定义。考虑这一点的一种好方法是源集合中元素的 空间 顺序或 从左到右的 顺序。如果源是,请考虑将较早的元素放在较后的元素的左侧。 还有文档中未定义的 处理 或 时间 顺序,但这是由不同线程处理元素的时间顺序

  • 我正在使用一个非常著名的圆环近似值的例子。我选取单位正方形((0,0)到(1,1))中的随机点,看看有多少随机点落在单位圆的区域内。分数应为?/4的值。 结果: