所以,我有一段并发的代码,它意味着要运行到每个CPU /核心上。
有两个具有输入/输出值的大向量
var (
input = make([]float64, rowCount)
output = make([]float64, rowCount)
)
这些是填充的,我想计算每个输入 - 输出对之间的距离(误差)。作为独立的对,可能的并发版本如下:
var d float64 // Error to be computed
// Setup a worker "for each CPU"
ch := make(chan float64)
nw := runtime.NumCPU()
for w := 0; w < nw; w++ {
go func(id int) {
var wd float64
// eg nw = 4
// worker0, i = 0, 4, 8, 12...
// worker1, i = 1, 5, 9, 13...
// worker2, i = 2, 6, 10, 14...
// worker3, i = 3, 7, 11, 15...
for i := id; i < rowCount; i += nw {
res := compute(input[i])
wd += distance(res, output[i])
}
ch <- wd
}(w)
}
// Compute total distance
for w := 0; w < nw; w++ {
d += <-ch
}
我们的想法是为每个CPU /核心配备一名工作人员,每个工作人员处理一部分行。
我遇到的问题是这段代码并不比串行代码快。
现在,我正在使用Go 1.7,因此runtime.GOMAXPROCS
应该已设置为runtime.NumCPU()
,但即使明确设置也不会提高性能。
(a-b)*(a-b)
; math.Pow
和math.Sqrt
函数); 因此,除了访问全局数据(输入/输出)以进行读取之外,还没有我知道的锁定/互斥锁(例如,不使用math/rand
)。
我也用-race
编译,没有出现。
我的主机有4个虚拟内核,但是当我运行这个代码时,我得到(使用htop)CPU使用率达到102%,但我预计会有大约380%的内容,因为过去发生的其他代码使用了所有的芯
我想调查,但我不知道运行时如何分配线程和调度goroutines。
如何调试此类问题?在这种情况下pprof
可以帮助我吗?那个runtime
包怎么样?
提前致谢
答案 0 :(得分:1)
抱歉,但最后我的测量结果出错了。 @JimB是对的,我有一个轻微的泄漏,但没有那么多来证明这种程度的减速是正确的。
我的期望太高了:我正在制作并发的功能只在程序开始时调用,因此性能提升很小。
将模式应用到程序的其他部分后,我得到了预期的结果。我在评估哪个部分是最重要的错误。
无论如何,我同时学到了很多有趣的东西,所以非常感谢所有想要帮助的人!