#channel #parallels
Вопрос:
Я столкнулся с ошибкой, когда пытался добавить фиксированное значение к каждому элементу матрицы в моем игрушечном примере. Моя мысль состояла в том, чтобы разделить всю матрицу на несколько подматриц и использовать карту для хранения начального индекса и подматрицы во время параллельных вычислений. Я уже выполнил это предыдущее требование. Но когда я хотел бы пойти дальше, я хотел бы, чтобы мои границы взаимодействовали друг с другом и в то же время не теряли никакой полезной информации, как в играх с клеточными автоматами, их положение определялось бы некоторыми соседями. Поэтому вместо того, чтобы идеально разделять всю матрицу, я намеренно добавляю несколько избыточных строк, чтобы границы могли получить правильное значение, как показано ниже, и в заключительной части комбинации я мог бы просто оставить эти неправильные границы и сохранить правильное вычисленное тело.
Предположим, у нас есть три процессора, а входная матрица представляет собой матрицу 10 на 10. Поэтому я бы создал три процедуры go. Как предлагалось ранее, я разрешаю некоторым помещениям обрабатывать пограничную ситуацию. Поэтому я выделил некоторое пространство или перекрытие между различными подразделениями во время сегментации. Для достижения этой цели я вручную добавляю одну строку перед подплатей и одну строку после подплати, что означает, что я должен написать три утверждения if, первая ситуация-подплата начинается с 0, мы могли бы добавить только одну строку из следующей подплати. Вторая ситуация была бы средней, добавьте одну строку сверху и одну строку снизу снизу. Последняя ситуация состояла бы в том, чтобы не добавлять еще одну строку снизу. Однако, когда я пытаюсь запустить код параллельно, кажется, что во время горутины произошло некоторое загрязнение, и я понятия не имел, как это произойдет. Предположительно, входная подплата перед подпрограммой goroutine и подплата в подпрограмме go должны быть одинаковыми, хотя порядок может отличаться. В этом случае значение в функции goroutine может быть загрязнено. Я понятия не имел, почему может возникнуть такая ситуация. Поскольку метод печати и метод точки останова могут не работать в параллельном программировании. Я действительно в замешательстве и понятия не имею, что происходит в этом случае. Я также приложил приведенный ниже код, если вы хотите его скопировать.
func TestParallelMatrixMapInteraction(t *testing.T) { wg := sync.WaitGroup{} boards := GenerateMatrix(10) //for i := 0; i lt; 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 lt; len(subBoard); i { for j := 0; j lt; 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 lt;- 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 lt; 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 lt; 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 lt; numProcess; i { subBoardMap := lt;-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 lt; actualEnd; j { newBoard[j] = subBoard[j-actualStart] } } wg.Wait() fmt.Println("=================ready to draw the matrix====================") for i := 0; i lt; len(newBoard); i { fmt.Println(newBoard[i]) } } func GenerateMatrix(size int) [][]int { board := make([][]int, size) for i := 0; i lt; size; i { board[i] = make([]int, size) } for i := 0; i lt; len(board); i { for j := 0; j lt; len(board[0]); j { board[i][j] = i } } return board } func GenerateEmptyMatrix(size int) [][]int { board := make([][]int, size) for i := 0; i lt; size; i { board[i] = make([]int, size) } return board }
Я также приложил предыдущие упомянутые примеры правильно выполненных матриц, и мне действительно любопытно, в чем причина этой разницы и где на самом деле моя ошибка.
func TestParallelMatrixMap(t *testing.T) { wg := sync.WaitGroup{} boards := GenerateMatrix(20) for i := 0; i lt; 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 lt; len(subBoard); i { for j := 0; j lt; len(subBoard[0]); j { subBoard[i][j] = 4 } } subBoardMap := make(map[int][][]int) subBoardMap[startIdx] = subBoard c lt;- subBoardMap } c := make(chan map[int][][]int, subRows) // iterate through all the available number of process for i := 0; i lt; numProcess; i { // split into numProcess approx . equal pieces startIdx := i * subRows endIdx := (i 1) * subRows if i lt; 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 lt; numProcess; i { subBoardMap := lt;-c var startIdx int var subBoard [][]int for idx, value := range subBoardMap { startIdx = idx subBoard = value } endIdx := startIdx len(subBoard) for j := startIdx; j lt; endIdx; j { newBoard[j] = subBoard[j-startIdx] } } wg.Wait() fmt.Println("=================ready to draw the matrix====================") for i := 0; i lt; len(newBoard); i { fmt.Println(newBoard[i]) } }
Ответ №1:
Я нашел ответ сам, обычно это была бы проблема с мелкой копией и глубокой копией в срезе голанга. Поскольку я использовал метод [startIdx-1:endIdx 1] для добавления двух смежных строк, и из-за внутренней природы беспорядка во время параллельных вычислений в goroutine, предыдущие строки могли быть изменены, что объясняет ситуацию, когда мой вывод будет беспорядочным и без порядка.
Чтобы избежать этой проблемы, вы можете создать функцию копирования, которая создаст новый срез, повторит старый и присвоит значение новому. Только таким образом срез, который мы получили, был бы глубокой копией и независимым от других модификаций.