当在Linux上运行lscpu
命令时,它将列出机器上的CPU信息。举一个例子,一台机器有一个CPU,2个核心,每个核心有两个线程,这表示有4个核心可用。
现在让我们看看GoLang程序将识别多少个核心。
从输出中,NumCPU
和 GOMAXPROCS
都输出4,这是预期的结果。Go运行时如何获取此信息?它是通过类似lscpu或/proc/cpuinfo这样的命令获取的吗?让我们深入研究GoLang的源代码。
在 runtime/debug.go
中,它说明此值来自全局变量ncpu
,该变量在进程启动时设置,一旦设置就不会更改。
ncpu在哪里设置? 在runtime目录中使用grep搜索此关键字,在runtime/os_linux.go
中,有一个函数osinit()
调用 getproccount()
来获取ncpu值。
在getproccount()
内部,它调用 sche_getaffinity()
,该函数将有一个输出buf
,其中值为1的每个位将被视为一个核心。
此函数sche_getaffinity()
是用Go汇编定义的原生函数。其实现可以在 runtime/sys_linux_amd64.s
中找到。
从上面可以看出,ncpu的值与lscpu
的输出不同,它是操作系统分配给当前进程的CPU数量。在大多数情况下,人们会看到ncpu与操作系统上可用的CPU数量相同,这是因为操作系统默认允许一个进程使用所有可用的CPU。如果想限制一个进程使用的CPU数量,可以使用 cpuset
来自cgroup
进行更改。
例如,让我们创建一个名为 gocpu
的cgroup。
cgcreate -g cpuset:/gocpu
如果只想允许cgroup gocpu使用CPU 0-1, 可以运行
#echo '0' > cpuset.mems
#echo '0-1' > cpuset.cpus
#echo $$ > tasks
然后让bash shell在这个新的cgroup中运行,并再次启动go程序,它现在将只有2个核心可用。