当我试图向我的玩具示例中的矩阵的每个元素添加一个固定值时,我遇到了一个错误。我的想法是将整个矩阵分成几个子矩阵,并在并行计算时使用一个映射来保存起始索引和子矩阵。我已经完成了前面的要求。但是当我想更进一步的时候,我想让我的边界彼此交互,同时不会丢失任何有用的信息,就像细胞自动机游戏一样,它们的位置将由一些邻居决定。因此,我没有将整个矩阵分离成一种完美的方式,而是故意添加了一些冗余的行,以允许边界获得正确的值,就像下面这样,在最终的组合部分中,我可以简单地保留那些不正确的边界,并保留正确的计算主体。

假设我们有三个CPU,输入矩阵是一个10 x 10的矩阵。因此,我将创建三个go例程。正如前面所建议的,我允许一些房间来处理边界情况。因此,在分割过程中,我在不同的子板之间留出了一些空间或重叠。为了达到这个目的,我手动在子板之前添加一行,在子板之后添加一行,这意味着我必须编写三个if语句,第一种情况是子板从0开始,我们只能从下一个子板添加一行。第二种情况是中间的情况,在顶部之前添加一行,从底部添加一行。最后一种情况是不从下面添加另一行。然而,当我尝试并行运行代码时,似乎在goroutine过程中发生了一些污染,我不知道这是如何发生的。假设,goroutine之前的输入子板和go例程中的子板应该是相同的,尽管顺序可能不同。在这种情况下,goroutine函数中的值可能会受到污染。我不知道为什么会发生这种情况。因为打印方法和断点方法可能无法在并行编程中工作。我真的很困惑,不知道在这种情况下发生了什么。我还附上了下面的代码,如果你想复制它。
func TestParallelMatrixMapInteraction(t *testing.T) {
wg := sync.WaitGroup{}
boards := GenerateMatrix(10)
//for i := 0; i < len(boards); i++ {
// fmt.Println(boards[i])
//}
numProcess := 3
nRows := len(boards)
subRows := nRows / numProcess
sumRow := func(subBoard [][]int, c chan map[int][][]int, startIdx int) {
// input
fmt.Println("The input of subBoard in goroutine: ", subBoard, "with start idx ",startIdx)
defer wg.Done()
for i := 0; i < len(subBoard); i++ {
for j := 0; j < len(subBoard[i]); j++ {
subBoard[i][j] += 4
//fmt.Println(subBoard[i][j])
}
}
subBoardMap := make(map[int][][]int)
subBoardMap[startIdx] = subBoard
//fmt.Println("After the modification, the subBoard is:", subBoardMap)
c <- subBoardMap
}
c := make(chan map[int][][]int)
//c := make(chan map[int][][]int, subRows)
// iterate through all the available number of process
for i := 0; i < numProcess; i++ {
// split into numProcess approx . equal pieces
startIdx := i * subRows
endIdx := (i + 1) * subRows
if startIdx ==0 {
wg.Add(1)
subBoard := boards[startIdx : endIdx+1]
fmt.Println("The input of subBoard: ", subBoard, "with start idx ",startIdx)
go sumRow(subBoard, c, startIdx)
} else if i < numProcess-1 {
wg.Add(1)
subBoard := boards[startIdx-1 : endIdx+1]
fmt.Println("The input of subBoard: ", subBoard, "with start idx ",startIdx-1)
go sumRow(subBoard, c, startIdx-1)
} else { // i = numProcess -1
wg.Add(1)
subBoard := boards[startIdx-1:]
fmt.Println("The input of subBoard: ", subBoard, "with start idx ",startIdx-1)
go sumRow(subBoard, c, startIdx-1)
}
}
newBoard := GenerateEmptyMatrix(10)
for i := 0; i < numProcess; i++ {
subBoardMap := <-c
//fmt.Println("=====================================")
//fmt.Println("The output from channel: It would be a map",subBoardMap)
var startIdx int
var subBoard [][]int
for idx, value := range subBoardMap {
startIdx = idx
subBoard = value
}
endIdx := startIdx + len(subBoard)
var actualStart int
var actualEnd int
if startIdx == 0 {
actualStart = startIdx
actualEnd = actualEnd - 1
} else if endIdx == len(newBoard) {
actualStart = startIdx + 1
actualEnd = endIdx
} else {
actualStart = startIdx + 1
actualEnd = endIdx - 1
}
for j := actualStart; j < actualEnd; j++ {
newBoard[j] = subBoard[j-actualStart]
}
}
wg.Wait()
fmt.Println("=================ready to draw the matrix====================")
for i := 0; i < len(newBoard); i++ {
fmt.Println(newBoard[i])
}
}
func GenerateMatrix(size int) [][]int {
board := make([][]int, size)
for i := 0; i < size; i++ {
board[i] = make([]int, size)
}
for i := 0; i < len(board); i++ {
for j := 0; j < len(board[0]); j++ {
board[i][j] = i
}
}
return board
}
func GenerateEmptyMatrix(size int) [][]int {
board := make([][]int, size)
for i := 0; i < size; i++ {
board[i] = make([]int, size)
}
return board
}
我还附上了前面提到的正确运行矩阵样本,我真的很好奇是什么导致了这种差异,以及我的bug到底在哪里。
func TestParallelMatrixMap(t *testing.T) {
wg := sync.WaitGroup{}
boards := GenerateMatrix(20)
for i := 0; i < len(boards); i++ {
fmt.Println(boards[i])
}
numProcess := 3
nRows := len(boards)
subRows := nRows / numProcess
sumRow := func(subBoard [][]int, c chan map[int][][]int, startIdx int) {
fmt.Println("The input of subBoard in goroutine: ", subBoard, "with start idx ",startIdx)
defer wg.Done()
for i := 0; i < len(subBoard); i++ {
for j := 0; j < len(subBoard[0]); j++ {
subBoard[i][j] += 4
}
}
subBoardMap := make(map[int][][]int)
subBoardMap[startIdx] = subBoard
c <- subBoardMap
}
c := make(chan map[int][][]int, subRows)
// iterate through all the available number of process
for i := 0; i < numProcess; i++ {
// split into numProcess approx . equal pieces
startIdx := i * subRows
endIdx := (i + 1) * subRows
if i < numProcess-1 {
wg.Add(1)
go sumRow(boards[startIdx:endIdx], c, startIdx)
} else { // i = numProcess -1
wg.Add(1)
go sumRow(boards[startIdx:], c, startIdx)
}
}
newBoard := GenerateEmptyMatrix(20)
for i := 0; i < numProcess; i++ {
subBoardMap := <-c
var startIdx int
var subBoard [][]int
for idx, value := range subBoardMap {
startIdx = idx
subBoard = value
}
endIdx := startIdx + len(subBoard)
for j := startIdx; j < endIdx; j++ {
newBoard[j] = subBoard[j-startIdx]
}
}
wg.Wait()
fmt.Println("=================ready to draw the matrix====================")
for i := 0; i < len(newBoard); i++ {
fmt.Println(newBoard[i])
}
}