ParArray.tabulate does not do concurrent computation

I am initializing the contents of an array using the tabulate method, but it seems to work sequentially despite the fact that I’m using ParArray rather than Array.

Is this just an issue that I’m using a scala that’s too old? Or is this the intended behavior.

  def visualizeSorted(temperatures: Iterable[(Location, Double)], sortedColors: List[(Double, Color)]): Image = {
    val temperaturesList = temperatures.toList
    def calcArrayEntry(index: Int): Pixel = {
      val imageY: Int = index / 360
      val imageX: Int = index % 360
      val lat: Double = 90.0 - imageY
      val lon: Double = imageX - 180.0
      println(s"y=$imageY   x=$imageX")
      val color = predictColor(Location(lat,lon),temperaturesList,sortedColors)
      Pixel.apply(color.red, color.green, color.blue, 255)
    }

    val arr = scala.collection.parallel.mutable.ParArray.tabulate(360*180)(calcArrayEntry)

    Image.apply(360, 180, Array.tabulate(360*180)(arr(_)))
  }

I’ve inserted some println calls to verify that it is indeed working only sequentially. Here is the output. I’ve let it run for a while, even if I’ve cut of the output for this message board.

y=0   x=0
y=0   x=1
y=0   x=2
y=0   x=3
y=0   x=4
y=0   x=5
y=0   x=6
y=0   x=7
y=0   x=8
y=0   x=9
y=0   x=10
y=0   x=11
y=0   x=12
y=0   x=13
y=0   x=14
1 Like

I don’t have 2.12 nearby. You should check if tabulate is a member of ParArray. I doubt if it is according to the doc: https://www.scala-lang.org/api/2.12.10/scala/collection/parallel/mutable/ParArray.html.

If it isn’t, then the closest thing I suggest is as follows:

ParArray.range(1, 20).map { x => 
  val r = Random.nextInt(10)
  Thread.sleep(r * 1000)
  println(s"$r secs: $x")
}
1 Like

In general, you should not be using scala.collection.parallel. It is buggy, unmaintained, and more or less abandoned: a relic of an earlier era when the standards of quality were not as high.

If you want to construct an array in parallel, consider spawning off a list of scala.concurrent.Futures and using Future.sequence or Await.result to aggregate the results back.

No disrespect intended, but is that really true? Anyone else care to weight in?