我寫了一個非常簡單的程序來測試並行程序的性能。我寫了一個非常簡單的程序,通過分區試驗來分解一個大的半數字。由於不涉及任何通訊,我預計幾乎完美的加速。但是,該計劃似乎非常糟糕。加速問題go
我使用系統time
命令,使用1,2,4和8個進程對運行在8(真正的非HT)內核計算機上的程序進行計時。我分解的數字是「28808539627864609」。這裏是我的結果:
cores time (sec) speedup 1 60.0153 1 2 47.358 1.27 4 34.459 1.75 8 28.686 2.10
如何解釋這種不好的加速?這是我的程序中的錯誤,還是運行時出現問題?我怎麼能得到更好的表演?我不是在談論算法本身(我知道有更好的算法來分解半數數字),而是我平行化的方式。
這裏是我的程序的源代碼:
package main
import (
"big"
"flag"
"fmt"
"runtime"
)
func factorize(n *big.Int, start int, step int, c chan *big.Int) {
var m big.Int
i := big.NewInt(int64(start))
s := big.NewInt(int64(step))
z := big.NewInt(0)
for {
m.Mod(n, i)
if m.Cmp(z) == 0{
c <- i
}
i.Add(i, s)
}
}
func main() {
var np *int = flag.Int("n", 1, "Number of processes")
flag.Parse()
runtime.GOMAXPROCS(*np)
var n big.Int
n.SetString(flag.Arg(0), 10) // Uses number given on command line
c := make(chan *big.Int)
for i:=0; i<*np; i++ {
go factorize(&n, 2+i, *np, c)
}
fmt.Println(<-c)
}
編輯
問題似乎真的涉及到Mod
功能。用Rem
代替它可以帶來更好但仍不完美的表現和加速。用QuoRem
代替它可以使性能提高3倍,並且提高速度。結論:似乎內存分配殺死了Go中的並行性能。爲什麼?你有任何關於此的參考?
在Go實現中「所有內存(分配)操作都被序列化」是不正確的。 – 2012-03-09 20:17:09
你有沒有關於在Go中的串行內存分配的任何參考?這可能是有道理的,但我希望看到事實。 – 2012-03-09 22:31:25
[來源](http://golang.org/src/pkg/runtime/malloc.h)有相關評論。所以,我糾正了。有一堆,但看起來goroutines可以一次獲得一堆內存,然後重複執行少量分配。無論如何,分配很明顯是你的程序中的問題,並且正如Atom正確識別的那樣,專門用Mod方法進行分配。我嘗試了他建議用QuoRem替代Mod的改變,而且你的程序不僅可以很好地與內核配合使用,而且運行得更快。 (以最新的一週來看,就是這樣。) – Sonia 2012-03-10 01:12:35