【发布时间】:2016-12-29 13:02:56
【问题描述】:
我正在玩无限流,并制作了这个程序用于基准测试。基本上,您提供的数字越大,完成的速度就越快。然而,我惊讶地发现,与顺序流相比,使用并行流导致性能呈指数级下降。直觉上,人们会期望在多线程环境中更快地生成和评估无限的随机数流,但情况似乎并非如此。这是为什么呢?
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");
【问题讨论】:
-
并行化小任务总是会变慢。多线程有足够的开销,任务需要证明成本是合理的,否则您将看不到任何收益。此外,1 次测试毫无意义。至少,将其循环并取平均值。
-
@Carcigenicate 除此之外,我相信 Math.random() 会减慢速度 :-) 如果有兴趣,请查看我的答案。
-
你知道有一个内置的
Random.ints()流来获取随机数流吗? -
您的示例遇到了并行化不佳的几个风险因素。首先,
findFirst()与流的遇到顺序相关联,这阻碍了库的并行化能力(您应该改用findAny()。)其次,您只是没有为每个元素做太多工作,这意味着创建、调度和协调任务的开销可能会超过实际工作。每个元素的工作也没有表现出太多的局部性。所以并行加速的条件并不真正存在。 (此外,您的基准方法可能会给出毫无意义的数字。) -
@Holger 是的,
generate()的结果是无序的。但是并行性和遇到顺序之间的关系是微妙的,并且经常是不能很好地并行化的原因。所以我觉得值得提出这种联系,即使它不适用于这个特定代码sn-p。
标签: java java-8 java-stream