Pythonを使用してCPUの数を確認する方法


537

Pythonを使用しているローカルマシンのCPUの数を知りたい。結果は、最適にスケーリングされたユーザー空間のみのプログラムで呼び出さuser/realれたtime(1)ときにによって出力されるはずです。


3
(Linuxの)cpusetsを覚えておく必要があります。cpusetを使用している場合でも、以下の解決策では、システムで使用可能な実際のCPUの数が示されますが、プロセスで使用可能な数は表示されません。/proc/<PID>/status現在のcpuset内のCPUの数を示すいくつかの行がありますCpus_allowed_list
wpoely86 2013

回答:


854

バージョン2.6以上のpythonを使用している場合は、次のように使用できます。

import multiprocessing

multiprocessing.cpu_count()

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


4
マルチプロセッシングは3.xでもサポートされています
LittleByBlue

3
これは、NotImplementedErrorが発生するIronPythonでは機能しないことを付け加えておきます。
Matthias

1
これにより、使用可能なCPUの数がわかります...プログラムでは使用されていません!
amc 2017

25
Python 3.6.2では、使用できるのはos.cpu_count()
Achilles

4
また、以下で説明するように、この数には「仮想」ハイパースレッドCPUが含まれる場合があり、CPUを多用するタスクをスケジュールしている場合は、これが適切でない場合があります。
Christopher Barber

186

現在のプロセスで利用可能なプロセッサの数に興味がある場合は、最初に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が良い方法だと思います。(または、質問が間違っていますか?)
マイク・オコナー

1
さらに調査を行うと、「グーグル」/proc/cpuinfoと言えば、「プロセッサー」のリストのいずれかで「兄弟」に「CPUコア」を掛けると、その使用からわかります。 「Cpus_allowed」番号を取得します。そして、私は兄弟がハイパースレッディングを参照しているので、「仮想」への参照を収集しています。しかし、私のMacProでは「Cpus_allowed」の数が8であるのに対し、あなたのmultiprocessing.cpu_count()答えは4であるという事実が残っています。私自身open('/proc/cpuinfo').read().count('processor')も4の物理コア(2つのデュアルコアプロセッサ)を生成します。
Mike O'Connor

1
open('/proc/self/status').read()ファイルを閉じるのを忘れました。with open('/proc/self/status') as f: f.read()代わりに使用
timdiels 2017年

4
os.cpu_count()
goetzc 2017年

1
@amcgregorこの場合、ファイルハンドルを開いたままにしておくことは許容され、同意されています。長時間実行するデーモン/プロセスを作成していない場合は問題ありません。OSの最大オープンファイルハンドルに達してしまうのではないかと心配しています。プロセスが終了する前に再度読み取る必要のあるファイルに書き込む場合はさらに悪いですが、ここではそうではないので、それは議論の余地があります。それでも、withあなたがそれを必要とするケースに遭遇したときに使用する習慣をつけるのは良い考えです。
timdiels 2018

91

もう1つのオプションは、psutilライブラリを使用することです。これは、常に次のような状況で役立ちます。

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

これは、psutil(UNIXおよびWindows)でサポートされているすべてのプラットフォームで機能します。

場合multiprocessing.cpu_countによっては、CPUの数を取得できるまでNotImplementedErrorしばらく時間psutilがかかることがあります。これは単に、psutil最初にと同じテクニックを使用しようとするためでmultiprocessingあり、失敗した場合は他のテクニックも使用するためです。


4
使用された方法でCPUコアが論理的または物理的コアであることを確認できることを考えると、これは本当に良いです。psutil.cpu_count(logical = True)
Devilhunter

こんにちは@ Bakuriu、psutilを使用して特定のプロセスで使用されているCPUコアの数を取得する方法はありますか?
saichand

