2013-03-07 47 views
6

我刚开始学习Scala,所以请耐心等待:-)可以reduceLeft并行执行吗?

我有一个关于reduceLeft如何行为的问题。这里的一个示例:

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

不知的计算可以simultanously进行,例如:

第一轮:

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

第二轮:

  • 过程1计算:3 + 3

第三轮:

  • 过程1个计算:6 + 9

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

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

这基本上意味着它不能并行执行,每个人都应该喜欢减少过度reduceLeft /右如果可能的话?

+1

不完全。 'reduceLEFT'按照定义是连续的(从左到右)。这就是为什么'blahLeft'和'blahRight' HOFs的并行版本被命名为'blah'的原因。 – 2013-03-08 02:54:46

回答

8

答案是肯定的,而且也很容易:

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

par方法把列表转换成并行集合。在此平行集合上调用reduce时,它将并行执行。

the parallel collection documentation

+2

我不知道谁低估了这一点 - 答案很简短,至关重要,并且完全正确。 – 2013-03-07 23:00:04

+0

其实我以为这是你,因为你之前的回答提到'reduce'不是可并行化的^^。在检查完REPL之后,它确实在多个线程上执行了,我会回复,只是看到你已经更新了这个语句,并且downvote已经不存在了(或者通过upvote来平衡,我不知道)。 – 2013-03-07 23:02:09

+1

平衡了我的赞成,因为你的答案至少与我的答案一样好(我的最初答案没有正确表达)。 – 2013-03-07 23:04:02

4

正如你已经注意到,reduceLeft不是并行的,因为它明确地假设一个形式,是不相关联:(B,A) => B

只要你使用关联运算符,reduce是可并行化的。

还有,它有两个功能称为aggregatefoldLeft模拟:一个映射到一个组合的形式,以及两个关联一个合并的元素:(B,A)=>B, (B,B) => B

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

因此,如果你希望能够平行,

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

可能有一些情况下,reducereduceLeftaggregate更严格的将这样的伎俩。

这就是说,这不仅使语句能够平行。对于它实际上平行您需要使用从ParIterable继承的集合,而这些都在他们的名字ParParVector等。获得并行集合最简单的方法是调用.par定期一( .seq从平行走向非平行)。这样做是因为一般情况下除了速度之外没有任何理由是平行的,但并行性增加了开销。所以,如果有足够的工作要做,你应该只能并行操作,而你可能知道,编译器可能不会。因此,您应明确选择您想要的集合类型。 (并行收集并行,并顺序返回顺序。)

+0

如果您可以添加是否为每个集合自动并行化reduce规则(这是我目前如何解释您的答案),还是仅适用于通过'par'获得的并行集合(这是我猜)。 – bluenote10 2013-03-08 09:20:57