簡體   English   中英

如何使用 python 找出 CPU 的數量

[英]How to find out the number of CPUs using python

我想知道使用 Python 的本地計算機上的 CPU 數量。當使用優化擴展的僅限用戶空間的程序調用時,結果應該是user/real as output by time(1)

如果你有 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 和更新版本中 go 的方法。 以下方法回退到舊版本 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')

len(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表示獲取當前進程的值。 function 返回一set()允許的 CPU,因此需要len()

另一方面, multiprocessing.cpu_count()os.cpu_count()只返回物理 CPU 的總數。

差異尤為重要,因為某些集群管理系統(例如Platform LSF )使用sched_getaffinity限制作業 CPU 使用率。

因此,如果您使用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)))

那么 output 是:

16
16
1

nproc

默認情況下, 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 數量。 可以使用len(os.sched_getaffinity(0))獲得可用 CPU 的數量

multiprocessing.cpu_count的文檔中也復制了相同的評論: https://docs.python.org/3/library/multiprocessing.html#multiprocessing.cpu_count

Lib/multiprocessing/context.py下的 3.8 源代碼我們還看到multiprocessing.cpu_count只是轉發到os.cpu_count ,除了multiprocessing拋出異常而不是在os.cpu_count失敗時返回 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的系統 function

這個os.sched_getaffinity的唯一缺點是,從 Python 3.8 開始,這似乎是 UNIX。

cpython 3.8 似乎只是嘗試在配置期間使用sched_setaffinity function 調用編譯一個小的 C hello world,如果不存在,則HAVE_SCHED_SETAFFINITY未設置並且 function 可能會丟失:

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

第三方psutil package ( pip install psutil ) 已在以下位置提及: https://stackoverflow.com/a/14840102/895245但不是cpu_affinity function :8810568383ps5270 psutil.Process.cpu_affinity

用法:

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

這個 function 與 Linux 上的標准庫os.sched_getaffinity的功能相同,但他們還通過調用GetProcessAffinityMask Windows API 8834800840888 實現了它

所以換句話說:那些 Windows 用戶必須停止偷懶並向上游 stdlib 發送補丁:-)

在 Ubuntu 16.04、Python 3.5.2 中測試。

另一種選擇是使用psutil庫,它在這些情況下總是很有用:

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

這應該適用於psutil (Unix 和 Windows)支持的任何平台。

請注意,在某些情況下multiprocessing.cpu_count可能會引發NotImplementedErrorpsutil將能夠獲得 CPU 的數量。 這僅僅是因為psutil首先嘗試使用與multiprocessing相同的技術,如果失敗,它還會使用其他技術。

在 Python 3.4+: os.cpu_count()

multiprocessing.cpu_count()是根據此 function 實現的,但如果os.cpu_count()返回None (“無法確定 CPU 的數量”),則會引發NotImplementedError

如果您想知道物理內核(不是虛擬超線程內核)的數量,這里有一個獨立於平台的解決方案:

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關鍵字參數。

import os

print(os.cpu_count())

這些為您提供超線程 CPU 計數

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

這些為您提供虛擬機 CPU 計數

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

僅當您在 VM 上工作時才重要。

對於 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 旨在跨操作系統和體系結構移植。

這可能適用於我們這些使用不同操作系統/系統但希望獲得最佳效果的人:

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

您也可以為此目的使用“joblib”。

import joblib
print joblib.cpu_count()

此方法將為您提供系統中的 CPU 數量。 不過需要安裝 joblib。 有關 joblib 的更多信息,請參見此處https://pythonhosted.org/joblib/parallel.html

或者,您可以使用 python 的 numexpr package。它有很多簡單的函數,有助於獲取有關系統 cpu 的信息。

import numexpr as ne
print ne.detect_number_of_cores()

無法弄清楚如何添加到代碼或回復消息,但這里有對 jython 的支持,您可以在放棄之前加入:

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

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

import torch.multiprocessing as mp

mp.cpu_count()

火炬中的 mp 庫與主要的 python 庫具有相同的界面,因此您也可以像評論者提到的那樣執行此操作:

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

希望這可以幫助; .) 有多個選項總是好的。

如果您沒有 Python 2.6,則另一種選擇:

import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")

如果您要打印系統中的核心數。

試試這個:

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

這應該有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM