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

前端 未结 4 1360
名媛妹妹
名媛妹妹 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:42

    The fact that your Scala code creates 50,000 BigInt objects is unlikely to be making much of a difference here. A bigger issue is the multiplication algorithm—Python's long uses Karatsuba multiplication and Java's BigInteger (which BigInt just wraps) doesn't.

    The easiest workaround is probably to switch to a better arbitrary precision math library, like JScience's:

    import org.jscience.mathematics.number.LargeInteger
    
    (1 to 50000).foldLeft(LargeInteger.ONE)(_ times _)
    

    This is faster than the Python solution on my machine.


    Update: I've written some quick benchmarking code using Caliper in response to Luigi Plingi's answer, which gives the following results on my (quad core) machine:

                  benchmark   ms linear runtime
             BigIntFoldLeft 4774 ==============================
                 BigIntFold 4739 =============================
               BigIntReduce 4769 =============================
          BigIntFoldLeftPar 4642 =============================
              BigIntFoldPar  500 ===
            BigIntReducePar  499 ===
       LargeIntegerFoldLeft 3042 ===================
           LargeIntegerFold 3003 ==================
         LargeIntegerReduce 3018 ==================
    LargeIntegerFoldLeftPar 3038 ===================
        LargeIntegerFoldPar  246 =
      LargeIntegerReducePar  260 =
    

    I don't see the difference between reduce and fold that he does, but the moral is clear: if you can use Scala 2.9's parallel collections, they'll give you a huge improvement, but switching to LargeInteger helps as well.

提交回复
热议问题