Reputation: 11
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
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