Kay*_*ayV 6 parallel-processing java-8 java-stream
我正在使用Stream并行处理,并了解如果我使用平面阵列流,它会得到非常快速的处理.但如果我使用ArrayList,那么处理速度会慢一些.但是,如果我使用LinkedList或使用一些二进制树,处理速度会更慢.
所有听起来更像是流的可分割性,处理速度越快.这意味着阵列和数组列表在并行流的情况下最有效.这是真的吗?如果是这样,ArrayList如果我们想并行处理流,我们总是使用或者Array吗?如果是这样,如何使用LinkedList和BlockingQueue并行流?
另一件事是选择的中间函数的状态.如果我执行像无状态操作filter(),map(),性能高,但如果执行像国家提供充分的操作distinct(),sorted(),limit(),skip(),它需要大量的时间.再次,并行流变慢.这是否意味着我们不应该在并行流中使用状态全中间函数?如果是这样,那么解决这个问题的方法是什么?
好吧,正如这个问题所讨论的,根本没有任何理由可以使用LinkedList.较高的迭代成本适用于所有操作,而不仅仅是并行流.
通常,拆分支持确实对并行性能有很大影响.首先,它是否具有真正的,希望廉价的分裂支持,而不是继承缓冲默认行为AbstractSpliterator,第二,分裂的平衡程度.
在这方面,没有理由为什么二叉树应该表现糟糕.树可以很容易地分成子树,如果树在开始时是平衡的,那么分裂也将是平衡的.当然,这要求实际Collection实现实现spliterator()返回合适Spliterator实现的default方法,而不是继承该方法.例如,TreeSet有一个专用的分裂器.仍然,迭代子树可能比迭代一个数组更昂贵,但这不是并行处理的属性,因为它也适用于顺序处理或一般的元素上的任何类型的迭代.
问题,如何使用LinkedList和BlockingQueue在并行流的情况下,是没有实际意义的.您根据应用程序的需要选择集合类型,如果您真的需要其中一个(在LinkedList难以想象的情况下),那么您可以使用它,并且它的并行流性能将低于ArrayList其显而易见的事实.不符合你的其他需求.没有一般的技巧可以更好地实现严重可拆分集合的并行流性能.如果有,它将成为图书馆的一部分.
有一些角落情况下JRE不提供最高的性能,这将在Java中9得到解决,比如String.chars(),Files.lines()或第三部分的默认spliterator RandomAccess ListS,但这些都不适用LinkedList,BlockingQueue或自定义二叉树的实现.
换句话说,如果您具有特定集合的特定用例,则可能需要改进,但没有任何技巧可以提高所有集合的所有任务的并行性能.
这是正确的,有状态的中间操作,比如distinct(),sorted(),limit(),skip()有平行流更高的成本和它们的文档甚至告诉这一点.所以我们可以给出一般建议来避免它们,特别是对于并行流,但是如果你不需要它们,那就没有用了,因为你没有使用它们.同样,没有一般的解决方法,因为如果有一个更好的替代方案,提供这些操作没有多大意义.
在我看来,这个问题还不错。
当然,array和 的ArrayList可分割性会比LinkedList某种类型的 a更好Tree。你可以看看他们Spliterators是如何说服你自己的。它们通常从一些元素(1024 个元素)开始batch size,然后逐渐增加。LinkedList这样做,Files.lines如果我没记错的话。所以是的,使用数组ArrayList将会有很好的并行化。
如果您想要对某些结构有更好的并行支持,例如LinkedList您可以编写自己的分裂器 - 我认为StreamEx这样做是为了Files.lines从较小的批量大小开始......顺便说一句,这是一个相关的问题。
另一件事是,当您使用有状态的中间操作时 - 您将有效地使above有状态的中间操作也成为有状态的......让我提供一个例子:
IntStream.of(1, 3, 5, 2, 6)
.filter(x -> {
System.out.println("Filtering : " + x);
return x > 2;
})
.sorted()
.peek(x -> System.out.println("Peek : " + x))
.boxed()
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
这将打印:
Filtering : 1
Filtering : 3
Filtering : 5
Filtering : 2
Filtering : 6
Peek : 3
Peek : 5
Peek : 6
Run Code Online (Sandbox Code Playgroud)
因为您已经使用了sorted并且filter在上面,所以过滤器必须获取所有元素并处理它们 - 以便将其sorted应用于正确的元素。
另一方面,如果你放弃了sorted:
IntStream.of(1, 3, 5, 2, 6)
.filter(x -> {
System.out.println("Filtering : " + x);
return x > 2;
})
// .sorted()
.peek(x -> System.out.println("Peek : " + x))
.boxed()
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
输出将是:
Filtering : 1
Filtering : 3
Peek : 3
Filtering : 5
Peek : 5
Filtering : 2
Filtering : 6
Peek : 6
Run Code Online (Sandbox Code Playgroud)
一般来说,我确实同意,我尝试避免(如果可以的话)有状态的中间操作 - 也许你不想让sorted我们说 - 也许你可以收集到TreeSet......等等。但我并没有想太多 - 它我需要使用它 - 我只是这样做,并且可能会衡量它是否真的是一个瓶颈。
除非你真的遇到了一些性能问题——我不会考虑那么多;特别是因为您需要大量元素才能真正从并行中获得一些速度优势。
这是一个相关的问题,表明您确实需要大量元素才能获得性能提升。
| 归档时间: |
|
| 查看次数: |
148 次 |
| 最近记录: |