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

假设我们有三个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])
    }

}