scala actor中的操作之间的依赖关系

时间:2010-03-17 17:46:04

标签: scala actor

我正在尝试使用scala actor来并行化代码。这是我的第一个真正的代码与演员,但我有一些Java Mulithreading和MPI在C中的经验。但我完全失去了。

我想要实现的工作流程是一个循环管道,可以描述如下:

  • 每个 worker actor都有一个引用另一个,从而形成一个圆圈
  • 有一个协调器 actor,它可以通过发送StartWork()消息来触发计算
  • 当工作人员收到StartWork()消息时,它会在本地处理一些内容并向该圈子中的邻居发送DoWork(...)消息。
  • 邻居做了其他一些事情,然后将DoWork(...)消息发送给自己的邻居。
  • 这将持续到初始工作人员收到DoWork()消息。
  • 协调员可以向初始工作人员发送GetResult()消息并等待回复。

关键是协调员只应在数据准备好时收到结果。 在回复GetResult()消息之前,工作人员如何等待作业返回?

为了加快计算速度,任何工作人员都可以随时收到StartWork()

这是我第一次尝试伪实现的worker:

class Worker( neighbor: Worker, numWorkers: Int ) {
   var ready = Foo()
   def act() {
     case StartWork() => { 
       val someData = doStuff()
       neighbor ! DoWork( someData, numWorkers-1 ) 
       }
     case DoWork( resultData, remaining ) => if( remaining == 0 ) {
         ready = resultData
       } else {
         val someOtherData = doOtherStuff( resultData )
         neighbor ! DoWork( someOtherData, remaining-1 )
      }
    case GetResult() => reply( ready )
  }
}

在协调员方面:

worker ! StartWork()
val result = worker !? GetResult() // should wait

2 个答案:

答案 0 :(得分:3)

首先,您显然需要有一些标识符来构成单件作品,以便GetResult可以获得正确的结果。我想明显的解决方案是让你的演员保持Map的结果和Map任何等待的 getters

class Worker( neighbor: Worker, numWorkers: Int ) {
   var res: Map[Long, Result] = Map.empty
   var gets: Map[Long, OutputChannel[Any]] = Map.empty   
   def act() {
     ...
     case DoWork( id, resultData, remaining ) if remaining == 0 =>
       res += (id -> resultData)
       gets.get(id).foreach(_ ! res(id)) //reply to getters when result is ready
       gets -= id //clear out getter map now?
     case GetResult(id) if res.isDefinedAt(d) => //result is ready
       reply (res(id))
     case GetResult(id) => //no result ready 
       gets += (id -> sender)
   }
}

注意:在匹配条件下使用if可以使邮件处理更清晰

答案 1 :(得分:1)

另一种选择是:

class Worker( neighbor: Worker, numWorkers: Int ) {
   var ready = Foo()
   def act() {
     case StartWork() => { 
       val someData = doStuff()
       neighbor ! DoWork( someData, numWorkers-1 ) 
       }
     case DoWork( resultData, remaining ) => if( remaining == 0 ) {
         ready = resultData
         react {
           case GetResult() => reply( ready )
         }
       } else {
         val someOtherData = doOtherStuff( resultData )
         neighbor ! DoWork( someOtherData, remaining-1 )
      }
  }
}

工作完成后,此工作人员将被卡住,直到收到GetResult消息。另一方面,协调员可以立即发送GetResult,因为它将保留在邮箱中,直到工作人员收到它。