Scala Future多核 - 性能降低

时间:2018-01-10 21:43:08

标签: scala performance future

    import java.util.concurrent.{Executors, TimeUnit}

    import scala.annotation.tailrec
    import scala.concurrent.{Await, ExecutionContext, Future}
    import scala.util.{Failure, Success}

    object Fact extends App {
      def time[R](block: => R): Long = {
        val t0 = System.nanoTime()
        val result = block // call-by-name
        val t1 = System.nanoTime()

        val t: Long = TimeUnit.SECONDS.convert((t1 - t0), TimeUnit.NANOSECONDS)
        //println(
        // "Time taken seconds: " + t)
        t
      }
      def factorial(n: BigInt): BigInt = {
        @tailrec
        def process(n: BigInt, acc: BigInt): BigInt = {
          //println(acc)
          if (n <= 0) acc
          else process(n - 1, n * acc)
        }

        process(n, 1)
      }

      implicit val ec =
        ExecutionContext.fromExecutor(Executors.newFixedThreadPool(2))
      val f1: Future[Stream[Long]] =
        Future.sequence(
          (1 to 50).toStream.map(x => Future { time(factorial(100000)) }))

      f1.onComplete {
        case Success(s) => {
          println("Success : " + s.foldLeft(0L)(_ + _) + " seconds!")

        }
        case Failure(f) => println("Fails " + f)
      }

      import scala.concurrent.duration._

      Await.ready(Future { 10 }, 10000 minutes)

    }

我有上面的Factorial代码,需要使用多个内核来更快地完成程序,并且应该使用更多内核。

所以我改变了,

  • Executors.newFixedThreadPool(1)使用1个核心

  • Executors.newFixedThreadPool(2)使用2个核心

更改为 1核心时,结果会显示在 127秒中。 但是当更改为 2个核心时,我会 157秒

我的疑问是,当我增加核心(并行性)时,它应该会提供良好的性能。但事实并非如此。为什么?

请纠正我,如果我错了或遗失了什么。

先谢谢。

2 个答案:

答案 0 :(得分:2)

你是如何衡量时间的?打印出来的结果不是执行所花费的时间,而是每次调用的时间总和。

在REPL中运行Fact.time(Fact.main(Array.empty))我分别得到90和178两个和一个线程。似乎有意义......

答案 1 :(得分:1)

首先,Dima是对的,你打印的是所有任务的总执行时间,而不是直到最后一个任务完成的总时间。不同之处在于,第一个并行完成所有工作的时间,只有后者显示多线程实际加速。

然而,还有另一个重要的影响。当我使用1,2和3个线程运行此代码并测量总时间(f1准备好的时间)和总并行时间(您打印的那个)时,我得到以下数据(我也减少了数量)计算从50到20加速我的测试):

1 - 70 - 70
2 - 47 - 94
3 - 43 - 126

乍一看它看起来很好,因为平行时间除以实际时间与线程数大致相同。但是如果你仔细观察一下,你可能会注意到,从1个线程到2个线程的速度只有1.5倍左右,第三个线程只有1.1倍。此外,这些数字表示添加线程时所有任务的总时间实际上都会增加。这可能看起来令人费解。

这个难题的答案是你的计算实际上不受CPU约束。问题是答案(factorial(100000))实际上是一个非常大的数字。事实上,它是如此之大,以至于需要大约185KB的内存来存储它。这意味着在计算的后期阶段,factorial方法实际上变得比CPU绑定更多的内存限制,因为这个大小足以溢出最快的CPU缓存。这就是为什么添加更多线程会减慢每个计算的原因:是的,你的计算速度更快但内存却没有更快。因此,当您使CPU缓存和内存通道饱和时,添加更多线程(内核)并不能提高性能。