2 回答

TA貢獻(xiàn)1820條經(jīng)驗(yàn) 獲得超9個贊
您看不到差異,因?yàn)闇?zhǔn)備數(shù)據(jù)以傳遞給 go 例程是您的瓶頸。它比執(zhí)行計算更慢或一樣快。
傳遞行和列的副本不是一個好的策略。這正在扼殺表演。
go 例程可以直接從只讀輸入矩陣中讀取數(shù)據(jù)。這里沒有可能的競爭條件。
輸出也一樣。如果 go 例程計算行和列的乘積,它會將結(jié)果寫入不同的單元格。這里也沒有可能的競爭條件。
要做的事情如下。定義一個包含兩個字段的結(jié)構(gòu),一個用于行,一個用于要相乘的列。
用所有可能的行和列組合填充緩沖通道,以從 (0,0) 乘到 (n-1,m-1)。
go 例程使用通道中的結(jié)構(gòu),執(zhí)行計算并將結(jié)果直接寫入輸出矩陣。
然后,您還有一個 done 通道向主 go 例程發(fā)出計算已完成的信號。當(dāng) goroutine 完成對結(jié)構(gòu) (n-1,m-1) 的處理時,它會關(guān)閉 done 通道。
編寫完所有結(jié)構(gòu)后,主 go 例程在 done 通道上等待。一旦完成通道關(guān)閉,它就會打印經(jīng)過的時間。我們可以使用一個等待組來等待所有的 goroutine 終止他們的計算。
然后,您可以從一個 goroutine 開始,并增加 goroutine 的數(shù)量,以查看處理時間的影響。
見代碼:
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
type pair struct {
row, col int
}
const length = 1000
var start time.Time
var rez [length][length]int
func main() {
const threadlength = 1
pairs := make(chan pair, 1000)
var wg sync.WaitGroup
var a [length][length]int
var b [length][length]int
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
a[i][j] = rand.Intn(10)
b[i][j] = rand.Intn(10)
}
}
wg.Add(threadlength)
for i := 0; i < threadlength; i++ {
go Calc(pairs, &a, &b, &rez, &wg)
}
start = time.Now()
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
pairs <- pair{row: i, col: j}
}
}
close(pairs)
wg.Wait()
elapsed := time.Since(start)
fmt.Println("Binomial took ", elapsed)
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
fmt.Print(rez[i][j])
fmt.Print(" ")
}
fmt.Println(" ")
}
}
func Calc(pairs chan pair, a, b, rez *[length][length]int, wg *sync.WaitGroup) {
for {
pair, ok := <-pairs
if !ok {
break
}
rez[pair.row][pair.col] = 0
for i := 0; i < length; i++ {
rez[pair.row][pair.col] += a[pair.row][i] * b[i][pair.col]
}
}
wg.Done()
}

TA貢獻(xiàn)1831條經(jīng)驗(yàn) 獲得超10個贊
您的代碼很難理解(調(diào)用變量 dummy1/dummy2 會讓人感到困惑,特別是當(dāng)它們在 中獲得不同的名稱時Calc)并且添加一些注釋會使它更容易理解。
首先是一個錯誤。在發(fā)送要計算的數(shù)據(jù)之后dummy1 <- -1,我相信您希望這會等待所有計算完成。但是,當(dāng)您有多個 goroutine 時,情況不一定如此。通道將被其中一個 goroutine 耗盡,并打印出計時信息;其他 goroutine 仍將運(yùn)行(并且可能尚未完成計算)。
在時間方面,我懷疑您向 go 例程發(fā)送數(shù)據(jù)的方式會減慢速度;您發(fā)送行,然后發(fā)送列;因?yàn)橥ǖ罌]有緩沖,所以 goroutine 將在等待列時阻塞(切換回主 goroutine 以發(fā)送列)。這種來回會減慢你的 goroutines 獲取數(shù)據(jù)的速度,并且可以很好地解釋為什么添加額外的 goroutines 影響有限(如果你使用緩沖通道也會變得危險)。
我已將您的代碼(注意可能存在錯誤,而且遠(yuǎn)非完美?。┲貥?gòu)為確實(shí)顯示出差異的東西(在我的計算機(jī)上 1 goroutine = 10s; 5 = 7s):
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
const length = 1000
var start time.Time
var rez [length][length]int
// toMultiply will hold details of what the goroutine will be multiplying (one row and one column)
type toMultiply struct {
rowNo int
columnNo int
row []int
column []int
}
func main() {
const noOfGoRoutines = 5
// Build up a matrix of dimensions (length) x (length)
var a [length][length]int
var b [length][length]int
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
a[i][j] = rand.Intn(10)
b[i][j] = rand.Intn(10)
}
}
// Setup completed so start the clock...
start = time.Now()
// Start off threadlength go routines to multiply each row/column
toCalc := make(chan toMultiply)
var wg sync.WaitGroup
wg.Add(noOfGoRoutines)
for i := 0; i < noOfGoRoutines; i++ {
go func() {
Calc(toCalc)
wg.Done()
}()
}
// Begin the multiplication.
start = time.Now()
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
tm := toMultiply{
rowNo: i,
columnNo: j,
row: make([]int, length),
column: make([]int, length),
}
for k := 0; k < length; k++ {
tm.row[k] = a[i][j]
tm.column[k] = b[i][k]
}
toCalc <- tm
}
}
// All of the data has been sent to the chanel; now we need to wait for all of the
// goroutines to complete
close(toCalc)
wg.Wait()
fmt.Println("Binomial took ", time.Since(start))
// The full result should be in tz
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
//fmt.Print(rez[i][j])
//fmt.Print(" ")
}
//fmt.Println(" ")
}
}
// Calc - Multiply a row from one matrix with a column from another
func Calc(toCalc <-chan toMultiply) {
for tc := range toCalc {
var result int
for i := 0; i < len(tc.row); i++ {
result += tc.row[i] * tc.column[i]
}
// warning - the below should work in this case but be careful writing to global variables from goroutines
rez[tc.rowNo][tc.columnNo] = result
}
}
- 2 回答
- 0 關(guān)注
- 136 瀏覽
添加回答
舉報