如何使用Scala Actor有效地获取Fibonacci(n)? [英] How can I get Fibonacci(n) in an efficient way with Scala Actor?

查看:104
本文介绍了如何使用Scala Actor有效地获取Fibonacci(n)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

算法就是这样。

    def fib(x: Int): BigInt = {
        x match {
            case 1 => BigInt(1)
            case 2 => BigInt(1)
            case x => fib(x-1) + fib(x-2)
        }
    }



<我尝试使算法与Scala中的Actor并行。但是与没有Actor的代码相比,我的代码非常慢!

I try to make the algorithm parallel with Actor in Scala. But my code is extremely slow compare with the one without Actor!

有没有一种好的方法可以使它工作?

Is there a good way to make it work?

推荐答案

对于不大的 n ,串行代码将始终更快(在尾部递归的情况下快得多) 。这是因为调用新函数比启动新角色快。

For not large size of n, the serial code will always be faster (Much much faster in cases of tail recursion). This is because calling a new function will be faster than starting a new actor. Plus there will contention among threads and context switches.

在下面的代码中,我为每个 n>创建一个新的actor。 2 。可以有许多优化的方法,但我只是将递归 T(n)= T(n-1)+ T(n-2)用于序列一。

In the below code, I start a new actor for every n > 2. There can be many optimized ways, but I simply using the recurrence T(n) = T(n-1) + T(n-2) to serial one.

import akka.actor.Actor
import akka.actor.Props
import akka.actor.ActorSystem
import akka.event.Logging
import akka.actor.ActorRef
import akka.routing.RoundRobinRouter

object Fib extends App {

trait Fib
case class N(val n: Int) extends Fib

case class Ans(n: Int)
class FibN(listen: ActorRef) extends Actor {

var numOfResults = 0;
var ans = 0;
val log = Logging(context.system, this)

def receive = {
  case N(x) => {
    //println(self.path+"-Message N(x) "+x)
    val others = context.actorOf(Props(new FibN(self)).withRouter(RoundRobinRouter(2)), name = "Fibn:" + x)
    if(x==1 || x==2)
      listen ! new Ans(1)
    else if(x>2){
      others ! new N(x-1)
      others ! new N(x-2)
    }


  }

  case Ans(x) => {
    //println(self.path+" Ans(x) "+x+" numOfResults "+numOfResults+" from "+sender.path)
    numOfResults += 1
    ans = ans + x;
    if (numOfResults == 2){
      //println(self.path+"sending back to sender "+listen.path+" numOfResults "+numOfResults)
      listen ! Ans(ans)
    }


  }
  case _ => println(self.path+"Not valid")

}

}


class Listener extends Actor{
val log = Logging(context.system, this)
var st:Long = 0;
def receive = {
  case Ans(x) => {
    println(self.path+"\n\nAns is "+x+" time taken: "+(System.currentTimeMillis() - st))
    context.system.shutdown
  }
  case N(x) => {
    println(self.path+" Message Received "+x)
    val actor = context.actorOf(Props(new FibN(self)),"FibN")
    st = System.currentTimeMillis()
    actor ! new N(x)
  }
  case _ => println(self.path+" Invalid request")
 }
}

val system = ActorSystem("Fibanoccia")
val listener = system.actorOf(Props[Listener],"Listener")
listener ! new N(25)
}

这比预期的要慢得多。除非 n 很大,否则actor总是会因上述原因而变慢。对于较大的'n',可以将其分解。

This as expected was much slower. Unless n is very large, actor will always be slower for reasons mentioned. For larger 'n', this can be decomposed.

这篇关于如何使用Scala Actor有效地获取Fibonacci(n)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