简体   繁体   English

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

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

I was playing with golang 1.7.3 on MacBook and Ubuntu and found that runtime.GOMAXPROCS is limited to 256. Does anyone know where this limit comes from? 我在MacBook和Ubuntu上使用golang 1.7.3,发现runtime.GOMAXPROCS限制为256。有人知道此限制来自何处吗? Is this documented anywhere and why would there be a limit? 是否在任何地方都有记录,为什么会有限制? Is this an implementation optimization? 这是实现优化吗?

Only reference to 256 I could find is on this page that describes golang's runtime package: https://golang.org/pkg/runtime/ . 在此页面上,我仅能找到256个参考,该参考描述了golang的运行时软件包: https ://golang.org/pkg/runtime/。 The runtime.MemStats struct has a couple of stat arrays of size 256: 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

Here's example golang code I used: 这是我使用的示例golang代码:

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

} }

Prints GOMAXPROCS 256 打印GOMAXPROCS 256

PS Also, can someone point me to documentation on how this GOMAXPROCS relate to OS thread count used by golang scheduler (if at all). PS另外,有人可以指出我有关此GOMAXPROCS与golang调度程序使用的OS线程计数的关系的文档(如果有的话)。 Shall we observe go-compiled code running GOMAXPROCS OS threads? 我们是否可以观察到运行GOMAXPROCS OS线程的经过编译的代码?

EDIT: Thanks @twotwotwo for pointing out how GOMAXPROCS relate to OS threads. 编辑:感谢@twotwotwo指出GOMAXPROCS如何与OS线程相关。 Still it's interesting that documentation does not mention this 256 limit (other that in the MemStats struct which may or may not be related). 仍然很有趣的是,文档没有提到这个256的限制(除了在MemStats结构中可能或可能不相关的限制)。

I wonder if anyone is aware of the true reason for this 256 number. 我想知道是否有人知道这256个数字的真正原因。

The package runtime docs clarify how GOMAXPROCS relates to OS threads: 软件包runtime文档阐明了GOMAXPROCS与OS线程的关系:

The GOMAXPROCS variable limits the number of operating system threads that can execute user-level Go code simultaneously. GOMAXPROCS变量限制了可以同时执行用户级Go代码的操作系统线程的数量。 There is no limit to the number of threads that can be blocked in system calls on behalf of Go code; 对于代表Go代码的系统调用中可以阻止的线程数量没有限制; those do not count against the GOMAXPROCS limit. 那些不计入GOMAXPROCS限制。 This package's GOMAXPROCS function queries and changes the limit. 该软件包的GOMAXPROCS函数查询并更改限制。

So you could see more than GOMAXPROCS OS threads (because some are blocked in system calls, and there's no limit to how many), or fewer (because GOMAXPROCS is only documented to limit the number of threads, not prescribe it exactly). 因此,您可能会看到不止一个GOMAXPROCS OS线程(因为某些线程在系统调用中被阻塞,并且对数量没有限制),或者更少(因为GOMAXPROCS仅被记录为限制线程数,而没有确切地规定它)。

I think capping GOMAXPROCS is consistent with the spirit of that documentation--you specified you were OK with 1000 OS threads running Go code, but the runtime decided to 'only' run 256. That doesn't limit the number of goroutines active because they're multiplexed onto OS threads--when one goroutine blocks (waiting for a network read to complete, say) Go's internal scheduler starts other work on the same OS thread. 我认为限制GOMAXPROCS符合该文档的精神-您指定可以运行1000个运行Go代码的OS线程是可以的,但是运行时决定“仅”运行256个。这不会限制激活的goroutine的数量,因为它们当一个goroutine块(例如,等待网络读取完成)时,Go的内部调度程序将在同一OS线程上启动其他工作。

The Go team might have made this choice to minimize the chance that Go programs end up running many times more OS threads than most machines today have cores; Go团队可能会选择这种方法,以最大程度地减少Go程序最终运行的OS线程的机会是当今大多数具有内核的机器的几倍; that would cause more OS context switches, which can be slower than user-mode goroutine switches that would occur if GOMAXPROCS were kept down to the number of CPU cores present. 这将导致更多的OS上下文切换,这可能比如果将GOMAXPROCS保持在现有CPU内核数量以下而进行的用户模式goroutine切换要慢。 Or it might just have been convenient for the design Go's internal scheduler to have an upper bound on GOMAXPROCS. 或者,对于设计Go的内部调度程序来说,在GOMAXPROCS上设置上限可能只是很方便。

Goroutines vs Threads is not perfect, eg goroutines don't have segmented stacks now, but it may help you understand what's going on here under the hood. Goroutines vs Threads并不完美,例如goroutines现在还没有分段堆栈,但是它可以帮助您了解引擎盖下的情况。

Note that, starting the next Go 1.10 (Q1 2018), GOMAXPROCS will be limited by ... nothing. 请注意,从下一个Go 1.10(Q1 2018)开始, GOMAXPROCS将受到...的限制。

The runtime no longer artificially limits GOMAXPROCS (previously it was limited to 1024). 运行时不再人为地限制GOMAXPROCS (以前仅限于1024)。

See commit ee55000 by Austin Clements ( aclements ) , which fixes issue 15131 . 请参阅Austin Clements( aclements )的 ee55000提交 ,该版本修复了问题15131

Now that allp is dynamically allocated, there's no need for a hard cap on GOMAXPROCS . 既然allp是动态分配的,那么就不需要对GOMAXPROCS设置硬上限了。


allp is defined here . allp在这里定义

See also commit e900e27 : 参见commit e900e27

runtime : clean up loops over allp runtime :清理allp循环

allp now has length gomaxprocs , which means none of allp[i] are nil or in state _Pdead . 现在, allp长度为gomaxprocs ,这意味着allp[i]都不为nil或不处于_Pdead状态。
This lets replace several different styles of loops over allp with normal range loops. 这样就可以用正常范围循环替换allp上几种不同样式的循环。

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

Loops that check for p == nil || p.state == _Pdead 检查p == nil || p.state == _Pdead循环 p == nil || p.state == _Pdead don't need to check this any more. p == nil || p.state == _Pdead不再需要检查。

Loops that check for p == nil don't have to check this if dead Ps don't affect them. 如果失效的P不影响p == nil ,则检查p == nil循环不必进行检查。 I checked that all such loops are, in fact, unaffected by dead Ps. 我检查了所有这些循环,实际上都不受死P的影响。 One loop was potentially affected, which this fixes by zeroing p.gcAssistTime in procresize . 可能会影响一个循环,这可以通过将p.gcAssistTimeprocresize

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

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