8

我刚开始学习 Scala,所以请耐心等待 :-)

我对 reduceLeft 的行为方式有疑问。这里有一个例子:

List(1, 2, 3, 4, 5) reduceLeft (_ + _)

我想知道是否可以同时进行计算,例如:

第一回合:

  • 过程 1 计算:1 + 2
  • 过程 2 计算:4 + 5

第二轮:

  • 过程 1 计算:3 + 3

第三轮:

  • 过程 1 计算:6 + 9

如果我只使用reduce 函数而不是reduceLeft,至少这是我所期望的。或者 reduceLeft 真的一次只做一次减少吗?

((((1 + 2) + 3) + 4) + 5)

这基本上意味着它不能并行执行,如果可能的话,应该总是更喜欢reduce而不是reduceLeft/Right?

4

2 回答 2

11

答案是肯定的,而且非常简单:

List(1, 2, 3, 4, 5).par.reduce (_ + _)

par方法将列表转换为并行集合。当您调用reduce此并行集合时,它将并行执行。

请参阅并行收集文档

于 2013-03-07T22:53:49.323 回答
6

正如您所注意到的,reduceLeft它是不可并行化的,因为它明确地假定了一种非关联的形式:(B,A) => B.

只要使用关联运算符,reduce就可以并行化。

还有一个 call 的类似物,foldLeftaggregate有两个功能:一个映射成可组合的形式,两个是关联的,用于合并元素: (B,A)=>B, (B,B) => B.

这个,只要两个函数在输出上达成一致,并且你可以在任何你想要的地方混合一个零,就可以并行化。

所以如果你想能够并行,

reduceLeft/Right ->  reduce
foldLeft/Right   ->  aggregate

在某些情况下,可能会reduce比限制性更强reduceLeft,但aggregate会起作用。

也就是说,这只会使语句能够并行。要使其真正并行,您需要使用继承自的集合,这些集合的名称中ParIterable都有:等。获得并行集合的最简单方法是调用常规集合(反之亦然,从平行与非平行)。这样做是因为通常除了速度之外没有理由并行,但是并行增加了开销。所以你应该只在有足够的工作要做的情况下并行操作,虽然你可能知道,但编译器可能不知道。因此,您要明确选择您想要的集合类型。(并行集合返回并行,顺序返回顺序。)ParParVector.par.seq

于 2013-03-07T22:56:16.893 回答