我希望这不是一个愚蠢的问题,或者我错过了一些明显的东西。我正在关注Coursera并行编程类,并且在第1周他们有以下代码来并行运行任务(可能略有不同,因为我输入了我的):
object parallelism {
val forkJoinPool = new ForkJoinPool
abstract class TaskScheduler {
def schedule[T](body: => T): ForkJoinTask[T]
def parallel[A, B](taskA: => A, taskB: => B): (A, B) = {
val right = task {
taskB
}
val left = taskA
(left, right.join())
}
}
class DefaultTaskScheduler extends TaskScheduler {
def schedule[T](body: => T): ForkJoinTask[T] = {
val t = new RecursiveTask[T] {
def compute = body
}
Thread.currentThread match {
case wt: ForkJoinWorkerThread => t.fork()
case _ => forkJoinPool.execute(t)
}
t
}
}
val scheduler =
new DynamicVariable[TaskScheduler](new DefaultTaskScheduler)
def task[T](body: => T): ForkJoinTask[T] = {
scheduler.value.schedule(body)
}
def parallel[A, B](taskA: => A, taskB: => B): (A, B) = {
scheduler.value.parallel(taskA, taskB)
}
}
我写了一个像这样的单元测试:
test("Test two task parallelizer") {
val (r1, t1) = timed {
( sieveOfEratosthenes(100000),
sieveOfEratosthenes(100000))
}
val (r2, t2) = timed {
parallel (
sieveOfEratosthenes(100000),
sieveOfEratosthenes(100000)
)
}
assert(t2 < t1)
}
test("Test four task parallelizer") {
val (r1, t1) = timed {
(sieveOfEratosthenes(100000),
sieveOfEratosthenes(100000),
sieveOfEratosthenes(100000),
sieveOfEratosthenes(100000))
}
val (r2, t2) = timed {
parallel (
parallel (
sieveOfEratosthenes(100000),
sieveOfEratosthenes(100000)
),
parallel (
sieveOfEratosthenes(100000),
sieveOfEratosthenes(100000)
)
)
}
assert(t2 < t1)
}
在第一次测试中,我节省了很多钱(300毫秒到50毫秒),但是在第二次测试中,我只节省了大约20毫秒,如果我经常运行它的时间实际上会增加并且我的测试失败。 (“timed”返回的元组中的第二个值是以毫秒为单位的时间)
测试方法是这里的第一个版本:https://rosettacode.org/wiki/Sieve_of_Eratosthenes#Scala
有人可以教我第二次测试中发生了什么吗?如果重要的话,我正在运行单个cpu,四核i5。我创建的线程数似乎对此特定测试没有太大影响。
答案 0 :(得分:1)
您选择的sieveOfEratosthenes
的实施已经是并行的(它使用ParSet
),因此将其并行化进一步无法提供帮助。
你在第一次测试中看到的加速可能是JIT热身。