문제
스칼라 액터를 사용하여 코드를 병렬화하려고합니다. 그것은 배우와의 첫 번째 실제 코드이지만 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
, 작업자가 수신 할 때까지 사서함에 남아 있습니다.
제휴하지 않습니다 StackOverflow