为什么map函数本质上是平行的



我正在阅读以下演示:

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

作者声称map函数的并行性构建得非常好(特别是他支持他在第3页或幻灯片9和10上的主张)。

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

这是由于递归定义映射的方式吗?所以每个函数调用都可以被抛出到不同的线程?

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

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

其他人已经解释了标准map实现不是并行的。

但在Scala中,由于您对其进行了标记,因此您可以获得与一样简单的并行版本

val list = ... // some list
list.par.map(x => ...) // instead of list.map(x => ...)

请参阅并行集合概述和ParIterable以及scala.collection.parallel包中其他类型的文档。

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

如果通过循环定义映射,它会如何分解?

幻灯片在末尾和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 

最新更新