有没有可能强制go例程在特定CPU上运行?

hujrc8aj  于 2022-12-28  发布在  Go
关注(0)|答案(2)|浏览(162)

我正在阅读Go语言的runtime包,发现我可以设置运行我的程序所需的CPU单元数(func GOMAXPROCS(n int)),我可以强制一个goroutine在我选择的特定CPU上运行吗?

j2datikz

j2datikz1#

在现代的Go语言中,我不会为了效率而将goroutine锁定到线程上,Go语言是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就不太走运了,因为那时goroutine会在运行时在操作系统线程之间迁移,实际上,James亨斯特里奇指出你可以使用runtime.LockOSThread()来阻止goroutine迁移。
这并不能解决将OS线程锁定到CPU的问题。@yerden在一条评论中指出,golang.org/x/sys/unix包中的SchedSeatffinity函数使用0作为pid,应该将调用线程锁定到其当前CPU。
在“C API需要锁定”用例中,从C代码调用pthread_setaffinity_np也可能有效。
我还没有测试过这两种将线程锁定到CPU的方法,具体细节将因操作系统而异。

gojuced7

gojuced72#

这取决于你的工作负载,但有时候在每个CPU上启动一个go进程,将gomaxprocs设置为1,然后使用taskset将进程固定到CPU上是有益的。

  • 使用reuseport侦听器。
  • 在GOMAXPROCS=1的情况下,为每个CPU核心运行单独的服务器示例。
  • 使用taskset将每个服务器示例固定到单独的CPU内核。
  • 确保多队列网卡的中断在CPU核之间均匀分布,具体参见this article
  • 使用Go 1.6是因为它提供了一些可观的性能改进。

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

相关问题