Scala中的并行处理模式

时间:2016-06-16 02:54:04

标签: scala parallel-processing

我希望这不是一个愚蠢的问题,或者我错过了一些明显的东西。我正在关注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。我创建的线程数似乎对此特定测试没有太大影响。

1 个答案:

答案 0 :(得分:1)

您选择的sieveOfEratosthenes的实施已经是并行的(它使用ParSet),因此将其并行化进一步无法提供帮助。

你在第一次测试中看到的加速可能是JIT热身。