为什么地图功能固有地平行?

时间:2017-11-18 17:43:27

标签: scala parallel-processing functional-programming map-function

我正在阅读以下演示文稿:

http://www.idt.mdh.se/kurser/DVA201/slides/parallel-4up.pdf

并且作者声称地图功能非常适合并行性(特别是他在第3页或幻灯片9和10中支持他的主张)。

如果给出了将列表的每个值增加+1的问题,我可以看到如何在列表中循环,需要更改索引值,从而导致潜在的竞争条件问题。但我很好奇地图功能如何更好地允许程序员成功并行编码。

是否由于递归定义地图的方式?那么每个函数调用都可以抛出到不同的线程?

我希望有人可以提供一些细节,谢谢!

2 个答案:

答案 0 :(得分:3)

map函数将相同的纯函数应用于集合中的async元素并聚合结果。将函数应用于集合成员的顺序并不重要,因为根据定义,函数的返回值完全取决于输入。

答案 1 :(得分:2)

其他人已经解释过标准map实施并不是平行的。

但是在Scala中,由于你标记了它,你可以像

一样获得并行版本
val list = ... // some list
list.par.map(x => ...) // instead of list.map(x => ...)

另请参阅Parallel Collections Overview以及ParIterablescala.collection.parallel包中其他类型的文档。

如果需要,您可以在https://github.com/scala/scala/blob/v2.12.1/src/library/scala/collection/parallel/ParIterableLike.scala中找到并行map的实现(查找def mapclass Map)。它需要非常重要的基础设施,当然不仅仅是采用顺序map的递归定义并将其并行化。

  

如果通过循环定义了地图,那会怎么破坏?

幻灯片最后以F#并行数组为例,在https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/array.fs#L266你可以看到非并行实现有一个循环:

let inline map (mapping: 'T -> 'U) (array:'T[]) = 
     checkNonNull "array" array             
     let res : 'U[] = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked array.Length 
     for i = 0 to res.Length-1 do  
         res.[i] <- mapping array.[i] 
     res