Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute multiple tasks parallellly?

Tags:

I attend the class Parallel Programming, and it shows the parallel interface:

def parallel[A, B](taskA: => A, taskB: => B): (A, B) = {
  val ta = taskA
  val tb = task {taskB}
  (ta, tb.join())
}

and the following is wrong:

def parallel[A, B](taskA: => A, taskB: => B): (A, B) = {
  val ta = taskB
  val tb = task {taskB}.join()
  (ta, tb)
}

see the interface more at https://gist.github.com/ChenZhongPu/fe389d30626626294306264a148bd2aa

It also show us the right way to execute four tasks:

def parallel[A, B, C, D](taskA: => A, taskB: => B, taskC: => C, taskD: => D): (A, B, C, D) = {
    val ta = task { taskA }
    val tb = task { taskB }
    val tc = task { taskC }
    val td = taskD
    (ta.join(), tb.join(), tc.join(), td)
}

My question: if I don't know the number of tasks advance (a List of tasks), how can I call join for each tasks correctly?

tasks.map(_.join()) // wrong

Edit

The similar discussion also occurs at Discuss this week's module: Parallel Programming

like image 397
chenzhongpu Avatar asked Aug 02 '16 05:08

chenzhongpu


1 Answers

Using framework from Parallel Programming course

You can implement the method like this:

def parallel[A](tasks: (() => A)*): Seq[A] = {
  if (tasks.isEmpty) Nil
  else {
    val pendingTasks = tasks.tail.map(t => task { t() })
    tasks.head() +: pendingTasks.map(_.join())
  }
}

(Note that you can't have variable number of by-name arguments - though this can change)

And then use it like that:

object ParallelUsage {
  def main(args: Array[String]) {
    val start = System.currentTimeMillis()

    // Use a list of tasks:
    val tasks = List(longTask _, longTask _, longTask _, longTask _)
    val results = parallel(tasks: _*)
    println(results)

    // or pass any number of individual tasks directly:
    println(parallel(longTask, longTask, longTask))
    println(parallel(longTask, longTask))
    println(parallel(longTask))
    println(parallel())

    println(s"Done in ${ System.currentTimeMillis() - start } ms")
  }

  def longTask() = {
    println("starting longTask execution")
    Thread.sleep(1000)
    42 + Math.random
  }
}

Using Scala's parallel collections

You can't go simpler than this:

val tasks = Vector(longTask _, longTask _, longTask _)
val results = tasks.par.map(_()).seq
like image 124
TeWu Avatar answered Oct 12 '22 23:10

TeWu