为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Go 通道加速 for 循环

使用 Go 通道加速 for 循环

Go
回首忆惘然 2022-01-17 16:31:28
我正在尝试使用 Go 的并发性来加速我的代码,这是我所拥有的:            for i:=7; i>-1; i-- {                go func (ch chan int32, ch2 chan int32, i int, arx int32, ary int32, dirf []int8, dirg []int8) {                    nx := arx + int32(dirf[i])                    ny := ary + int32(dirg[i])                    ch <- nx                    ch2 <- ny                }(ch, ch2, i, arx,ary,dirf,dirg)            }            for i:=7; i>-1; i-- {                nxx := <- ch                nyx := <- ch2                ind := nyx*w+nxx                if imData[ind] == e[i]{                    process[c]=nxx                    process[c+1]=nyx                    c+=2                    matrix[ind]=1                }            }运行此之后,我没有得到我期望的矩阵切片,它充满了零。但是如果我运行下面的代码,它会给出矩阵切片,就像没有通道的代码一样,但它太慢了。            for i:=7; i>-1; i-- {                go func (ch chan int32, ch2 chan int32, i int, arx int32, ary int32, dirf []int8, dirg []int8) {                    nx := arx + int32(dirf[i])                    ny := ary + int32(dirg[i])                    ch <- nx                    ch2 <- ny                }(ch, ch2, i, arx,ary,dirf,dirg)                nxx := <- ch                nyx := <- ch2                ind := nyx*w+nxx                if imData[ind] == e[i]{                    process[c]=nxx                    process[c+1]=nyx                    c+=2                    matrix[ind]=1                }            }第一个有什么问题?有任何想法吗?我对 Go 很陌生。所以,当你提出一些建议时,请清楚。
查看完整描述

2 回答

?
波斯汪

TA贡献1811条经验 获得超4个赞

在第二种情况下,您确定 goroutines 是“以正确的顺序”执行的,因为您在继续执行下一个之前等待 goroutines 完成。

golang 操场上的这个最小示例就是一个例子。要解决此问题,您可能希望通过通道传递三个成员的结构,即 your和nxvalues 。nyi


查看完整回答
反对 回复 2022-01-17
?
慕斯王

TA贡献1864条经验 获得超2个赞

我怀疑您的“if imData[ind] == e[i]”条件在前一种情况下失败了,但是如果没有通道的设置代码以及有关这些不同切片的更多详细信息,就很难判断。您是否尝试过使用 print 语句运行它以查看您从渠道中获得了什么?

另外,请注意,如果有问题的通道被缓冲,则不能保证ch和中的值ch2将以相同的顺序排列。这很可能是你的问题。

Goroutine 1 可以给 on 赋值ch,但是 Goroutine 2 可以ch2在 Goroutine 1 到达之前给 on 赋值。如果您有 7 个 goroutine,则完全有可能在通道(或任意数量的其他通道)上看到以下顺序:

ch: 1, 2, 3, 4, 5, 6, 7

ch2: 1, 3, 4, 5, 6, 7, 2

如果它们没有被缓冲,那么这对你的代码来说是不可能的,但它在技术上仍然是不安全的(编辑:实际上,它仍然不会与i第二个循环匹配)。如果数据是一组有序对,您应该通过单个通道将每对作为结构发送。

顺便说一句,您只需要将变量传递给go func()调用,如果它们预计会在调用之外发生变化。 chch2arxarydirf, 和dirg所有这些对于这段代码来说似乎都是有效的常量,因此不需要传递给go func(). 您只需要传入i,因为循环在将外壳触发到 goroutine 后立即更改它。

现在,从纯粹的速度角度来看,您最好将第一个循环移动到go func()调用中。您可以在主例程中循环时创建 7 个 goroutine,而不是创建一个例程,它会循环遍历这些值并将它们发送到通道上。如果通道被缓冲到至少那个大小,这将成为一个非常快速的操作。顺便说一句,这也解决了通道排序的问题(尽管在单个通道上将有序对作为结构发送仍然更好),因为您只有一个 goroutine 试图在通道上发送。


查看完整回答
反对 回复 2022-01-17
  • 2 回答
  • 0 关注
  • 264 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信