我正在阅读go包“runtime”,看看我可以在其他(func GOMAXPROCS(n int))中设置可用于运行程序的CPU单元数。我可以强制goroutine在我选择的特定CPU上运行吗?
答案 0 :(得分:13)
在现代Go中,我不会将goroutine锁定到线程以提高效率。去1.5 added goroutine scheduling affinity, to minimize how often goroutines switch between OS threads。并且必须权衡CPU之间剩余迁移的任何成本与用户模式调度程序的好处,避免上下文切换到内核模式。最后,当转换成本是一个真正的问题时,有时候更好的关注点是改变你的程序逻辑,因此它需要减少切换,比如通过批量工作而不是单个工作项。
但即使考虑到所有这些,有时你只需要锁定一个goroutine,就像C API需要它一样,我会假设下面是这种情况。
如果整个程序以GOMAXPROCS=1
运行,则it's relatively simple to set a CPU affinity by calling out to the taskset utility from the schedutils package。
我认为你GOMAXPROCS > 1
因为pid
而失败了,因为那时goroutines are migrated between OS threads at runtime。实际上,James Henstridge指出你可以使用runtime.LockOSThread()
来保持你的goroutine不会迁移。但是,一旦你锁定了goroutine,我就不知道任何Go stdlib函数来设置当前线程的CPU亲和力。您可以使用cgo并致电pthread_setaffinity_np
,因为显然Go uses pthreads in cgo mode。由于我们正在讨论系统调用,因此操作系统会有所不同。
(如果您的整个程序都是纯Go(没有C链接),可以通过syscall
模块调用sched_setaffinity
参数为零{{1}}。但是那个&#39 ; s会变得棘手。)
答案 1 :(得分:1)
取决于您的工作负载,但有时为每个CPU启动一个go进程是有益的,将gomaxprocs设置为1并使用taskset将进程固定到CPU。以下是来自awesome fasthttp库的该主题的摘录:
- 使用reuseport 监听器。
- 使用GOMAXPROCS = 1为每个CPU核心运行单独的服务器实例。
- 使用taskset将每个服务器实例固定到单独的CPU核心。
- 确保多核网卡的中断在CPU核心之间均匀分布。请参阅this article 的信息。
- 使用Go 1.6,因为它提供了一些可观的性能改进。
来源:https://github.com/valyala/fasthttp#performance-optimization-tips-for-multi-core-systems