Go例程Matrix乘法错误

时间:2018-05-06 04:34:11

标签: go parallel-processing goroutine indexoutofrangeexception

我使用go例程并行地将矩阵相乘。我的索引超出范围,但是当我运行相同的代码顺序时,它的工作原理。 (顺序我的意思是评论go line)。我正在使用延迟所以我不必等待我的例程结束,因为它将是最后一个叫做

错误     D:\ 0000>去运行Ap.go     恐慌:运行时错误:索引超出范围

goroutine 5 [running]:
main.pmultiply(0xc04206c000, 0x3, 0x3, 0xc04206c050, 0x3, 0x3, 0x1, 0x3, 0x0)
        D:/0000/Ap.go:48 +0x95
main.multiply.func1(0xc04206c0a0, 0x3, 0x3, 0xc04200e090, 0xc04200e098, 0xc04206
c000, 0x3, 0x3, 0xc04206c050, 0x3, ...)
        D:/0000/Ap.go:64 +0x94
created by main.multiply
        D:/0000/Ap.go:63 +0x1d7
exit status 2

CODE

package main

import "fmt"

func main(){

    matrix_a := make([][]int,3);

    for i:=0;i<len(matrix_a);i++{

        matrix_a[i]=make([]int,3);

    }


    for i:=0;i<len(matrix_a);i++{

        for j:=0;j<len(matrix_a[0]);j++{
            matrix_a[i][j] = 2;
        }
    }

    matrix_b := make([][]int,3);

    for i:=0;i<len(matrix_b);i++{

        matrix_b[i]=make([]int,3);

    }


    for i:=0;i<len(matrix_b);i++{

        for j:=0;j<len(matrix_b[0]);j++{
            matrix_b[i][j] = 2;
        }
    }

    defer fmt.Println(multiply(matrix_a,matrix_b));

}

func pmultiply(matrix_a [][] int,matrix_b [][] int,row int,col int) int{

    sum := 0;

    for z:=0;z<len(matrix_a[0]);z++{
        sum = sum + matrix_a[row][z] *  matrix_b[z][col];
    }
    return sum;
}

func multiply(matrix_a [][] int,matrix_b [][] int) ([][] int){

    matrix_c := make([][]int,3);

    for i:=0;i<len(matrix_c);i++{
        matrix_c[i]=make([]int,3);
    }

    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            go func(){
                matrix_c[i][j] = pmultiply(matrix_a,matrix_b,i,j);
            }()
        }   
    }

    return matrix_c;
}

1 个答案:

答案 0 :(得分:1)

我看到两个问题:

  1. const urlReg = /((\w*?)((:\/\/)|www|\w\.{1}\w{2,})[^"<\s]+)(?![^<>]*>|[^"]*?<\/a)/g; multiplyij中存在经典的闭包问题。
  2. matrix_c返回multiply之前,无法保证计算for i := 0; i < 3; i++ { for j := 0; j < 3; j++ { go func(){ matrix_c[i][j] = pmultiply(matrix_a,matrix_b,i,j); }() } }
  3. 第一个就在这里:

    i

    匿名函数在j时保留对ij的引用,而不是go func() { ... }()i的实际值,因此当goroutine执行时,ji可以是0到3之间的任何值(包含)。这就是你知道的错误来自:ji是三,因为goroutine在循环完成后正在执行。最简单的解决方案是在正确的时间强制jgo func(i, j int) { matrix_c[i][j] = pmultiply(matrix_a, matrix_b, i, j) }(i, j) 进行评估:

    return matrix_c

    第二个问题是,在你import "sync"之前,goroutines不一定都会完成,甚至没有保证任何一个都能完成。最简单的解决方案是使用https://testask.com/item/45e20490-2b86-4b6a-8772-5ed96f64de52等待它们完成。首先你var wg sync.WaitGroup for i := 0; i < 3; i++ { for j := 0; j < 3; j++ { wg.Add(1) // Tell the WaitGroup to wait for another thing. go func(i, j int) { matrix_c[i][j] = pmultiply(matrix_a, matrix_b, i, j) wg.Done() // Tell it that we're done. }(i, j) } } ,然后调整循环:

    wg.Wait()
    return matrix_c
    

    然后在返回前等待:

    defer

    对评论的回复: defer不起作用,sync.WaitGroup

      

    “defer”语句调用一个函数,该函数的执行被推迟到周围函数返回的那一刻,因为周围的函数执行了一个return语句,到达了它的函数体的末尾,或者因为相应的goroutine是恐慌的。 / p>

    就是这样,当执行离开周围的功能时,它会安排执行某些操作。 TheLabel.color = UIColor.black.withAlphaComponent(0.2) 与等待线程/ goroutine无关,也不知道延迟函数可能创建的goroutine。