ParSeq.fill 运行 按顺序?

ParSeq.fill running sequentially?

我正在尝试使用并行化在 Scala 中初始化一个数组。但是,当使用 ParSeq.fill 方法时,性能似乎并不比顺序初始化 (Seq.fill) 好多少。如果我执行相同的任务,但使用 map 初始化集合,那么它会快得多。

为了表明我的观点,我设置了以下示例:

import scala.collection.parallel.immutable.ParSeq
import scala.util.Random

object Timer {
  def apply[A](f: => A): (A, Long) = {
    val s = System.nanoTime
    val ret = f
    (ret, System.nanoTime - s)
  }
}

object ParallelBenchmark extends App {

  def randomIsPrime: Boolean = {
    val n = Random.nextInt(1000000)
    (2 until n).exists(i => n % i == 0)
  }

  val seqSize = 100000

  val (_, timeSeq) = Timer { Seq.fill(seqSize)(randomIsPrime) }
  println(f"Time Seq:\t\t $timeSeq")
  val (_, timeParFill) = Timer { ParSeq.fill(seqSize)(randomIsPrime) }
  println(f"Time Par Fill:\t $timeParFill")
  val (_, timeParMap) = Timer { (0 until seqSize).par.map(_ => randomIsPrime) }
  println(f"Time Par map:\t $timeParMap")

}

结果是:

Time Seq:        32389215709
Time Par Fill:   32730035599
Time Par map:    17270448112 

很明显fill方法不是运行并行

Scala 中的并行集合库只能并行化现有集合,fill 尚未实现(并且可能永远不会)。如果您想提高速度,使用 Range 生成便宜的占位符集合的方法可能是您的最佳选择。

这是ParSeq.fill调用的底层方法,显然不是并行的。