문제

스칼라 액터를 사용하여 코드를 병렬화하려고합니다. 그것은 배우와의 첫 번째 실제 코드이지만 C에서 Java Mulithreading과 MPI에 대한 경험이 있습니다. 그러나 나는 완전히 잃어 버렸습니다.

내가 깨닫고 싶은 워크 플로는 원형 파이프 라인이며 다음과 같이 설명 할 수 있습니다.

  • 노동자 배우는 다른 사람에 대한 언급을 가지고있어 원을 형성합니다.
  • 이있다 조정자 a StartWork() 메시지
  • 근로자가 a StartWork() 메시지, 일부 물건을 로컬로 처리하고 보냅니다 DoWork(...) 원 안에있는 이웃에게 메시지.
  • 이웃은 다른 일을하고 차례로 DoWork(...) 자신의 이웃에게 메시지.
  • 이것은 초기 작업자가 a를받을 때까지 계속됩니다 DoWork() 메시지.
  • 코디네이터는 a를 보낼 수 있습니다 GetResult() 초기 작업자에게 메시지를 보내고 답장을 기다립니다.

요점은 코디네이터가 데이터가 준비된 경우에만 결과 만 받아야한다는 것입니다. 근로자는 어떻게 일자리가 응답하기 전에 직장으로 돌아 왔을 때까지 기다릴 수 있습니까? GetResult() 메시지 ?

계산 속도를 높이려면 모든 작업자가 StartWork() 언제든지.

다음은 근로자의 첫 번째 시도를 시도합니다.

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
도움이 되었습니까?

해결책

첫째, 당신은 단일 작업을 구성하는 것의 식별자가 있어야합니다. GetResult 올바른 결과를 얻을 수 있습니다. 명백한 해결책은 배우가 Map 결과와 a 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 일치하는 조건에서 메시지 처리가 조금 더 명확해질 수 있습니다.

다른 팁

한 가지 대안은 다음과 같습니다.

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, 작업자가 수신 할 때까지 사서함에 남아 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top