Sayna Sadeghipour
Sayna Sadeghipour

Reputation: 11

golang deadlock error with waitgroups but no channels

im new to go. i have this project it's about matrices and their operations. i am supposed to use goroutine in my multiply function.(also disclaimer:this is not my code, its a group project im supposed to add the goroutine to the function) i've searched around and seen this way(the way that i used) in different sites.however i get a fatal error: all the goroutines are asleep.deadlock! or it just takes way too long for the code to run.


    func (M Matrix) Multiply(N Matrix) Matrix {
        var ans  = BuildZeroMatrix(len(M), len(N[0]))
        var wg sync.WaitGroup
        wg.Add(len(M)*len(N[0])*len(N))
        for i := 0; i < len(M); i++ {
            for j := 0; j < len(N[0]); j++ {
                for k := 0; k < len(N); k++ {
                    wg.Add(1)
                    go func(j int, i int, k int) {
                        ans[i][j] += M[i][k] * N[k][j]
                        defer wg.Done()
                    }(j, i, k)
                }
            }
        }
        go func(){
            wg.Wait()

        }()
        return ans
    }

this is the multiply function.

type Matrix [][]float64

this is Matrix.


    func BuildZeroMatrix(Row int, Col int) Matrix {
        var temp [][]float64
        for i := 0; i < Row; i++ {
            var tmp []float64
            for j := 0; j < Col; j++ {
                tmp = append(tmp, 0)
            }
            temp = append(temp, tmp)
        }
        M, _ := BuildMatrix(Row, Col, temp)
        return M
    }

and this is the buildzeromatrix function. i give the function 2 500*500 matrices and it takes about 10 seconds to run or it gives the fatal error. every post i found on this problem had channels in them and their problem was with the channel.however i dont have any.

Upvotes: 0

Views: 91

Answers (1)

Pratheesh M
Pratheesh M

Reputation: 1078

Just pointing out the mistakes in this snippet. Please check the inline comments.

func (M Matrix) Multiply(N Matrix) Matrix {
    var ans  = BuildZeroMatrix(len(M), len(N[0]))
    var wg sync.WaitGroup
    wg.Add(len(M)*len(N[0])*len(N)) // This is unnecessary. You are already adding the goroutine inside the k loop.
    for i := 0; i < len(M); i++ {
        for j := 0; j < len(N[0]); j++ {
            for k := 0; k < len(N); k++ {
                wg.Add(1)
                go func(j int, i int, k int) {
                    ans[i][j] += M[i][k] * N[k][j] // This is data race area. Multiple goroutines will try to write to the same address. You will need a lock here.
                    defer wg.Done()
                }(j, i, k)
            }
        }
    }
    go func(){
        wg.Wait() // Wait()ing for goroutines to be completed should not be done inside a goroutine. Because here you don't wait for this goroutine to be done.
    }()
    return ans
}

UPDATED: Pls check the sample code

package main

import (
    "fmt"
    "sync"
)

type Matrix [][]float64

func (M Matrix) Multiply(N Matrix) Matrix {
    var ans = BuildZeroMatrix(len(M), len(N[0]))
    var wg sync.WaitGroup
    var mx sync.Mutex
    for i := 0; i < len(M); i++ {
        for j := 0; j < len(N[0]); j++ {
            for k := 0; k < len(N); k++ {
                wg.Add(1)
                go func(j int, i int, k int) {
                    defer wg.Done()
                    mx.Lock()
                    ans[i][j] += M[i][k] * N[k][j]
                    mx.Unlock()
                }(j, i, k)
            }
        }
    }
    wg.Wait()
    return ans
}
func BuildZeroMatrix(Row int, Col int) Matrix {
    var temp [][]float64
    for i := 0; i < Row; i++ {
        var tmp []float64
        for j := 0; j < Col; j++ {
            tmp = append(tmp, 0)
        }
        temp = append(temp, tmp)
    }
    return temp
}

func main() {
    var m, n Matrix

    // T1:
    m = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
    n = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
    fmt.Printf("%v", m.Multiply(n))

    // T2:
    m = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
    n = Matrix{[]float64{1, 1}, []float64{1, 1}, []float64{1, 1}}
    fmt.Printf("\n%v", m.Multiply(n))
}

Upvotes: 2

Related Questions