如何使用python找出CPU数量


535

我想知道使用Python的本地计算机上的CPU数量。当使用最佳缩放的仅用户空间程序调用时,结果应user/real为输出time(1)


3
您应该牢记cpusets(在Linux中)。如果您使用的是cpuset,则以下解决方案仍将提供系统中实际CPU的数量,而不是进程可用的数量。/proc/<PID>/status有几行告诉您当前cpuset中的CPU数量:查找Cpus_allowed_list
wpoely86 2013年

Answers:


853

如果您的Python版本> = 2.6,则可以简单地使用

import multiprocessing

multiprocessing.cpu_count()

http://docs.python.org/library/multiprocessing.html#multiprocessing.cpu_count


4
3.x也支持多处理
LittleByBlue

3
我想补充一点,这在IronPython中不起作用,它会引发NotImplementedError。
马赛厄斯

1
这给出了可用的CPU数量...程序未使用!
amc

25
在Python 3.6.2上,我只能使用os.cpu_count()
阿基里斯(Achilles)

4
另外,如下所述,此计数可能包括“虚拟”超线程cpus,如果您要调度CPU密集型任务,则可能不是您想要的。
Christopher Barber

185

如果您对当前进程可用的处理器数量感兴趣,则必须首先检查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')

在运行最新Ubuntu的MacPro 1,0,运行最新Debian的HP笔记本电脑和运行旧Ubuntu的旧eMachine上,的cpus_allowed结果/proc/self/status分别为ff,f和f ---分别对应于8、4 和根据您的(正确)数学计算得出4。但是,CPU的实际数量分别为4、2和1。我发现计算“处理器”一词的出现次数/proc/cpuinfo可能是更好的方法。(或者我有错吗?)
Mike O'Connor

1
经过进一步的研究-如果可以说是“ Google搜索”-我会发现/proc/cpuinfo,如果对于每个“处理器”的列表中的任何一个,您都将“兄弟姐妹”乘以“ cpu核心”您得到您的“ Cpus_allowed”号码。而且我认为兄弟姐妹指的是超线程,因此您指的是“虚拟”。但是事实仍然是,在MacPro上您的“ Cpus_allowed”数是8,而multiprocessing.cpu_count()答案是4。我自己open('/proc/cpuinfo').read().count('processor')也产生了4(即物理核(两个双核处理器))。
Mike O'Connor

1
open('/proc/self/status').read()忘记关闭文件。使用with open('/proc/self/status') as f: f.read()代替
timdiels

4
os.cpu_count()
goetzc

1
@amcgregor在这种情况下,可以接受的,只是将文件句柄保持打开状态,如果您不编写长时间运行的守护进程/进程,我想这是可以的。我担心这可能最终会达到操作系统的最大打开文件句柄。当写入需要在过程结束之前重新读取的文件时,情况更糟,但这不是这种情况,因此这是有争议的。with在遇到需要的情况时习惯使用它仍然是一个好主意。
timdiels

91

另一种选择是使用该psutil库,它在以下情况下总是有用的:

>>> import psutil
>>> psutil.cpu_count()
2

这应该可以在psutil(Unix和Windows)支持的任何平台上使用。

请注意,在某些情况下multiprocessing.cpu_count可能会产生一种NotImplementedError同时psutil就能获得CPU的数量。这仅仅是因为psutil首先尝试使用与以前使用的相同的技术multiprocessing,如果失败,它还会使用其他技术。


4
考虑到所使用的方法可以找出CPU核心是逻辑矿石还是物理核心,因此这真的很好。psutil.cpu_count(logical = True)
Devilhunter

@Bakuriu,您好,是否有任何方法可以通过psutil获取特定进程使用的cpu核心数?
saichand

我的Intel i7-8700上的Windows上的@Devilhunter psutil.cpu_count()提供12(这是具有超线程功能的6核CPU)。这是因为默认参数logical为True,因此您明确需要进行写操作psutil.cpu_count(logical = False)才能获取物理内核的数量。
OscarVanL

