Tag*_*eev 14 java parallel-processing java-8 java-stream
假设我有两个int[]数组input1和input2.我想从第一个中取正数,从第二个中取出不同的数字,将它们合并在一起,排序并存储到结果数组中.这可以使用流执行:
int[] result = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).distinct()).sorted().toArray();
Run Code Online (Sandbox Code Playgroud)
我想加快任务,所以我考虑使流并行.通常这只意味着我可以.parallel()在流构造和终端操作之间插入任何地方,结果将是相同的.IntDream.concat的JavaDoc 表示如果任何输入流是并行的,则生成的流将是并行的.所以,我认为做parallel()任何input1流或input2流或级联的流将产生相同的结果.
实际上我错了:如果我添加.parallel()到结果流,似乎输入流保持顺序.此外,我可以将输入流(它们中的任何一个或两者)标记为.parallel(),然后将结果流转换为.sequential(),但输入保持平行.所以实际上有8种可能性:input1,input2和连接流都可以是并行的:
int[] sss = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).distinct()).sorted().toArray();
int[] ssp = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).distinct()).parallel().sorted().toArray();
int[] sps = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).parallel().distinct()).sequential().sorted().toArray();
int[] spp = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).parallel().distinct()).sorted().toArray();
int[] pss = IntStream.concat(Arrays.stream(input1).parallel().filter(x -> x > 0),
Arrays.stream(input2).distinct()).sequential().sorted().toArray();
int[] psp = IntStream.concat(Arrays.stream(input1).parallel().filter(x -> x > 0),
Arrays.stream(input2).distinct()).sorted().toArray();
int[] pps = IntStream.concat(Arrays.stream(input1).parallel().filter(x -> x > 0),
Arrays.stream(input2).parallel().distinct()).sequential().sorted().toArray();
int[] ppp = IntStream.concat(Arrays.stream(input1).parallel().filter(x -> x > 0),
Arrays.stream(input2).parallel().distinct()).sorted().toArray();
Run Code Online (Sandbox Code Playgroud)
我针对不同的输入大小对所有版本进行了基准测试(在Core i5 4xCPU,Win7上使用JDK 8u45 64位),并且针对每种情况得到了不同的结果:
Benchmark (n) Mode Cnt Score Error Units
ConcatTest.SSS 100 avgt 20 7.094 ± 0.069 us/op
ConcatTest.SSS 10000 avgt 20 1542.820 ± 22.194 us/op
ConcatTest.SSS 1000000 avgt 20 350173.723 ± 7140.406 us/op
ConcatTest.SSP 100 avgt 20 6.176 ± 0.043 us/op
ConcatTest.SSP 10000 avgt 20 907.855 ± 8.448 us/op
ConcatTest.SSP 1000000 avgt 20 264193.679 ± 6744.169 us/op
ConcatTest.SPS 100 avgt 20 16.548 ± 0.175 us/op
ConcatTest.SPS 10000 avgt 20 1831.569 ± 13.582 us/op
ConcatTest.SPS 1000000 avgt 20 500736.204 ± 37932.197 us/op
ConcatTest.SPP 100 avgt 20 23.871 ± 0.285 us/op
ConcatTest.SPP 10000 avgt 20 1141.273 ± 9.310 us/op
ConcatTest.SPP 1000000 avgt 20 400582.847 ± 27330.492 us/op
ConcatTest.PSS 100 avgt 20 7.162 ± 0.241 us/op
ConcatTest.PSS 10000 avgt 20 1593.332 ± 7.961 us/op
ConcatTest.PSS 1000000 avgt 20 383920.286 ± 6650.890 us/op
ConcatTest.PSP 100 avgt 20 9.877 ± 0.382 us/op
ConcatTest.PSP 10000 avgt 20 883.639 ± 13.596 us/op
ConcatTest.PSP 1000000 avgt 20 257921.422 ± 7649.434 us/op
ConcatTest.PPS 100 avgt 20 16.412 ± 0.129 us/op
ConcatTest.PPS 10000 avgt 20 1816.782 ± 10.875 us/op
ConcatTest.PPS 1000000 avgt 20 476311.713 ± 19154.558 us/op
ConcatTest.PPP 100 avgt 20 23.078 ± 0.622 us/op
ConcatTest.PPP 10000 avgt 20 1128.889 ± 7.964 us/op
ConcatTest.PPP 1000000 avgt 20 393699.222 ± 56397.445 us/op
Run Code Online (Sandbox Code Playgroud)
从这些结果我只能得出结论,distinct()步骤的并行化降低了整体性能(至少在我的测试中).
所以我有以下问题:
parallel().这是真的?规范精确地描述了你得到的东西 - 当你考虑到这一点时,与其他操作不同,我们不是在讨论单个管道而是三个不同Stream的管道,它们保持其属性独立于其他管道.
规范说:" 如果任何一个输入流是并行的,那么得到的流是并行的."这就是你得到的; 如果任一输入流是并行的,则生成的流是并行的(但您可以在之后将其转换为顺序).但是将结果流更改为并行或顺序不会改变输入流的性质,也不会将并行和顺序流输入concat.
关于性能影响,请参阅文档"流操作和流水线":
中间操作进一步分为无状态操作和有状态操作.无状态操作(例如
filter和)map在处理新元素时不保留先前看到的元素的状态 - 每个元素都可以独立于其他元素的操作进行处理.状态操作(例如distinct和sorted)可以在处理新元素时包含先前看到的元素的状态.有状态操作可能需要在生成结果之前处理整个输入.例如,在查看流的所有元素之前,不能通过对流进行排序来产生任何结果.因此,在并行计算下,某些包含有状态中间操作的管道可能需要对数据进行多次传递,或者可能需要缓冲重要数据.仅包含无状态中间操作的管道可以在一次通过中处理,无论是顺序还是并行,具有最小的数据缓冲.
您已选择了两个命名的有状态操作并将它们组合在一起.因此,.sorted()结果流的操作需要在整个内容开始排序之前缓冲整个内容,这意味着distinct操作的完成.由于线程必须同步已经看到的值,因此明显难以并行操作.
所以要回答你的第一个问题,它不是关于,concat而是简单地说distinct并没有从并行执行中获益.
这也使您的第二个问题变得过时,因为您在两个连接流中执行完全不同的操作,因此您无法对预连接的集合/数组执行相同操作.连接数组并distinct在结果数组上运行不太可能产生更好的结果.
关于你的第三个问题,flatMap关于parallel溪流的行为可能会引起惊喜......
| 归档时间: |
|
| 查看次数: |
1000 次 |
| 最近记录: |