-
Notifications
You must be signed in to change notification settings - Fork 9
First Class Tasks
val (v1, v2) = parallel(e1, e2)
we can write alternatively using a new construct called task
:
val t1 = task(e1)
val t2 = task(e2)
val v1 = t1.join
val v2 = t2.join
t = task(e)
starts computation of a call-by-name
parameter e
"in the background"
- t is a task, which performs computation of e.
- current computation on the main thread proceeds in parallel with t
- to obtain the result of e, use
t.join
-
t.join
blocks the parent thread and waits until the result is computed - subsequent
t.join
calls quickly return the same result
In short, we use task
to represent each expression/computation that we want to do in parallel.
Here is a minimal interface for tasks:
def task(c: => A) : Task[A]
trait Task[A] {
def join: A
}
task
and join
map between computations and tasks that perform these computations.
In terms of the value computed the equation task(e).join == e
holds i.e. values gotten from LHS and RHS are same, LHS being faster as it happens in parallel.
We can omit writing .join
if we also define an implicit conversion:
implicit def getJoin[T](x:Task[T]): T = x.join
We have seen four-way parallel p-norm:
val ((part1, part2),(part3,part4)) = parallel( parallel(sumSegment(a, p, 0, mid1), sumSegment(a, p, mid1, mid2)),
parallel(sumSegment(a, p, mid2, mid3), sumSegment(a, p, mid3, a.length)))
power(part1 + part2 + part3 + part4, 1/p)
Here is essentially the same computation expressed using task:
val t1 = task {sumSegment(a, p, 0, mid1)}
val t2 = task {sumSegment(a, p, mid1, mid2)}
val t3 = task {sumSegment(a, p, mid2, mid3)}
val t4 = task {sumSegment(a, p, mid3, a.length)}
power(t1 + t2 + t3 + t4, 1/p) // join is implicit
We defined the signature of parallel
previously.
Can we implement parallel
construct as a method using task
:
def parallel[A, B](cA: => A, cB: => B): (A, B) = {
val tB: Task[B] = task { cB }
val tA: A = cA
(tA, tB.join)
}
Note that we need only one extra thread to the main thread, so we use the main thread for tA.
def parallelWrong[A, B](cA: => A, cB: => B): (A, B) = {
val tB: B = (task { cB }).join
val tA: A = cA
(tA, tB.join)
}
Here join
is called on tb
where we are creating the task to be executed in parallel. So first we wait until tb
is calculated. Then we calculated ta
. So we are not doing these tasks in parallel.
Here is the source of the parallel package that will be used in assignments: https://github.com/rohitvg/scala-parallel-programming-3/blob/master/resources/source/package-parallel.pdf
Week 1
- Introduction to Parallel Computing
- Parallelism on the JVM
- Running Computations in Parallel
- Monte Carlo Method to Estimate Pi
- First Class Tasks
- How fast are parallel programs?
- Benchmarking Parallel Programs
Week 2
- Parallel Sorting
- Data Operations
- Parallel map()
- Parallel fold()
- Associativity I
- Associativity II
- Parallel Scan (Prefix Sum) Operation
Week 3
- Data Parallel Programming
- Data Parallel Operations
- Scala Parallel Collections
- Splitters and Combiners
Week 4