How to optimize this short factorial function in scala? (Creating 50000 BigInts)

前端 未结 4 1426
名媛妹妹
名媛妹妹 2021-02-13 06:41

I\'ve compaired the scala version

(BigInt(1) to BigInt(50000)).reduce(_ * _)

to the python version

reduce(lambda x,y: x*y, rang         


        
4条回答
  •  孤街浪徒
    2021-02-13 07:31

    Most efficient way to calculate factorial in Scala is using of divide and conquer strategy:

    def fact(n: Int): BigInt = rangeProduct(1, n)
    
    private def rangeProduct(n1: Long, n2: Long): BigInt = n2 - n1 match {
      case 0 => BigInt(n1)
      case 1 => BigInt(n1 * n2)
      case 2 => BigInt(n1 * (n1 + 1)) * n2
      case 3 => BigInt(n1 * (n1 + 1)) * ((n2 - 1) * n2)
      case _ => 
        val nm = (n1 + n2) >> 1
        rangeProduct(n1, nm) * rangeProduct(nm + 1, n2)
    }
    

    Also to get more speed use latest version of JDK and following JVM options:

    -server -XX:+TieredCompilation
    

    Bellow are results for Intel(R) Core(TM) i7-2640M CPU @ 2.80GHz (max 3.50GHz), RAM 12Gb DDR3-1333, Windows 7 sp1, Oracle JDK 1.8.0_25-b18 64-bit:

    (BigInt(1) to BigInt(100000)).product took: 3,806 ms with 26.4 % of CPU usage
    (BigInt(1) to BigInt(100000)).reduce(_ * _) took: 3,728 ms with 25.4 % of CPU usage
    (BigInt(1) to BigInt(100000)).reduceLeft(_ * _) took: 3,510 ms with 25.1 % of CPU usage
    (BigInt(1) to BigInt(100000)).reduceRight(_ * _) took: 4,056 ms with 25.5 % of CPU usage
    (BigInt(1) to BigInt(100000)).fold(BigInt(1))(_ * _) took: 3,697 ms with 25.5 % of CPU usage
    (BigInt(1) to BigInt(100000)).par.product took: 406 ms with 66.3 % of CPU usage
    (BigInt(1) to BigInt(100000)).par.reduce(_ * _) took: 296 ms with 71.1 % of CPU usage
    (BigInt(1) to BigInt(100000)).par.reduceLeft(_ * _) took: 3,495 ms with 25.3 % of CPU usage
    (BigInt(1) to BigInt(100000)).par.reduceRight(_ * _) took: 3,900 ms with 25.5 % of CPU usage
    (BigInt(1) to BigInt(100000)).par.fold(BigInt(1))(_ * _) took: 327 ms with 56.1 % of CPU usage
    fact(100000) took: 203 ms with 28.3 % of CPU usage
    

    BTW to improve efficience of factorial calculation for numbers that greater than 20000 use following implementation of Schönhage-Strassen algorithm or wait until it will be merged to JDK 9 and Scala will be able to use it

提交回复
热议问题