2012-05-05 17 views
0

我一直在尋找scala和AKKA來管理一個明顯可並行化的算法。 我有一些函數式編程的知識,主要是做Java,所以我的FP可能不是最好的。斯卡拉,使用響應者來抽象可能的異步計算

我一起工作的算法很簡單,有一個頂部計算:

def computeFull(...): FullObject 

這種計算調用子計算,然後總結一下(簡化):

def computePartial(...): Int 

computeFull做了這樣的事情(再次簡化):

val partials = for(x <- 1 to 10 
    y <- 1 to 10) yield computePartial(x, y) 
partials.foldLeft(0)(_ + _) 

因此,我t非常接近AKKA的例子,進行PI計算。我有很多computeFull調用,並在他們每個中有很多computePartial。所以我可以將所有這些包裝在AKKA actors中,或者在Futures中簡化,在不同的線程中調用每個computeFull和每個computePartial。然後我可以使用http://doc.akka.io/docs/akka/snapshot/scala/futures.html的摺疊,zip和map功能來梳理未來。

但是,這意味着computeFull和computePartial將不得不返回包含實際結果的期貨。他們因此變得依賴於AKKA並且假定事情是並行運行的。事實上,我也必須隱式地傳遞我的函數中的執行上下文。

我認爲這很奇怪,算法「不應該」知道它是如何並行化的細節,或者如果它是。

在閱讀了關於scala(而不是AKKA的)的期貨並研究了Code Continuation之後。似乎scala提供的Responder monad(http://www.scala-lang.org/api/current/scala/Responder.html)似乎是抽象函數調用運行的正確方法。 我有這種模糊的直覺,computeFull和computePartial可以返回響應者而不是期貨,並且當monad在執行時,它決定如何嵌入響應者中的代碼得到執行(如果它產生一個新的actor或者它是在相同的線)。

但是,我不太確定如何得到這個結果。有什麼建議麼?你認爲我是正確的嗎?

回答

3

如果您不想依賴Akka(但請注意,Akka風格的期貨將被移動幷包含在Scala 2.10中)並且您的計算只是對集合的簡單摺疊,您可以簡單地使用Scala的平行集合:

val partials = for { x <- (1 to 10).par 
    y <- 1 to 10 
} yield computePartial(x, y) 
// blocks until everything is computed 
partials.foldLeft(0)(_ + _) 

當然,這將阻塞,直到partials是準備好了,所以它可能不是一個合適的情況下,當你真正需要的期貨。

使用Scala 2.10作風期貨可以使完全不同步的算法曾經注意到它:

def computePartial(x: Int, y: Int) = { 
    Thread.sleep((1000 * math.random).toInt) 
    println (x + ", " + y) 
    x * y 
} 

import scala.concurrent.future 
import scala.concurrent.Future 
val partials: IndexedSeq[Future[Int]] = for { 
    x <- 1 to 10 
    y <- 1 to 10 
} yield future(computePartial(x, y)) 

val futureResult: Future[Int] = Future.sequence(partials).map(_.fold(0)(_ + _)) 

def useResult(result: Int) = println(s"The sum is $result") 

// now I want to use the result of my computation 
futureResult map { result => // called when ready 
    useResult(result) 
} 
// still no blocking 
println("This is probably printed before the sum is calculated.") 

所以,computePartial並不需要了解如何在執行任何東西。 (儘管就本例而言,它應該不會有任何副作用,但包括println副作用。)

可能的方法computeFull應該管理算法並且因此知道關於Futures或並行性。畢竟這個算法的一部分。

(至於Responder:?Scala的老期貨使用它,所以我不知道這是怎麼回事 - 而不是一個執行上下文配置的完全意味着你正在尋找)

+0

聽起來不錯,我會指望官方2.10那麼。然而,我可能並不清楚,我想知道的不是如何獨立於AKKA,而是如何讓computePartial/computeFull不知道期貨。有點像使用Reader monad進行依賴注入,但不是傳遞數據庫連接,而是傳遞一個執行函數的策略:或者是並行的,或者是完全不同的。因此可以在不改變這兩種方法的代碼的情況下比較不同的並行化選項。 – Mortimer

0

的阿卡中的單身演員不知道他是否平行奔跑。這就是阿卡的設計。但是,如果你不想靠阿卡可以使用parrallel藏品,如:

for (i <- (0 until numberOfPartialComputations).par) yield (
    computePartial(i) 
).sum 

的總和稱爲上parrallel收集和parrallel進行。