2013-12-18 67 views
0

我已經構建了一個流行數學模型,它在Go中的計算量非常強。我現在正在嘗試構建一套系統來測試我的模型,在那裏我改變了一個輸入並期望得到一個不同的輸出。我建立了一個系列的版本,以緩慢增加艾滋病毒流行率,並看到對艾滋病毒死亡的影響。它需要大約200毫秒的時間才能運行。Go-lang平行段運行速度比系列段慢

for q = 0.0; q < 1000; q++ { 

    inputs.CountryProfile.HivPrevalenceAdultsByGroup[0] = inputs.CountryProfile.HivPrevalenceAdultsByGroup[0] * float32(math.Pow(1.00001, q)) 
    results := costAnalysisHandler(inputs) 
    fmt.Println(results.HivDeaths[20]) 

} 

然後,我使用多個信道進行了「平行」的版本,它需要更長的,〜400毫秒來運行。這些小小的變化很重要,因爲我們將用不同的輸入來運行數百萬次運行,所以想盡可能提高效率。這裏是水貨版本:

ch := make(chan ChData) 
var q float64 
for q = 0.0; q < 1000; q++ { 
    go func(q float64, inputs *costanalysis.Inputs, ch chan ChData) { 
     inputs.CountryProfile.HivPrevalenceAdultsByGroup[0] = inputs.CountryProfile.HivPrevalenceAdultsByGroup[0] * float32(math.Pow(1.00001, q)) 
     results := costAnalysisHandler(inputs) 
     fmt.Println(results.HivDeaths[20]) 
     ch <- ChData{int(q), results.HivDeaths[20]} 
    }(q, inputs, ch) 
} 
for q = 0.0; q < 1000; q++ { 
    theResults := <-ch 
    fmt.Println(theResults) 
} 

任何想法非常讚賞。

回答

4

有開銷,並開始與後臺任務通信。花了你的成本的時間分析 可能相形見絀 等於溝通的成本,如果該方案正在採取的200ms,但如果協調成本不斷確實殺死你的應用程序,常用的方法是在一個時間來交班工作稍大塊例如,讓每個goroutine做一個10 q值的範圍分析,而不是一個。 (編輯:正如@Innominate所說,創建一個處理一系列作業對象的「goroutines」「工作者池」是另一種常見方法。)

此外,您粘貼的代碼具有競爭條件。你的Inputs結構的內容不會在你每次產生一個goroutine時被複制,因爲你正在傳遞你的函數指針。因此並行運行的例程將讀取和寫入同一個Inputs實例。

簡單地使一個全新的Inputs例如每個分析,結合自身陣列等將避免比賽。如果這最終浪費大量內存或導致大量冗餘副本,你可以1)recycle Inputs instances,2)分離出可以安全共享的只讀數據(也許有國家數據是固定的,不知道的),或者3)改變一些相對較大的陣列是costAnalysisHandler內的局部變量,而不是需要傳播的東西(也許它可能只是採取初步的艾滋病毒流行並在t = 20時返回艾滋病毒的死亡,而其他一切都是本地和堆棧中的)。

這並不適用於今天的Go,而是在最初發布問題時進行:除非您調用runtime.GOMAXPROCS()與期望的併發級別,例如runtime.GOMAXPROCS(runtime.NumCPU()),否則什麼都不是真正並行運行。

最後,如果您正在做一些更大的分析並確實存在性能問題,您應該只擔心所有這些;如果.2秒的等待是所有表演工作都可以節省您的地方,那不值得。

1

並行化計算密集型組計算要求的並行計算可以並行你的機器上實際運行。如果他們不這樣做,那麼創建goroutine,通道和讀取通道的額外開銷會使程序運行速度變慢。

我猜這是這裏的問題。

嘗試運行您的代碼之前GOMAXPROCS環境變量設置爲CPU的你有數量。或者在開始並行計算之前調用runtime.GOMAXRPROCS(runtime.NumCPU())。

1

我看到相關的並行性能兩個問題,

第一,更明顯的是,你必須爲了得到Go運行時使用多個CPU /核心設置GOMAXPROCS。通常可以將其設置爲機器中處理器的數量,但理想設置可能會有所不同。

第二個問題是有點棘手,這是你的代碼不會出現被並行很好。簡單地啓動一千個goroutines並假設他們將解決這個問題不會帶來好的結果。你可能應該使用某種工作池,運行有限的同時計算(一個好的起始數字將設置爲與GOMAXPROCS相同),而不是一次嘗試1000次。

參見:http://golang.org/doc/faq#Why_no_multi_CPU