我想使用Python知道本地机器上的CPU数量。当使用一个最佳缩放的仅用户空间程序调用time(1)
时,结果应该输出user/real
。
我想使用Python知道本地机器上的CPU数量。当使用一个最佳缩放的仅用户空间程序调用time(1)
时,结果应该输出user/real
。
如果你的Python版本 >= 2.6,你可以简单地使用:
import multiprocessing
multiprocessing.cpu_count()
http://docs.python.org/library/multiprocessing.html#multiprocessing.cpu_count
os.cpu_count()
函数。 - Achilles如果您想了解当前进程可以使用的处理器数量,首先需要查看cpuset,如果没有使用cpuset,或者您正在使用Python2.6或更新版本,则可以使用multiprocessing.cpu_count()
方法。在旧版本的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')
/proc/cpuinfo
中发现,对于每个"处理器"的列表中,如果将"兄弟姐妹"乘以"CPU内核",就可以得到"Cpus_allowed"数字。我了解到,兄弟姐妹是指超线程,因此你提到了"虚拟"。但事实仍然是,在我的MacPro上,你的"Cpus_allowed"数字是8,而你的multiprocessing.cpu_count()
答案是4。我的open('/proc/cpuinfo').read().count('processor')
也产生了4,即物理内核数(两个双核处理器)。 - Mike O'Connoropen('/proc/self/status').read()
忘记关闭文件。请改用with open('/proc/self/status') as f: f.read()
。 - Tim Dielsos.cpu_count()
- goetz__del__
)将会在“最后一个引用被释放之后的未来某个时间点”发生,或者在解释器先关闭的情况下不会发生(https://pypy.readthedocs.io/en/latest/cpython_differences.html#differences-related-to-garbage-collection-strategies)。“或不”情况也是可以接受的;当进程关闭时,文件句柄无论如何都会关闭。 - amcgregorlen(os.sched_getaffinity(0))
是你通常想要的
https://docs.python.org/3/library/os.html#os.sched_getaffinity
os.sched_getaffinity(0)
(在Python 3中添加)返回可用CPU集合,考虑到sched_setaffinity
Linux系统调用,该调用限制了进程及其子进程可以运行的CPU。
0
表示获取当前进程的值。该函数返回 set()
允许使用的CPU,因此需要用到 len()
。
另一方面,multiprocessing.cpu_count()
和 os.cpu_count()
只返回逻辑CPU的总数,即考虑超线程的 CPU 数量。
这种差异尤其重要,因为某些集群管理系统(如Platform LSF)通过sched_getaffinity
限制作业的CPU使用率。
taskset -c 0 ./main.py
使用测试脚本:
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
Vs nproc
nproc
默认情况下会尊重亲和性并且:
taskset -c 0 nproc
输出:
1
man nproc
非常明确:
打印可用处理单元的数量
因此,默认情况下,len(os.sched_getaffinity(0))
的行为类似于nproc
。
nproc
具有--all
标志,用于较少见的情况,即您想在不考虑taskset的情况下获取物理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
Lib/multiprocessing/context.py
下,我们还可以看到multiprocessing.cpu_count
只是将其转发到os.cpu_count
,除了如果os.cpu_count
失败时,multiprocessing
会抛出异常而不是返回None:
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
并且该函数可能会丢失:
psutil.Process().cpu_affinity()
:带有Windows端口的第三方版本
第三方psutil
软件包(pip install psutil
)已经在https://dev59.com/_HNA5IYBdhLWcg3wVcJx#14840102中提到,但没有提到cpu_affinity
函数:https://psutil.readthedocs.io/en/latest/#psutil.Process.cpu_affinity
用法:
import psutil
print(len(psutil.Process().cpu_affinity()))
这个函数在Linux上执行与标准库os.sched_getaffinity
相同的功能,但他们还通过调用GetProcessAffinityMask
Windows API函数来实现了Windows版本:
AttributeError: 'Process' 对象没有 'cpu_affinity' 属性
。 - Anentropicpsutil
和上游的标准库了 :-) - Ciro Santilli OurBigBook.com另一个选择是使用psutil
库,在这些情况下总是非常有用的:
>>> import psutil
>>> psutil.cpu_count()
2
这应该可以在任何 psutil
支持的平台上工作(Unix和Windows)。
请注意,在某些情况下,multiprocessing.cpu_count
可能会引发 NotImplementedError
,而 psutil
将能够获取CPU数量。这只是因为 psutil
首先尝试使用与 multiprocessing
相同的技术,如果失败,则还使用其他技术。
psutil.cpu_count(logical=True)
- Devilhunterpsutil.cpu_count()
返回12(这是一款具有超线程技术的6核心CPU)。这是因为logical
参数的默认值为True,所以你需要显式地写出psutil.cpu_count(logical = False)
才能获取物理核心数。 - OscarVanLpsutil.Process().cpu_affinity()
,如此解释在这里:https://dev59.com/_HNA5IYBdhLWcg3wVcJx#55423170 顺便说一句。 - Ciro Santilli OurBigBook.commultiprocessing.cpu_count()
基于该函数实现,但如果os.cpu_count()
返回None
("无法确定CPU数量"),则会引发NotImplementedError
异常。cpu_count
的文档。根据用途,len(os.sched_getaffinity(0))
可能更好。 - Albertos.cpu_count()
- OP 所询问的内容) 可能与当前进程可用的 CPU 数量 (os.sched_getaffinity(0)
) 不同。 - jfsos.sched_getaffinity(0)
在BSD上不可用,因此需要使用os.cpu_count()
(不使用其他外部库)。 - Cometsong如果你想知道物理核心数(而不是虚拟超线程核心数),这里提供了一个平台无关的解决方案:
psutil.cpu_count(logical=False)
https://github.com/giampaolo/psutil/blob/master/INSTALL.rst
请注意,默认情况下 logical
的值为 True
,所以如果您确实想包括超线程核心,则可以使用以下命令:
psutil.cpu_count()
这将提供与os.cpu_count()
和multiprocessing.cpu_count()
相同的数字,它们都没有logical
关键字参数。
psutil.cpu_count(logical=False)
返回 4
,表示物理 CPU 核心数。
psutil.cpu_count(logical=True)
返回 8
,即逻辑 CPU 核心数。
multiprocessing.cpu_count()
返回 8
,即逻辑 CPU 核心数。 - user305883这些代码可以获取超线程CPU数量:
multiprocessing.cpu_count()
os.cpu_count()
这些代码可以获取虚拟机CPU数量:
psutil.cpu_count()
numexpr.detect_number_of_cores()
仅适用于在虚拟机上工作的情况。
os.cpu_count()
和 multiprocessing.cpu_count()
返回的是超线程 CPU 数量,而非实际物理 CPU 数量。 - Christopher Barber对于 Python 版本在 3.4 及以上,您可以使用:
import os
os.cpu_count()
如果你正在寻找Linux命令nproc
的替代方案,你有以下选择
len(os.sched_getaffinity(0))
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旨在跨操作系统和架构移植。
psutil.cpu_count(logical=False)
- TimZaman这可能适用于那些使用不同操作系统/系统,但想要获得最佳效果的人:
import os
workers = os.cpu_count()
if 'sched_getaffinity' in dir(os):
workers = len(os.sched_getaffinity(0))
import torch.multiprocessing; mp.cpu_count()
。 - Charlie Parker