52

在Python 3.4及更高版本中:os.cpu_count()

multiprocessing.cpu_count()就此功能实现了,但是NotImplementedError如果os.cpu_count()返回则提高None(“无法确定CPU的数量”)。


4
另请参阅的文档cpu_countlen(os.sched_getaffinity(0))可能会更好,具体取决于目的。
阿尔伯特

1
@Albert是的,系统中的CPU数量(— os.cpu_count()OP询问的内容)可能与当前进程可用的CPU数量(os.sched_getaffinity(0))不同。
jfs

我知道。我只是想为其他可能会错过这种差异的读者提供补充,以使他们获得更完整的图画。
艾伯特

1
另外:os.sched_getaffinity(0)可用的上BSD,所以使用os.cpu_count()是必需的(没有其它外部库,这是)。
Cometsong

1
应该注意的是,os.sched_getaffinity在Windows上似乎不可用。
manu3d

47

len(os.sched_getaffinity(0)) 通常就是你想要的

https://docs.python.org/3/library/os.html#os.sched_getaffinity

os.sched_getaffinity(0)(在Python 3中添加)(考虑sched_setaffinityLinux系统调用)返回可用的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中进行了测试。


3
仅在Unix上可用。
Christopher Barber

@ChristopherBarber感谢您提供的信息,并将其添加到答案中。
Ciro Santilli郝海东冠状病六四事件法轮功

33

平台无关:

psutil.cpu_count(逻辑=假)

https://github.com/giampaolo/psutil/blob/master/INSTALL.rst


4
逻辑CPU与非逻辑CPU有什么区别?在我的笔记本电脑上:psutil.cpu_count(logical=False) #4 psutil.cpu_count(logical=True) #8multiprocessing.cpu_count() #8
user305883 '16

1
@ user305883假定您具有x86 CPU,则此计算机上具有超线程,即每个物理核心对应于两个超线程(“逻辑”核心)。超线程允许物理内核的一部分在线程A处于空闲状态时(例如,等待从高速缓存或内存中获取数据)使用物理内核执行来自线程B的指令。根据您的代码,一个人可以获得额外的百分之一或百分之几十的核心利用率,但这远低于实际物理核心的性能。
安德烈·霍尔兹纳

23

这些给你超线程的CPU数量

  1. multiprocessing.cpu_count()
  2. os.cpu_count()

这些为您提供虚拟机的CPU数量

  1. psutil.cpu_count()
  2. numexpr.detect_number_of_cores()

仅在您在VM上工作时才重要。


并不是的。如前所述,os.cpu_count()并且multiprocessing.cpu_count()将返回超线程cpu计数,而不是实际的物理cpu计数。
Christopher Barber

2
是。我改写了。通常是内核数x2。我的意思是,如果您在虚拟机上划分出8个内核,但是主机物理上是20个内核,则第一组命令给您20,第二组命令给您8.
yangliu2

21

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设计为可跨操作系统和体系结构移植。


在这种情况下,我需要逻辑CPU的数量(即,如果该程序可扩展性很好,则应该启动多少线程),但是答案可能还是有帮助的。
phihag 2014年

7
psutil.cpu_count(logical=False)
TimZaman '16

8

无法弄清楚如何添加到代码或回复消息,但是这里提供了对jython的支持,您可以在放弃之前先加以支持:

# jython
try:
    from java.lang import Runtime
    runtime = Runtime.getRuntime()
    res = runtime.availableProcessors()
    if res > 0:
        return res
except ImportError:
    pass

7

这对于使用不同操作系统/系统但想要获得世界最佳状态的我们来说可能是有用的:

import os
workers = os.cpu_count()
if 'sched_getaffinity' in dir(os):
    workers = len(os.sched_getaffinity(0))

5

您也可以为此目的使用“ 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()

joblib使用基础的多处理模块。为此,最好直接调用多处理。
ogrisel

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.