问题 是否可以强制在特定的CPU上运行go例程?


我正在阅读go包“runtime”,看看我可以在其他(func GOMAXPROCS(n int))中设置可用于运行程序的CPU单元数。我可以强制goroutine在我选择的特定CPU上运行吗?


2539
2017-11-03 22:26


起源

据说FWIW go 1.5具有“更智能的调度程序”,CPU可以更准确地避免在例程之间进行缓存未命中。我猜这有点像CPU亲和力...... - rogerdpack


答案:


在现代Go中,我不会将goroutine锁定到线程以提高效率。去1.5 添加了goroutine调度亲和性,以最小化goroutines在OS线程之间切换的频率。并且必须权衡CPU之间剩余迁移的任何成本与用户模式调度程序的好处,从而避免上下文切换到内核模式。最后,当转换成本是一个真正的问题时,有时候更好的关注点是改变你的程序逻辑,因此它需要减少切换,比如通过批量工作而不是单个工作项。

但即使考虑到所有这些,有时你只需要锁定一个goroutine,就像C API需要它一样,我会假设下面就是这种情况。


如果整个程序运行 GOMAXPROCS=1, 然后 通过从schedutils包调用taskset实用程序来设置CPU关联性相对简单

我曾经以为你运气不好 GOMAXPROCS > 1 因为那时候 goroutines在运行时在OS线程之间迁移。事实上,James Henstridge指出你可以使用 runtime.LockOSThread() 保持你的goroutine不迁移。但是,一旦你锁定了goroutine,我不知道任何Go stdlib函数来设置当前线程的CPU亲和力。您可以使用cgo并致电 pthread_setaffinity_np,显然 Go在cgo模式下使用pthreads。由于我们讨论的是系统调用,因此操作系统的细节会有所不同。

(如果你的整个程序都是纯粹的Go(没有C链接),它可能会调用 sched_setaffinity 零 pid 参数通过 syscall 模块。但那会很棘手。)


10
2017-11-03 22:56



您可以将goroutine锁定到特定的OS线程 runtime.LockOSThread 虽然。这可以与底层的OS CPU亲和程序一起使用来实现目标。 - James Henstridge
哦谢谢!更新。 - twotwotwo


取决于您的工作负载,但有时每个CPU启动一个go进程是有益的,将gomaxprocs设置为1并使用taskset将进程固定到CPU。以下是来自awesome fasthttp库的关于该主题的摘录:

  • 使用 reuseport   监听器。
  • 使用GOMAXPROCS = 1为每个CPU核心运行单独的服务器实例。
  • 使用将每个服务器实例固定到单独的CPU核心 包括taskset
  • 确保多核网卡的中断均匀分布在CPU内核之间。看到 这个   文章 对于   细节。
  • 使用Go 1.6,因为它提供了一些可观的性能改进。

资源: https://github.com/valyala/fasthttp#performance-optimization-tips-for-multi-core-systems


1
2018-03-01 01:38