我試圖開始工作的程序是一維細(xì)胞自動圖像的生成器,它需要足夠強(qiáng)大以處理數(shù)百萬個單個細(xì)胞的訂單的超大型模擬,因此多線程圖像生成過程是必要的。我之所以選擇 Go 是因為 go-routines 將使 CPU 的工作分配問題變得更加容易和高效?,F(xiàn)在,因為用單獨的 go-routine 編寫每個單元格根本不會非常高效,我決定創(chuàng)建一個函數(shù)來調(diào)用圖像對象并負(fù)責(zé)生成一整行單元格。此函數(shù)引用包含位切片的 2D 數(shù)組對象(請參閱此) 要繪制的所有單元格的數(shù)組,因此有許多循環(huán),但這對于手頭的問題并不重要。程序應(yīng)該做的是簡單地讀取所有單獨的位并將一個正方形寫入圖像矩形的正確位置,表示存在一個單元格(基于變量 pSize 表示正方形的邊長)。這是那個功能...func renderRow(wg *sync.WaitGroup, img *image.RGBA, i int, pSize int) { defer wg.Done() var lpc = 0 for j := 0; j < 64; j++ { for k := range sim[i] { for l := lpc * pSize; l <= (lpc*pSize)+pSize; l++ { for m := i * pSize; m <= (i*pSize)+pSize; m++ { if getBit(sim[i][k], j) == 1 { img.Set(l, m, black) } else { img.Set(l, m, white) } } } lpc++ } }}現(xiàn)在我很高興地說,當(dāng)在一個線程上按順序運行時,這里的這個函數(shù)的性能和預(yù)期的一樣。這是非并行函數(shù)調(diào)用(忽略等待組)img = image.NewRGBA(image.Rectangle{Min: upLeft, Max: lowRight})for i := range sim { renderRow(&wg, img, i, pSize)}f, _ := os.Create("export/image.png")_ = png.Encode(f, img)另一方面,當(dāng)我們對并發(fā)實現(xiàn)進(jìn)行簡單更改時,輸出有幾個單獨的像素錯誤,并且似乎隨著每次運行的錯誤數(shù)量的變化而隨機(jī)收縮和擴(kuò)展某些行。這是并發(fā)函數(shù)調(diào)用。這是并發(fā)函數(shù)調(diào)用...img = image.NewRGBA(image.Rectangle{Min: upLeft, Max: lowRight})for i := range sim { go renderRow(&wg, img, i, pSize) // TODO make multithreaded again}wg.Wait()f, _ := os.Create("export/image.png")_ = png.Encode(f, img)現(xiàn)在這兩個各自實現(xiàn)的輸出是什么樣的?使用這些起始條件{0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1}和11(pSize 2) 的演化空間。我們將其作為單線程實現(xiàn)的輸出...現(xiàn)在,如果您放大該圖像,您會發(fā)現(xiàn)所有正方形都垂直和水平均勻分布,沒有異常。然而,現(xiàn)在讓我們看看并發(fā)輸出。這個版本似乎有幾個異常,很多行都被縮小了,很多地方都有個別像素錯誤,雖然它正確地遵循了模擬的一般模式,但它肯定在視覺上并不令人愉悅。當(dāng)我在調(diào)查這個問題時,我尋找與并發(fā)相關(guān)的問題,所以我認(rèn)為圖像包中像素數(shù)組的動態(tài)分配可能會導(dǎo)致某種沖突,所以我調(diào)查img.Set()了看起來像這樣的沖突......
1 回答

阿波羅的戰(zhàn)車
TA貢獻(xiàn)1862條經(jīng)驗 獲得超6個贊
上面的代碼產(chǎn)生了許多競爭沖突,這些沖突是由于 go-routines 試圖寫入 .Pix 對象中的相同像素坐標(biāo)而引起的。修復(fù)在renderRow
函數(shù)內(nèi),其中當(dāng)前像素的寬度和高度的計算在每次迭代中由于<=
而不是“<”而重疊。故事的寓意是用于-race
查找沖突并始終查找相同變量的覆蓋或并發(fā)讀取。感謝@rustyx。
- 1 回答
- 0 關(guān)注
- 114 瀏覽
添加回答
舉報
0/150
提交
取消