16

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

4

2 回答 2

18

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

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


如果整个程序使用 运行GOMAXPROCS=1,那么通过调用 schedutils 包中的任务集实用程序来设置 CPU 亲和性相对简单

GOMAXPROCS > 1如果因为goroutine 在运行时在 OS 线程之间迁移,我原以为你不走运。事实上,James Henstridge 指出你可以使用它 runtime.LockOSThread()来防止你的 goroutine 迁移。但是,一旦您将 goroutine 锁定到它,我不知道有任何 Go stdlib 函数来设置当前线程的 CPU 亲和性。您也许可以使用 cgo 和 call pthread_setaffinity_np,因为显然Go 在 cgo 模式下使用 pthreads。由于我们谈论的是系统调用,因此细节会因操作系统而异。

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

于 2013-11-03T22:56:42.900 回答
1

取决于您的工作量,但有时最好为每个 CPU 启动一个 go 进程,将 gomaxprocs 设置为 1 并使用 taskset 将进程固定到 CPU。以下是令人敬畏的 fasthttp 库中关于该主题的摘录:

  • 使用重用端口 监听器。
  • 使用 GOMAXPROCS=1 为每个 CPU 内核运行一个单独的服务器实例。
  • 使用taskset将每个服务器实例固定到单独的 CPU 内核。
  • 保证多队列网卡的中断在CPU核之间均匀分布。有关详细信息,请参阅本文
  • 使用 Go 1.6,因为它提供了一些相当大的性能改进。

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

于 2016-03-01T01:38:54.733 回答