繁体   English   中英

Golang:为什么runtime.GOMAXPROCS限制为256?

[英]Golang: why runtime.GOMAXPROCS is limited to 256?

我在MacBook和Ubuntu上使用golang 1.7.3,发现runtime.GOMAXPROCS限制为256。有人知道此限制来自何处吗? 是否在任何地方都有记录,为什么会有限制? 这是实现优化吗?

在此页面上,我仅能找到256个参考,该参考描述了golang的运行时软件包: https ://golang.org/pkg/runtime/。 runtime.MemStats结构具有几个大小为256的状态数组:

type MemStats struct {
    ...
    PauseNs       [256]uint64 // circular buffer of recent GC pause durations, most recent at [(NumGC+255)%256]
    PauseEnd      [256]uint64 // circular buffer of recent GC pause end times

这是我使用的示例golang代码:

func main() {
    runtime.GOMAXPROCS(1000)
log.Printf("GOMAXPROCS %d\n", runtime.GOMAXPROCS(-1))

}

打印GOMAXPROCS 256

PS另外,有人可以指出我有关此GOMAXPROCS与golang调度程序使用的OS线程计数的关系的文档(如果有的话)。 我们是否可以观察到运行GOMAXPROCS OS线程的经过编译的代码?

编辑:感谢@twotwotwo指出GOMAXPROCS如何与OS线程相关。 仍然很有趣的是,文档没有提到这个256的限制(除了在MemStats结构中可能或可能不相关的限制)。

我想知道是否有人知道这256个数字的真正原因。

软件包runtime文档阐明了GOMAXPROCS与OS线程的关系:

GOMAXPROCS变量限制了可以同时执行用户级Go代码的操作系统线程的数量。 对于代表Go代码的系统调用中可以阻止的线程数量没有限制; 那些不计入GOMAXPROCS限制。 该软件包的GOMAXPROCS函数查询并更改限制。

因此,您可能会看到不止一个GOMAXPROCS OS线程(因为某些线程在系统调用中被阻塞,并且对数量没有限制),或者更少(因为GOMAXPROCS仅被记录为限制线程数,而没有确切地规定它)。

我认为限制GOMAXPROCS符合该文档的精神-您指定可以运行1000个运行Go代码的OS线程是可以的,但是运行时决定“仅”运行256个。这不会限制激活的goroutine的数量,因为它们当一个goroutine块(例如,等待网络读取完成)时,Go的内部调度程序将在同一OS线程上启动其他工作。

Go团队可能会选择这种方法,以最大程度地减少Go程序最终运行的OS线程的机会是当今大多数具有内核的机器的几倍; 这将导致更多的OS上下文切换,这可能比如果将GOMAXPROCS保持在现有CPU内核数量以下而进行的用户模式goroutine切换要慢。 或者,对于设计Go的内部调度程序来说,在GOMAXPROCS上设置上限可能只是很方便。

Goroutines vs Threads并不完美,例如goroutines现在还没有分段堆栈,但是它可以帮助您了解引擎盖下的情况。

请注意,从下一个Go 1.10(Q1 2018)开始, GOMAXPROCS将受到...的限制。

运行时不再人为地限制GOMAXPROCS (以前仅限于1024)。

请参阅Austin Clements( aclements )的 ee55000提交 ,该版本修复了问题15131

既然allp是动态分配的,那么就不需要对GOMAXPROCS设置硬上限了。


allp在这里定义

参见commit e900e27

runtime :清理allp循环

现在, allp长度为gomaxprocs ,这意味着allp[i]都不为nil或不处于_Pdead状态。
这样就可以用正常范围循环替换allp上几种不同样式的循环。

for i := 0; i < gomaxprocs; i++ { ... } for i := 0; i < gomaxprocs; i++ { ... }循环可以简单地遍历allp
同样, range loops over allp[:gomaxprocs]可以在allp范围allp

检查p == nil || p.state == _Pdead循环 p == nil || p.state == _Pdead不再需要检查。

如果失效的P不影响p == nil ,则检查p == nil循环不必进行检查。 我检查了所有这些循环,实际上都不受死P的影响。 可能会影响一个循环,这可以通过将p.gcAssistTimeprocresize

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM