如何在scala中并行迭代地图?

时间:2016-10-25 15:20:03

标签: multithreading scala parallel-processing

我有以下代码。

var arr = new Array[...](map.size)
var i = 0
for((k,value) <- map)
{
    arr(i) = (k, someFunc(value))
    i += 1
}

我希望这个循环并行执行。例如,我希望它并行运行在8个独立的线程中。我怎样才能在Scala中实现这一目标?

2 个答案:

答案 0 :(得分:5)

您可以将地图转换为并行集合,并通过使用大小为8(或任何您想要的大小)的池覆盖默认的“TaskSupport”来控制线程数:

import scala.collection.parallel.ForkJoinTaskSupport
import scala.collection.parallel.immutable.ParMap

val parMap: ParMap[Int, Int] = map.par
parMap.tasksupport = new ForkJoinTaskSupport(new scala.concurrent.forkjoin.ForkJoinPool(8))

parMap.foreach { case (k, value) =>
  arr(i) = (k, someFunc(value))
  i += 1
}

请注意,您可以通过删除所有可变值来使此代码更“惯用”:

val arr = parMap.map { case (k, value) => (k, someFunc(value)) }.toArray
val i = arr.length

编辑:或更短的版本:

val arr = parMap.mapValues(someFunc).toArray
val i = arr.length

答案 1 :(得分:1)

i+=1为什么?

否则,您正在寻找(使用Ints作为一个简单示例):

scala> val m = Map(1 -> 2, 2 -> 3)
m: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 2 -> 3)

scala> val mp = m.toParArray map {case(a,b) => (a,b+1)} 
mp: scala.collection.parallel.mutable.ParArray[(Int, Int)] = ParArray((1,3), (2,4))

scala> mp.toArray
res17: Array[(Int, Int)] = Array((1,3), (2,4))

您只需将b+1替换为someFunc(b)即可。 someFunc将并行执行,因为我们使用并行集合(m.toParArray),最后我们使用.toArray将parArray转换为顺序集合(不确定是否需要)