1
@Devilhunter Intel i7-8700上のWindowsでは、psutil.cpu_count()12(ハイパースレッディングを備えた6コアCPU)を提供します。これは、デフォルトの引数logicalがTrueであるためpsutil.cpu_count(logical = False)、物理コアの数を取得するために明示的に書き込む必要があるためです。
OscarVanL

52

Python 3.4以降の場合:os.cpu_count()

multiprocessing.cpu_count()この関数の観点から実装されていますがNotImplementedErroros.cpu_count()戻る場合に発生しますNone(「CPUの数を判別できません」)。


4
のドキュメントも参照してくださいcpu_countlen(os.sched_getaffinity(0))目的によってはより良いかもしれません。
アルバート

1
@Albertはい、システム内のCPUの数(os.cpu_count()OPが要求するもの)は、現在のプロセスで使用可能なCPUの数とは異なる場合があります(os.sched_getaffinity(0))。
jfs 2018年

知っている。私は、この違いを見逃している可能性がある他の読者が、より完全な画像を得るために、それを追加したかっただけです。
アルバート

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で追加)プロセスとその子が実行できるCPUを制限するsched_setaffinityLinuxシステムコールを考慮して、利用可能なCPUのセットを返します。

0現在のプロセスの値を取得することを意味します。関数はset()許可されたCPUのa を返すため、の必要性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郝海东冠状病六四事件法轮功

34

物理コア(仮想ハイパースレッドコアではない)の数を知りたい場合は、プラットフォームに依存しないソリューションを次に示します。

psutil.cpu_count(logical=False)

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

のデフォルト値logicalTrueなので、ハイパースレッドコアを含める場合は、次のように使用できます。

psutil.cpu_count()

これにより、os.cpu_count()およびと同じ数が得られますがmultiprocessing.cpu_count()、どちらにもlogicalキーワード引数はありません。


4
論理CPUではなく論理CPUの違いは何ですか?私のラップトップ:psutil.cpu_count(logical=False) #4 psutil.cpu_count(logical=True) #8およびmultiprocessing.cpu_count() #8
user305883

1
@ user305883 x86 CPUがあるとすると、このマシンにはハイパースレッディングがあります。つまり、各物理コアは2つのハイパースレッド(「論理」コア)に対応します。ハイパースレッディングにより、物理コアを使用して、スレッドBからの命令を実行することができます(スレッドの一部がアイドル状態のとき(キャッシュまたはメモリからデータがフェッチされるのを待っているなど))。コードによっては、コアの使用率が1〜数十パーセント増加する可能性がありますが、実際の物理コアのパフォーマンスをはるかに下回ります。
Andre Holzner、2017

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
はい。言い換えました。通常はコア数x 2です。つまり、仮想マシンを使用している場合、8コアが刻まれていますが、ホストマシンは物理的に20コアです。最初のコマンドセットは20、2番目のコマンドセットは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は、OSおよびアーキテクチャ間で移植できるように設計されています。


この場合、論理CPUの数(つまり、このプログラムが非常に適切にスケーリングされている場合は、いくつのスレッドを開始する必要があるか)が必要ですが、それでも解決策は役に立ちます。
phihag 14

7
またはpsutil.cpu_count(logical=False)
TimZaman 2016年

8

コードに追加する方法やメッセージに返信する方法がわかりませんが、諦める前に取り組むことができるjythonのサポートを次に示します。

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

7

これは、異なるOS /システムを使用しているものの、すべての世界で最高のものを取得したい人には有効です。

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()

このメソッドは、システム内のCPUの数を提供します。ただし、joblibをインストールする必要があります。joblibの詳細については、https: //pythonhosted.org/joblib/parallel.htmlを参照して ください。

あるいは、Pythonのnumexprパッケージを使用できます。これには、システムCPUに関する情報を取得するのに役立つ単純な関数がたくさんあります。

import numexpr as ne
print ne.detect_number_of_cores()

joblibは、基礎となるマルチプロセッシングモジュールを使用します。そのためには、マルチプロセッシングを直接呼び出すのがおそらく最善です。
ogrisel

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.