Answers:
如果您的Python版本> = 2.6,则可以简单地使用
import multiprocessing
multiprocessing.cpu_count()
http://docs.python.org/library/multiprocessing.html#multiprocessing.cpu_count
os.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')
/proc/self/status
分别为ff,f和f ---分别对应于8、4 和根据您的(正确)数学计算得出4。但是,CPU的实际数量分别为4、2和1。我发现计算“处理器”一词的出现次数/proc/cpuinfo
可能是更好的方法。(或者我有错吗?)
/proc/cpuinfo
,如果对于每个“处理器”的列表中的任何一个,您都将“兄弟姐妹”乘以“ cpu核心”您得到您的“ Cpus_allowed”号码。而且我认为兄弟姐妹指的是超线程,因此您指的是“虚拟”。但是事实仍然是,在MacPro上您的“ Cpus_allowed”数是8,而multiprocessing.cpu_count()
答案是4。我自己open('/proc/cpuinfo').read().count('processor')
也产生了4(即物理核(两个双核处理器))。
open('/proc/self/status').read()
忘记关闭文件。使用with open('/proc/self/status') as f: f.read()
代替
os.cpu_count()
with
在遇到需要的情况时习惯使用它仍然是一个好主意。
另一种选择是使用该psutil
库,它在以下情况下总是有用的:
>>> import psutil
>>> psutil.cpu_count()
2
这应该可以在psutil
(Unix和Windows)支持的任何平台上使用。
请注意,在某些情况下multiprocessing.cpu_count
可能会产生一种NotImplementedError
同时psutil
就能获得CPU的数量。这仅仅是因为psutil
首先尝试使用与以前使用的相同的技术multiprocessing
,如果失败,它还会使用其他技术。
psutil.cpu_count(logical = True)
psutil.cpu_count()
提供12(这是具有超线程功能的6核CPU)。这是因为默认参数logical
为True,因此您明确需要进行写操作psutil.cpu_count(logical = False)
才能获取物理内核的数量。
在Python 3.4及更高版本中:os.cpu_count()。
multiprocessing.cpu_count()
就此功能实现了,但是NotImplementedError
如果os.cpu_count()
返回则提高None
(“无法确定CPU的数量”)。
cpu_count
。len(os.sched_getaffinity(0))
可能会更好,具体取决于目的。
os.cpu_count()
OP询问的内容)可能与当前进程可用的CPU数量(os.sched_getaffinity(0)
)不同。
os.sched_getaffinity(0)
是不可用的上BSD,所以使用os.cpu_count()
是必需的(没有其它外部库,这是)。
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()
另一方面,仅返回物理CPU的总数。
这种差异尤为重要,因为某些集群管理系统(例如Platform LSF)将作业CPU的使用限制为sched_getaffinity
。
因此,如果使用multiprocessing.cpu_count()
,则脚本可能会尝试使用比可用内核更多的内核,这可能导致过载和超时。
通过限制与taskset
实用程序的关联性,我们可以具体看到差异。
例如,如果我在16核系统中将Python限制为仅1核(0核):
taskset -c 0 ./main.py
使用测试脚本:
main.py
#!/usr/bin/env python3
import multiprocessing
import os
print(multiprocessing.cpu_count())
print(len(os.sched_getaffinity(0)))
那么输出是:
16
1
nproc
但是默认情况下确实遵守关联性,并且:
taskset -c 0 nproc
输出:
1
并man nproc
使其非常明确:
打印可用的处理单元数
nproc
具有--all
要获取物理CPU计数的较不常见情况的标志:
taskset -c 0 nproc --all
该方法的唯一缺点是,它似乎仅适用于UNIX。我以为Windows必须具有类似的相似性API SetProcessAffinityMask
,所以我想知道为什么还没有移植它。但是我对Windows一无所知。
已在Ubuntu 16.04,Python 3.5.2中进行了测试。
psutil.cpu_count(logical=False) #4
psutil.cpu_count(logical=True) #8
和multiprocessing.cpu_count() #8
这些给你超线程的CPU数量
multiprocessing.cpu_count()
os.cpu_count()
这些为您提供虚拟机的CPU数量
psutil.cpu_count()
numexpr.detect_number_of_cores()
仅在您在VM上工作时才重要。
os.cpu_count()
并且multiprocessing.cpu_count()
将返回超线程cpu计数,而不是实际的物理cpu计数。
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)
您也可以为此目的使用“ joblib”。
import joblib
print joblib.cpu_count()
此方法将为您提供系统中的cpus数。但是需要安装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")
/proc/<PID>/status
有几行告诉您当前cpuset中的CPU数量:查找Cpus_allowed_list
。