我想知道使用 Python 的本地机器上的 CPU 数量。当使用优化缩放的纯用户空间程序调用时,结果应该是user/real
输出。time(1)
15 回答
如果您的 python 版本 >= 2.6,您可以简单地使用
import multiprocessing
multiprocessing.cpu_count()
http://docs.python.org/library/multiprocessing.html#multiprocessing.cpu_count
如果您对当前进程可用的处理器数量感兴趣,则必须先检查cpuset。否则(或者如果 cpuset 没有被使用),multiprocessing.cpu_count()
是 Python 2.6 和更新版本的方法。以下方法回退到旧版本 Python 中的几种替代方法:
import os
import re
import subprocess
def available_cpu_count():
""" Number of available virtual or physical CPUs on this system, i.e.
user/real as output by time(1) when called with an optimally scaling
userspace-only program"""
# cpuset
# cpuset may restrict the number of *available* processors
try:
m = re.search(r'(?m)^Cpus_allowed:\s*(.*)$',
open('/proc/self/status').read())
if m:
res = bin(int(m.group(1).replace(',', ''), 16)).count('1')
if res > 0:
return res
except IOError:
pass
# Python 2.6+
try:
import multiprocessing
return multiprocessing.cpu_count()
except (ImportError, NotImplementedError):
pass
# https://github.com/giampaolo/psutil
try:
import psutil
return psutil.cpu_count() # psutil.NUM_CPUS on old versions
except (ImportError, AttributeError):
pass
# POSIX
try:
res = int(os.sysconf('SC_NPROCESSORS_ONLN'))
if res > 0:
return res
except (AttributeError, ValueError):
pass
# Windows
try:
res = int(os.environ['NUMBER_OF_PROCESSORS'])
if res > 0:
return res
except (KeyError, ValueError):
pass
# jython
try:
from java.lang import Runtime
runtime = Runtime.getRuntime()
res = runtime.availableProcessors()
if res > 0:
return res
except ImportError:
pass
# BSD
try:
sysctl = subprocess.Popen(['sysctl', '-n', 'hw.ncpu'],
stdout=subprocess.PIPE)
scStdout = sysctl.communicate()[0]
res = int(scStdout)
if res > 0:
return res
except (OSError, ValueError):
pass
# Linux
try:
res = open('/proc/cpuinfo').read().count('processor\t:')
if res > 0:
return res
except IOError:
pass
# Solaris
try:
pseudoDevices = os.listdir('/devices/pseudo/')
res = 0
for pd in pseudoDevices:
if re.match(r'^cpuid@[0-9]+$', pd):
res += 1
if res > 0:
return res
except OSError:
pass
# Other UNIXes (heuristic)
try:
try:
dmesg = open('/var/run/dmesg.boot').read()
except IOError:
dmesgProcess = subprocess.Popen(['dmesg'], stdout=subprocess.PIPE)
dmesg = dmesgProcess.communicate()[0]
res = 0
while '\ncpu' + str(res) + ':' in dmesg:
res += 1
if res > 0:
return res
except OSError:
pass
raise Exception('Can not determine number of CPUs on this system')
另一种选择是使用psutil
库,它在这些情况下总是有用的:
>>> import psutil
>>> psutil.cpu_count()
2
psutil
这应该适用于(Unix 和 Windows)支持的任何平台。
请注意,在某些场合multiprocessing.cpu_count
可能会提高NotImplementedError
一会儿psutil
就能获得 CPU 的数量。这仅仅是因为psutil
首先尝试使用相同的技术multiprocessing
,如果失败了,它也会使用其他技术。
len(os.sched_getaffinity(0))
是你通常想要的
https://docs.python.org/3/library/os.html#os.sched_getaffinity
os.sched_getaffinity(0)
(在 Python 3 中添加)返回考虑到sched_setaffinity
Linux 系统调用的可用 CPU 集,这限制了进程及其子进程可以在哪些 CPU 上运行。
0
意思是获取当前进程的值。该函数返回一个set()
允许的 CPU,因此需要len()
.
multiprocessing.cpu_count()
os.cpu_count()
另一方面,只返回物理 CPU 的总数。
区别尤其重要,因为某些集群管理系统(例如Platform LSF )使用sched_getaffinity
.
因此,如果您使用multiprocessing.cpu_count()
,您的脚本可能会尝试使用比可用内核更多的内核,这可能会导致过载和超时。
我们可以通过限制与实用程序的亲和性来具体看到差异taskset
,这使我们能够控制进程的亲和性。
最小的taskset
例子
例如,如果我在我的 16 核系统中将 Python 限制为只有 1 个核心(核心 0):
taskset -c 0 ./main.py
使用测试脚本:
主文件
#!/usr/bin/env python3
import multiprocessing
import os
print(multiprocessing.cpu_count())
print(os.cpu_count())
print(len(os.sched_getaffinity(0)))
那么输出是:
16
16
1
VSnproc
nproc
默认情况下确实尊重亲和力,并且:
taskset -c 0 nproc
输出:
1
并man nproc
使其非常明确:
打印可用处理单元的数量
因此,默认情况下的len(os.sched_getaffinity(0))
行为nproc
。
nproc
对于--all
不太常见的情况,您希望在不考虑任务集的情况下获得物理 CPU 计数的标志:
taskset -c 0 nproc --all
os.cpu_count
文件
的文档os.cpu_count
也简要提到了这个https://docs.python.org/3.8/library/os.html#os.cpu_count
这个数字不等于当前进程可以使用的 CPU 数量。可用 CPU 的数量可以通过
len(os.sched_getaffinity(0))
同样的评论也被复制到以下文档中multiprocessing.cpu_count
:https ://docs.python.org/3/library/multiprocessing.html#multiprocessing.cpu_count
从下面的 3.8 源代码中,Lib/multiprocessing/context.py
我们还看到multiprocessing.cpu_count
只是转发到os.cpu_count
,除了如果失败multiprocessing
则抛出异常而不是返回 None :os.cpu_count
def cpu_count(self):
'''Returns the number of CPUs in the system'''
num = os.cpu_count()
if num is None:
raise NotImplementedError('cannot determine number of cpus')
else:
return num
3.8 可用性:具有本机sched_getaffinity
功能的系统
唯一的缺点os.sched_getaffinity
是这似乎只适用于 Python 3.8 的 UNIX。
cpython 3.8 似乎只是尝试sched_setaffinity
在配置期间使用函数调用编译一个小的 C hello world,如果不存在HAVE_SCHED_SETAFFINITY
则不设置并且该函数可能会丢失:
- https://github.com/python/cpython/blob/v3.8.5/configure#L11523
- https://github.com/python/cpython/blob/v3.8.5/Modules/posixmodule.c#L6457
psutil.Process().cpu_affinity()
: 带有 Windows 端口的第三方版本
第三方psutil
包(pip install psutil
_ _ _ cpu_affinity
_ _
用法:
import psutil
print(len(psutil.Process().cpu_affinity()))
此函数与 Linux 上的标准库相同os.sched_getaffinity
,但他们也通过调用GetProcessAffinityMask
Windows API 函数为 Windows 实现了它:
- https://github.com/giampaolo/psutil/blob/ee60bad610822a7f630c52922b4918e684ba7695/psutil/_psutil_windows.c#L1112
- https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getprocessaffinitymask
换句话说:那些 Windows 用户必须停止偷懒,向上游标准库发送补丁 :-)
在 Ubuntu 16.04、Python 3.5.2 中测试。
在 Python 3.4+ 中:os.cpu_count()。
multiprocessing.cpu_count()
是根据此函数实现的,但NotImplementedError
如果os.cpu_count()
返回则引发None
(“无法确定 CPU 数量”)。
如果您想知道物理内核(不是虚拟超线程内核)的数量,这里有一个独立于平台的解决方案:
psutil.cpu_count(logical=False)
https://github.com/giampaolo/psutil/blob/master/INSTALL.rst
请注意,默认值为logical
,True
因此如果您确实想要包含超线程内核,您可以使用:
psutil.cpu_count()
os.cpu_count()
这将给出与and相同的数字multiprocessing.cpu_count()
,两者都没有logical
关键字参数。
这些为您提供超线程 CPU 计数
multiprocessing.cpu_count()
os.cpu_count()
这些为您提供虚拟机 CPU 计数
psutil.cpu_count()
numexpr.detect_number_of_cores()
仅当您在虚拟机上工作时才重要。
multiprocessing.cpu_count()
将返回逻辑 CPU 的数量,因此如果您有一个带超线程的四核 CPU,它将返回8
. 如果您想要物理 CPU 的数量,请使用 python 绑定到 hwloc:
#!/usr/bin/env python
import hwloc
topology = hwloc.Topology()
topology.load()
print topology.get_nbobjs_by_type(hwloc.OBJ_CORE)
hwloc 旨在跨操作系统和体系结构移植。
对于 3.4 以上的 python 版本,您可以使用
import os
os.cpu_count()
如果您正在寻找一个等效的 linux 命令nproc
。你有这个选项
len(os.sched_getaffinity(0))
这可能适用于我们这些使用不同操作系统/系统但想要获得最好的世界的人:
import os
workers = os.cpu_count()
if 'sched_getaffinity' in dir(os):
workers = len(os.sched_getaffinity(0))
无法弄清楚如何添加到代码或回复消息,但这里是对 jython 的支持,您可以在放弃之前添加:
# jython
try:
from java.lang import Runtime
runtime = Runtime.getRuntime()
res = runtime.availableProcessors()
if res > 0:
return res
except ImportError:
pass
您也可以为此目的使用“joblib”。
import joblib
print joblib.cpu_count()
此方法将为您提供系统中的 CPU 数量。不过需要安装joblib。有关 joblib 的更多信息,请参见 https://pythonhosted.org/joblib/parallel.html
或者,您可以使用 python 的 numexpr 包。它有很多简单的功能,有助于获取有关系统 cpu 的信息。
import numexpr as ne
print ne.detect_number_of_cores()
如果您没有 Python 2.6,另一种选择:
import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")
如果您使用的是手电筒,您可以执行以下操作:
import torch.multiprocessing as mp
mp.cpu_count()
torch 中的 mp 库与主 python 具有相同的界面,因此您也可以像评论者提到的那样执行此操作:
python -c "import multiprocessing; print(multiprocessing.cpu_count())"
希望这可以帮助!;) 拥有超过 1 个选项总是很不错的。
如果您正在寻找打印系统中的核心数量。
试试这个:
import os
no_of_cores = os.cpu_count()
print(no_of_cores)
这应该会有所帮助。