gpt4 book ai didi

go - "Matrix multiplication"使用 goroutine 和 channel

转载 作者:行者123 更新时间:2023-12-01 22:37:20 27 4
gpt4 key购买 nike

当我使用 1 个 goroutine、2 个 goroutine、3 个等等时,我有一个大学项目来测试矩阵乘法的时间差。我必须使用 channel 。我的问题是,无论我添加多少 goroutine,编译时间几乎总是相同的。也许有人能说出问题出在哪里。也许发送时间很长,并且一直在发送。代码如下

package main
import (
"fmt"
"math/rand"
"time"
)
const length = 1000
var start time.Time
var rez [length][length]int
func main() {
const threadlength = 1
toCalcRow := make(chan []int)
toCalcColumn := make(chan []int)
dummy1 := make(chan int)
dummy2 := make(chan int)
var row [length + 1]int
var column [length + 1]int
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)
}
}
for i := 0; i < threadlength; i++ {
go Calc(toCalcRow, toCalcColumn, dummy1, dummy2)
}
start = time.Now()
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
row[0] = i
column[0] = j
for k := 0; k < length; k++ {
row[k+1] = a[i][j]
column[k+1] = b[i][k]
}
rowSlices := make([]int, len(row))
columnSlices := make([]int, len(column))
copy(rowSlices, row[:])
copy(columnSlices, column[:])
toCalcRow <- rowSlices
toCalcColumn <- columnSlices
}
}
dummy1 <- -1
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
fmt.Print(rez[i][j])
fmt.Print(" ")
}
fmt.Println(" ")
}
<-dummy2
close(toCalcRow)
close(toCalcColumn)
close(dummy1)
}
func Calc(chin1 <-chan []int, chin2 <-chan []int, dummy <-chan int, dummy1 chan<- int) {
loop:
for {
select {
case row := <-chin1:
column := <-chin2
var sum [3]int
sum[0] = row[0]
sum[1] = column[0]
for i := 1; i < len(row); i++ {
sum[2] += row[i] * column[i]
}
rez[sum[0]][sum[1]] = sum[2]
case <-dummy:
elapsed := time.Since(start)
fmt.Println("Binomial took ", elapsed)
dummy1 <- 0
break loop
}
}
close(dummy1)
}

最佳答案

您看不到差异,因为准备数据以传递给 go 例程是您的瓶颈。它比执行计算更慢或一样快。

传递行和列的副本不是一个好的策略。这正在扼杀表演。

go 例程可以直接从只读输入矩阵中读取数据。这里没有可能的竞争条件。

输出也一样。如果 go 例程计算行和列的乘积,它会将结果写入不同的单元格。这里也没有可能的竞争条件。

要做的事情如下。定义一个包含两个字段的结构,一个用于行,一个用于要相乘的列。

用所有可能的行和列组合填充缓冲 channel ,以从 (0,0) 乘到 (n-1,m-1)。

go 例程使用 channel 中的结构,执行计算并将结果直接写入输出矩阵。

然后,您还有一个 done channel 向主 go 例程发出计算已完成的信号。当 goroutine 完成对结构 (n-1,m-1) 的处理时,它会关闭 done channel 。

编写完所有结构后,主 go 例程在 done channel 上等待。一旦完成 channel 关闭,它就会打印耗时。
我们可以使用一个 WaitGroup 来等待所有的 goroutine 终止他们的计算。

然后,您可以从一个 goroutine 开始,并增加 goroutine 的数量,以查看处理时间的影响。

见代码:

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()
}

关于go - "Matrix multiplication"使用 goroutine 和 channel ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59128141/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com