2015-09-04 45 views
3

我期待改進我正在開發的蒙特卡洛模擬的性能。使用Scalaz時的性能下降任務

我第一做這確實各路徑的模擬順序如下的實現:

def simulate() = { 
    for (path <- 0 to 30000) { 
    (0 to 100).foreach(
     x => // do some computation 
    )  
    } 
} 

這基本上是模擬30000條路徑和每個路徑具有100離散化隨機步驟。

上面的函數在我的機器上運行非常快(大約1s),因此我正在進行計算。

然後,我想通過使代碼以多線程的方式運行,進一步加快速度。

我決定使用Task對於這一點,我編寫了以下內容:

val simulation = (1 |-> 30000).map(n => Task { 
    (1 |-> 100).map(x => // do some computation) 
    }) 

然後我用這個如下:

Task.gatherUnordered(simulation).run 

當我打完這一關,我知道我的機器是幹什麼大量的工作,我可以 看到,在活動監測和機器風扇正在發生衝擊。 經過大約兩分鐘的機器上的繁重活動,看起來 要完成的工作,但我沒有得到任何價值返回(我預計從每個任務處理雙倍收集 )。

我的問題是:

  1. 爲什麼這個時間比順序例如長?我更可能做錯事,但我看不到它。
  2. 爲什麼我沒有從顯然正在處理的任務中獲取任何返回的值集合?
+0

看起來像'Task.gatherUnordered'效率低下。總時間是'O(N^2)',其中'N'是列表中的任務數量。 – ZhekaKozlov

+0

一般而言,取決於各個計算的速度,100 * 30000操作對於現代CPU的並行化來說可能太小。 –

+0

@mikołak,是的,但是這個模擬將運行一籃子產品。我只是想首先獲得一種產品的語義。 –

回答

3

我不知道爲什麼Task.gatherUnordered速度很慢,但如果你改變Task.gatherUnorderedNondeterminism.gatherUnordered一切都會好起來:

import scalaz.Nondeterminism 

Nondeterminism[Task].gatherUnordered(simulation).run 

我將在Github上關於Task.gatherUnordered創建一個問題。這絕對應該修復。

+0

創建問題:https://github.com/scalaz/scalaz/issues/997 – ZhekaKozlov