【发布时间】:2021-12-25 05:33:02
【问题描述】:
当我尝试在我的玩具示例中为矩阵的每个元素添加一个固定值时,我遇到了一个错误。我的想法是将整个矩阵分成几个子矩阵,并在并行计算期间使用映射来保存起始索引和子矩阵。我已经完成了之前的要求。但是当我想更进一步时,我想让我的边界相互交互,同时不丢失任何有用的信息,就像元胞自动机游戏一样,它们的位置将由一些邻居决定。因此,我并没有将整个矩阵分割成完美的方式,而是特意添加了一些冗余行,让边界获得正确的值,如下面的方式,在最后的组合部分,我可以简单地留下那些不正确的边界并保留正确的计算体。
假设我们有 3 个 CPU,输入矩阵是 10 x 10 矩阵。因此,我将创建三个围棋例程。如前所述,我允许一些房间来处理边界情况。因此,我在分割过程中在不同子板之间留出了一些空间或重叠。为了达到目的,我手动在子板前加一行,在子板后加一行,也就是说我要写三个if语句,第一种情况是子板以0开头,我们只能添加下一个子板的一排。第二种情况是中间的情况,在顶部之前添加一排,从下方添加一排底部。最后一种情况是不要从下面添加另一行。但是,当我尝试并行运行代码时,似乎在 goroutine 期间发生了一些污染,我不知道这是怎么发生的。假设 goroutine 之前的输入子板和 go-routine 中的子板应该是相同的,尽管顺序可能不同。在这种情况下,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
}
我还附上了前面提到的正确运行的矩阵示例,我真的很好奇导致这种差异的原因以及我的错误到底在哪里。
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])
}
}
【问题讨论】: