如何检测什么阻止golang中使用多个核心?

时间:2017-02-21 20:30:11

标签: go concurrency goroutine

所以,我有一段并发的代码,它意味着要运行到每个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.Powmath.Sqrt函数);
  • 没有其他goroutine正在运行。

因此,除了访问全局数据(输入/输出)以进行读取之外,还没有我知道的锁定/互斥锁(例如,不使用math/rand)。

我也用-race编译,没有出现。

我的主机有4个虚拟内核,但是当我运行这个代码时,我得到(使用htop)CPU使用率达到102%,但我预计会有大约380%的内容,因为过去发生的其他代码使用了所有的芯

我想调查,但我不知道运行时如何分配线程和调度goroutines。

如何调试此类问题?在这种情况下pprof可以帮助我吗?那个runtime包怎么样?

提前致谢

1 个答案:

答案 0 :(得分:1)

抱歉,但最后我的测量结果出错了。 @JimB是对的,我有一个轻微的泄漏,但没有那么多来证明这种程度的减速是正确的。

我的期望太高了:我正在制作并发的功能只在程序开始时调用,因此性能提升很小。

将模式应用到程序的其他部分后,我得到了预期的结果。我在评估哪个部分是最重要的错误。

无论如何,我同时学到了很多有趣的东西,所以非常感谢所有想要帮助的人!