【发布时间】:2011-04-14 00:29:43
【问题描述】:
Scala(或 Java)的 QtConcurrent 的类似物是什么?即MapReduce、并行map 和foldl 的简化实现。 谢谢
【问题讨论】:
标签: scala mapreduce parallel-processing
Scala(或 Java)的 QtConcurrent 的类似物是什么?即MapReduce、并行map 和foldl 的简化实现。 谢谢
【问题讨论】:
标签: scala mapreduce parallel-processing
您可以使用 Scala 并行集合。它们目前是 Scala 夜间版本的一部分,并将在 Scala 2.9 中发布。这个想法是常规集合中可用的大多数操作都是并行化的,因此可以以相同的方式使用并行集合。
目前,有几种可用的集合类型 - 并行范围、并行数组和并行哈希尝试。例如,您可以像这样在并行数组上调用并行 map 和 fold 操作:
scala> val pa = (0 until 10000).toArray.par
pa: scala.collection.parallel.mutable.ParArray[Int] = ParArray(0, 1, 2, 3, 4, 5, 6,...
scala> pa.map(_ + 1)
res0: scala.collection.parallel.mutable.ParArray[Int] = ParArray(1, 2, 3, 4, 5, 6, 7,...
scala> pa map { v => if (v % 2 == 0) v else -v }
res1: scala.collection.parallel.mutable.ParArray[Int] = ParArray(0, -1, 2, -3, 4, -5,...
scala> pa.fold(0) { _ + _ }
res2: Int = 49995000
还有其他可用的并行收集操作。请注意,fold 必须采用关联运算符 - 在上面的示例中,加法是关联的 ((A + B) + C == A + (B + C)),即您可以按任何顺序添加数字的子序列并且您将始终获得相同的金额(reduce 有类似的合同)。
要注意的另一件事是,传递给并行集合的闭包是同时调用的。如果它们有副作用,例如修改环境中的局部变量,则这些访问必须同步。例如,您可以这样做:
scala> var a = 0
a: Int = 0
scala> pa foreach { a += _ }
scala> a
res1: Int = 49995000
scala> a = 0
a: Int = 0
scala> pa foreach { a += _ }
scala> a
res7: Int = 49990086
并且每次都有不同的结果,因为foreach 并行调用{ a += _ }。在上面的例子中,a 应该被同步,用锁或原子保护。
但想法是使用内置组合器来完成任务并倾向于函数式编程,避免如上例中的局部副作用。
您可能想在其他答案中提供的链接中阅读更多有关其内部机制的信息。
【讨论】:
见Scala Parallel Collections视频和论文“A Generic Parallel Collection Framework”
This states:并行集合在 current development builds 中,将作为 Scala 2.9 的一部分发布。参见发布计划here,Scala 2.9 可下载here。
【讨论】:
你可以在集合上使用scala.actors.Futures 和普通的map/flatMap。但是,不容易并行化 fold。
如果您使用多主机,我会使用Akka's send-and-receive-future。
【讨论】: