700

我想知道使用 Python 的本地机器上的 CPU 数量。当使用优化缩放的纯用户空间程序调用时,结果应该是user/real输出。time(1)

4

15 回答 15

1088

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

import multiprocessing

multiprocessing.cpu_count()

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

于 2009-06-17T10:53:53.843 回答
216

如果您对当前进程可用的处理器数量感兴趣,则必须先检查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')
于 2009-06-17T10:43:28.980 回答
117

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

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

psutil这应该适用于(Unix 和 Windows)支持的任何平台。

请注意,在某些场合multiprocessing.cpu_count可能会提高NotImplementedError一会儿psutil就能获得 CPU 的数量。这仅仅是因为psutil首先尝试使用相同的技术multiprocessing,如果失败了,它也会使用其他技术。

于 2013-02-12T19:19:05.940 回答
105

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()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_counthttps ://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则不设置并且该函数可能会丢失:

psutil.Process().cpu_affinity(): 带有 Windows 端口的第三方版本

第三方psutilpip install psutil_ _ _ cpu_affinity_ _

用法:

import psutil
print(len(psutil.Process().cpu_affinity()))

此函数与 Linux 上的标准库相同os.sched_getaffinity,但他们也通过调用GetProcessAffinityMaskWindows API 函数为 Windows 实现了它:

换句话说:那些 Windows 用户必须停止偷懒,向上游标准库发送补丁 :-)

在 Ubuntu 16.04、Python 3.5.2 中测试。

于 2019-03-29T18:00:55.117 回答
60

在 Python 3.4+ 中:os.cpu_count()

multiprocessing.cpu_count()是根据此函数实现的,但NotImplementedError如果os.cpu_count()返回则引发None(“无法确定 CPU 数量”)。

于 2014-09-03T04:16:56.270 回答
51

如果您想知道物理内核(不是虚拟超线程内核)的数量,这里有一个独立于平台的解决方案:

psutil.cpu_count(logical=False)

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

请注意,默认值为logicalTrue因此如果您确实想要包含超线程内核,您可以使用:

psutil.cpu_count()

os.cpu_count()这将给出与and相同的数字multiprocessing.cpu_count(),两者都没有logical关键字参数。

于 2016-04-11T05:42:55.397 回答
29

这些为您提供超线程 CPU 计数

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

这些为您提供虚拟机 CPU 计数

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

仅当您在虚拟机上工作时才重要。

于 2019-03-14T13:16:55.420 回答
23

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 旨在跨操作系统和体系结构移植。

于 2014-07-17T13:32:10.697 回答
11

对于 3.4 以上的 python 版本,您可以使用

import os
os.cpu_count()

如果您正在寻找一个等效的 linux 命令nproc。你有这个选项

len(os.sched_getaffinity(0))
于 2021-07-07T11:21:21.023 回答
10

这可能适用于我们这些使用不同操作系统/系统但想要获得最好的世界的人:

import os
workers = os.cpu_count()
if 'sched_getaffinity' in dir(os):
    workers = len(os.sched_getaffinity(0))
于 2019-11-07T11:47:28.507 回答
8

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

# jython
try:
    from java.lang import Runtime
    runtime = Runtime.getRuntime()
    res = runtime.availableProcessors()
    if res > 0:
        return res
except ImportError:
    pass
于 2010-10-02T12:16:02.887 回答
8

您也可以为此目的使用“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()
于 2015-04-21T11:14:43.393 回答
1

如果您没有 Python 2.6,另一种选择:

import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")
于 2014-08-29T14:05:39.103 回答
1

如果您使用的是手电筒,您可以执行以下操作:

import torch.multiprocessing as mp

mp.cpu_count()

torch 中的 mp 库与主 python 具有相同的界面,因此您也可以像评论者提到的那样执行此操作:

python -c "import multiprocessing; print(multiprocessing.cpu_count())"

希望这可以帮助!;) 拥有超过 1 个选项总是很不错的。

于 2021-02-18T19:02:29.393 回答
-1

如果您正在寻找打印系统中的核心数量。

试试这个:

import os 
no_of_cores = os.cpu_count()
print(no_of_cores)

这应该会有所帮助。

于 2021-09-21T17:07:58.440 回答