私はPythonを使ってローカルマシン上のCPUの数を知りたいのです。最適にスケーリングされるユーザースペースのみのプログラムで呼び出されると、結果はtime(1)
による出力としてuser/real
になるはずです。
現在のプロセスで利用可能なプロセッサの数に興味がある場合は、 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')
バージョン2.6以上のpythonを使っているなら、単純に使うことができます。
import multiprocessing
multiprocessing.cpu_count()
http://docs.python.org/library/multiprocessing.html#multiprocessing.cpu_count
別の選択肢は psutil
ライブラリを使うことです。
>>> import psutil
>>> psutil.cpu_count()
2
これはpsutil
(UnixとWindows)でサポートされているどのプラットフォームでも動作するはずです。
場合によってはmultiprocessing.cpu_count
がNotImplementedError
を上げることがありますが、psutil
はCPUの数を取得することができます。これは単にpsutil
が最初にmultiprocessing
と同じテクニックを使用しようとし、それが失敗した場合には他のテクニックも使用するからです。
Python 3.4以降の場合: os.cpu_count() 。
multiprocessing.cpu_count()
はこの関数の観点から実装されていますが、os.cpu_count()
がNotImplementedError
を返す場合( "CPUの数を決定できません")、None
が発生します。
import os
print(os.cpu_count())
プラットフォームに依存しない
psutil.cpu_count(logical = False)
multiprocessing.cpu_count()
は論理CPUの数を返すので、ハイパースレッディング付きのクアッドコアCPUがある場合は8
を返します。物理CPUの数が欲しいなら、hwlocにpythonバインディングを使います。
#!/usr/bin/env python
import hwloc
topology = hwloc.Topology()
topology.load()
print topology.get_nbobjs_by_type(hwloc.OBJ_CORE)
hwlocはOSとアーキテクチャ間で移植性があるように設計されています。
len(os.sched_getaffinity(0))
はあなたが通常欲しいものです
https://docs.python.org/3/library/os.html#os.sched_getaffinity
(Python 3で追加された)os.sched_getaffinity(0)
は sched_setaffinity
Linuxシステムコール を考慮して利用可能なCPUのセットを返します。 。
0
は現在のプロセスの値を取得することを意味します。この関数は許可されたCPUのset()
を返すので、len()
が必要です。
一方、multiprocessing.cpu_count()
は単に物理CPUの総数を返します。
Platform LSF などの特定のクラスタ管理システムでは、sched_getaffinity
でジョブのCPU使用率が制限されるため、この違いは特に重要です。
そのため、multiprocessing.cpu_count()
を使用すると、スクリプトは使用可能なコアよりも多くのコアを使用しようとする可能性があり、それが過負荷やタイムアウトにつながる可能性があります。
taskset
ユーティリティでアフィニティを制限することで、違いを具体的に確認できます。
たとえば、16コアシステムでPythonを1コア(core 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
には、物理的なCPU数を取得したいという、あまり一般的ではない場合のための--all
フラグがあります。
taskset -c 0 nproc --all
この方法の唯一の欠点は、これがUNIXだけのように見えることです。私は、おそらく SetProcessAffinityMask
のように、Windowsにも同様のアフィニティAPIがなければならないと思いました。しかし、私はWindowsについては何も知りません。
Ubuntu 16.04、Python 3.5.2でテスト済み。
コードを追加したりメッセージに返信したりする方法を理解することはできませんが、あきらめる前にあなたが取り組むことができるjythonのサポートは次のとおりです。
# jython
try:
from Java.lang import Runtime
runtime = Runtime.getRuntime()
res = runtime.availableProcessors()
if res > 0:
return res
except ImportError:
pass
この目的のために "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()
まだコメントできないので
これらはあなたにハイパースレッドCPU数を与えます
これらにより、仮想マシンのCPU数がわかります。
あなたがVMで作業している場合にのみ重要です。
import os
import sys
def cpu_count():
'''
Returns the number of CPUs in the system
'''
if sys.platform == 'win32':
try:
num = int(os.environ['NUMBER_OF_PROCESSORS'])
except (ValueError, KeyError):
num = 0
Elif 'bsd' in sys.platform or sys.platform == 'darwin':
comm = '/sbin/sysctl -n hw.ncpu'
if sys.platform == 'darwin':
comm = '/usr' + comm
try:
with os.popen(comm) as p:
num = int(p.read())
except ValueError:
num = 0
else:
try:
num = os.sysconf('SC_NPROCESSORS_ONLN')
except (ValueError, OSError, AttributeError):
num = 0
if num >= 1:
return num
else:
raise NotImplementedError('cannot determine number of cpus')
あなたがPython 2.6を持っていないならば、もう一つの選択肢:
import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")