英文:
is it possible to force a go routine to be run on a specific CPU?
问题
我正在阅读关于Go语言包“runtime”的内容,发现我可以使用其中的函数(如func GOMAXPROCS(n int))来设置可以用于运行我的程序的CPU单元数量。我是否可以强制将一个goroutine运行在我选择的特定CPU上?
英文:
I am reading about the go package "runtime" and see that i can among other (func GOMAXPROCS(n int)) set the number of CPU units that can be used to run my program. Can I force a goroutine to be run on a specific CPU of my choice?
答案1
得分: 20
在现代的Go语言中,为了提高效率,我不会将goroutine锁定到线程上。Go 1.5引入了goroutine调度亲和性,以最小化goroutine在操作系统线程之间切换的频率。剩余的CPU迁移成本必须与用户模式调度器避免上下文切换到内核模式的好处相权衡。最后,当切换成本成为真正的问题时,有时更好的方法是改变程序逻辑,使其需要较少的切换,例如通过批量通信而不是单个工作项通信。
但是,即使考虑到所有这些,有时你仍然需要锁定一个goroutine,比如当一个C API需要时,我假设下面的情况就是这种情况。
如果整个程序以GOMAXPROCS=1
运行,那么可以通过调用schedutils包中的taskset实用程序来相对简单地设置CPU亲和性。
我曾经认为如果GOMAXPROCS > 1
,那么当时没有办法设置CPU亲和性,因为在运行时goroutine会在操作系统线程之间迁移。事实上,James Henstridge指出你可以使用runtime.LockOSThread()
来防止goroutine迁移。
这并不能解决将操作系统线程锁定到CPU的问题。@yerden在评论中指出,使用golang.org/x/sys/unix
包中的SchedSetaffinity
函数,将pid设置为0,应该可以将调用线程锁定到其当前CPU。
在“C API需要锁定”的用例中,从C代码中调用pthread_setaffinity_np
也可能起作用。
我没有测试过这两种将线程锁定到CPU的方法,而且具体细节会因操作系统而异。
英文:
In modern Go, I wouldn't lock goroutines to threads for efficiency. Go 1.5 added goroutine scheduling affinity, to minimize how often goroutines switch between OS threads. And any cost of the remaining migrations between CPUs has to be weighed against the benefit of the user-mode scheduler avoiding context switches into kernel mode. Finally, when switching costs are a real problem, sometimes a better focus is changing your program logic so it needs to switch less, like by communicating batches of work instead of individual work items.
But even considering all that, sometimes you simply have to lock a goroutine, like when a C API requires it, and I'll assume that's the case below.
If the whole program runs with GOMAXPROCS=1
, then it's relatively simple to set a CPU affinity by calling out to the taskset utility from the schedutils package.
I had thought you were out of luck if GOMAXPROCS > 1
because then goroutines are migrated between OS threads at runtime. In fact, James Henstridge points out you can use runtime.LockOSThread()
to keep your goroutine from migrating.
That doesn't solve locking the OS thread to a CPU. @yerden points out in a comment that the SchedSeatffinity
function in the golang.org/x/sys/unix
package, using 0 as the pid, ought to lock the calling thread to its current CPU.
In the "C API requires locking" use case, it might also work to call pthread_setaffinity_np
from C code.
I haven't tested either of those ways to lock threads to CPUs, and details will vary by OS there.
答案2
得分: 2
根据你的工作负载而定,但有时候每个CPU启动一个go进程,将gomaxprocs设置为1,并使用taskset将进程固定到CPU上是有益的。以下是关于这个主题的一段摘录,来自于优秀的fasthttp库:
- 使用reuseport监听器。
- 使用GOMAXPROCS=1为每个CPU核心运行一个独立的服务器实例。
- 使用taskset将每个服务器实例固定到一个独立的CPU核心上。
- 确保多队列网络卡的中断均匀分布在CPU核心之间。详细信息请参阅这篇文章。
- 使用Go 1.6,因为它提供了一些显著的性能改进。
来源:https://github.com/valyala/fasthttp#performance-optimization-tips-for-multi-core-systems
英文:
Depends on your workload, but sometimes it's beneficial to start a go process per CPU, set gomaxprocs to 1 and pin the process to the CPU with taskset. Here is an excerpt on that topic from the awesome fasthttp library:
> * Use reuseport
> listener.
> * Run a separate server instance per CPU core with GOMAXPROCS=1.
> * Pin each server instance to a separate CPU core using taskset.
> * Ensure the interrupts of multiqueue network card are evenly distributed between CPU cores. See this
> article for
> details.
> * Use Go 1.6 as it provides some considerable performance improvements.
Source: https://github.com/valyala/fasthttp#performance-optimization-tips-for-multi-core-systems
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论