reduceLeft可以并行执行吗?

时间:2013-03-07 22:19:11

标签: scala

我刚刚开始学习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)

这基本上意味着它不能并行执行,如果可能的话,应该总是倾向于减少reduceLeft / Right?

2 个答案:

答案 0 :(得分:9)

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

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

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

请参阅the parallel collection documentation

答案 1 :(得分:6)

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

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

还有一个名为foldLeft的类似aggregate,它有两个函数:一个映射为可组合的形式,另一个是关联的元素:(B,A)=>B, (B,B) => B

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

因此,如果您希望能够并行,

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

在某些情况下reducereduceLeft更具限制性但aggregate可以解决问题。

也就是说,这只会使声明并行。要使实际并行,您需要使用一个继承自ParIterable的集合,这些集合的名称中都有ParParVector等。获得并行集合的最简单方法是在常规集合上调用.par.seq从另一个方向调用,从并行到非并行)。它是这样做的,因为除了速度之外,通常没有理由保持并行,但并行性增加了开销。因此,如果有足够的工作要做,你应该只能并行操作,而你可能知道,编译器可能不会。因此,您要明确选择所需的集合类型。 (并行集合返回并行,顺序返回顺序。)