Odpowiedzi:
Jeśli masz Pythona w wersji> = 2.6, możesz po prostu użyć
import multiprocessing
multiprocessing.cpu_count()
http://docs.python.org/library/multiprocessing.html#multiprocessing.cpu_count
os.cpu_count()
Jeśli interesuje Cię liczba procesorów dostępnych dla bieżącego procesu, musisz najpierw sprawdzić cpuset . W przeciwnym razie (lub jeśli cpuset nie jest używany), multiprocessing.cpu_count()
jest to droga do przejścia w Pythonie 2.6 i nowszych. Następująca metoda odwołuje się do kilku alternatywnych metod w starszych wersjach Pythona:
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')
/proc/self/status
są odpowiednio ff, f i f --- odpowiadające 8, 4 i 4 według (poprawnej) matematyki. Jednak rzeczywista liczba procesorów wynosi odpowiednio 4, 2 i 1. Uważam, że policzenie liczby wystąpień słowa „procesor” /proc/cpuinfo
może być lepszym sposobem. (Czy mam błędne pytanie?)
/proc/cpuinfo
stwierdzam, że dla dowolnej z list dla każdego „procesora” mnożymy „rodzeństwo” przez „rdzenie procesora” dostaniesz swój numer „Cpus_allowed”. I rozumiem, że rodzeństwo odnosi się do hiperwątkowości, stąd wasze odniesienie do „wirtualnego”. Ale faktem jest, że twoja liczba „Cpus_allowed” wynosi 8 na moim MacPro, podczas gdy twoja multiprocessing.cpu_count()
odpowiedź to 4. Moje własne open('/proc/cpuinfo').read().count('processor')
produkują również 4, czyli liczbę rdzeni fizycznych (dwa dwurdzeniowe procesory).
open('/proc/self/status').read()
zapomina zamknąć plik. with open('/proc/self/status') as f: f.read()
Zamiast tego użyj
os.cpu_count()
with
gdy napotkasz przypadek, w którym go potrzebujesz.
Inną opcją jest użycie psutil
biblioteki, która zawsze okazuje się przydatna w następujących sytuacjach:
>>> import psutil
>>> psutil.cpu_count()
2
Powinno to działać na dowolnej platformie obsługiwanej przez psutil
(Unix i Windows).
Należy pamiętać, że w niektórych przypadkach multiprocessing.cpu_count
może wzrosnąć przez pewien NotImplementedError
czas psutil
będzie w stanie uzyskać liczbę procesorów. Dzieje się tak po prostu dlatego, że psutil
najpierw próbuje zastosować te same techniki, których używa, multiprocessing
a jeśli te zawiodą, stosuje również inne techniki.
psutil.cpu_count(logical = True)
psutil.cpu_count()
daje 12 (jest to 6-rdzeniowy procesor z hyperthreading). Wynika to z tego, że domyślnym argumentem logical
jest Prawda, więc musisz jawnie napisać, psutil.cpu_count(logical = False)
aby uzyskać liczbę fizycznych rdzeni.
W Python 3.4+: os.cpu_count () .
multiprocessing.cpu_count()
jest zaimplementowany w kategoriach tej funkcji, ale podnosi się, NotImplementedError
jeśli os.cpu_count()
zwraca None
(„nie można określić liczby procesorów”).
cpu_count
. len(os.sched_getaffinity(0))
może być lepiej, w zależności od celu.
os.cpu_count()
prosi OP) może różnić się od liczby procesorów dostępnych dla bieżącego procesu ( os.sched_getaffinity(0)
).
os.sched_getaffinity(0)
jest dostępny w BSD, więc użycie jest wymagane (bez innej biblioteki zewnętrznej). os.cpu_count()
len(os.sched_getaffinity(0))
jest tym, czego zwykle chcesz
https://docs.python.org/3/library/os.html#os.sched_getaffinity
os.sched_getaffinity(0)
(dodany w Pythonie 3) zwraca zestaw dostępnych procesorów, biorąc pod uwagę sched_setaffinity
wywołanie systemowe Linux , które ogranicza procesory, na których proces i jego potomne mogą działać.
0
oznacza uzyskanie wartości dla bieżącego procesu. Funkcja zwraca a set()
dozwolonych procesorów, stąd potrzeba len()
.
multiprocessing.cpu_count()
z drugiej strony po prostu zwraca całkowitą liczbę fizycznych procesorów.
Różnica jest szczególnie ważna, ponieważ niektóre systemy zarządzania klastrami, takie jak Platform LSF, ograniczają użycie procesora zadaniasched_getaffinity
.
Dlatego jeśli używasz multiprocessing.cpu_count()
, twój skrypt może próbować użyć znacznie większej liczby rdzeni, niż ma dostępnych, co może prowadzić do przeciążenia i przekroczenia limitu czasu.
Widzimy różnicę konkretnie, ograniczając powinowactwo z taskset
użytecznością.
Na przykład, jeśli ograniczę Pythona do 1 rdzenia (0 rdzenia) w moim 16-rdzeniowym systemie:
taskset -c 0 ./main.py
ze skryptem testowym:
main.py
#!/usr/bin/env python3
import multiprocessing
import os
print(multiprocessing.cpu_count())
print(len(os.sched_getaffinity(0)))
następnie dane wyjściowe to:
16
1
nproc
jednak domyślnie szanuje powinowactwo i:
taskset -c 0 nproc
wyjścia:
1
i man nproc
czyni to całkiem wyraźnym:
wydrukuj liczbę dostępnych jednostek przetwarzania
nproc
ma --all
flagę dla rzadszego przypadku, w którym chcesz uzyskać fizyczną liczbę procesorów:
taskset -c 0 nproc --all
Jedynym minusem tej metody jest to, że wydaje się, że jest to tylko UNIX. Podejrzewam, że Windows musi mieć podobny interfejs API powinowactwa SetProcessAffinityMask
, więc zastanawiam się, dlaczego nie został przeniesiony. Ale nic nie wiem o systemie Windows.
Testowane w Ubuntu 16.04, Python 3.5.2.
niezależny od platformy:
psutil.cpu_count (logiczne = Fałsz)
psutil.cpu_count(logical=False) #4
psutil.cpu_count(logical=True) #8
imultiprocessing.cpu_count() #8
Dają ci liczbę procesorów hyperthreaded
multiprocessing.cpu_count()
os.cpu_count()
Dają ci liczbę procesorów maszyny wirtualnej
psutil.cpu_count()
numexpr.detect_number_of_cores()
Ma to znaczenie tylko, jeśli pracujesz na maszynach wirtualnych.
os.cpu_count()
i multiprocessing.cpu_count()
zwróci liczbę procesorów z hiperwątkiem, a nie rzeczywistą fizyczną liczbę procesorów.
multiprocessing.cpu_count()
zwróci liczbę logicznych procesorów, więc jeśli masz czterordzeniowy procesor z hyperthreading, zwróci 8
. Jeśli chcesz mieć liczbę fizycznych procesorów, użyj hwloc:
#!/usr/bin/env python
import hwloc
topology = hwloc.Topology()
topology.load()
print topology.get_nbobjs_by_type(hwloc.OBJ_CORE)
hwloc jest zaprojektowany tak, aby był przenośny w różnych systemach operacyjnych i architekturach.
psutil.cpu_count(logical=False)
Nie mogę wymyślić, jak dodać do kodu lub odpowiedzieć na wiadomość, ale oto wsparcie dla Jython, które możesz wprowadzić przed rezygnacją:
# jython
try:
from java.lang import Runtime
runtime = Runtime.getRuntime()
res = runtime.availableProcessors()
if res > 0:
return res
except ImportError:
pass
W tym celu możesz również użyć „joblib”.
import joblib
print joblib.cpu_count()
Ta metoda da ci liczbę procesorów w systemie. Joblib musi być jednak zainstalowany. Więcej informacji na temat joblib można znaleźć tutaj https://pythonhosted.org/joblib/parallel.html
Alternatywnie możesz użyć pakietu numexpr Pythona. Ma wiele prostych funkcji pomocnych w uzyskiwaniu informacji o procesorze systemowym.
import numexpr as ne
print ne.detect_number_of_cores()
Inna opcja, jeśli nie masz języka Python 2.6:
import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")
/proc/<PID>/status
ma kilka wierszy informujących o liczbie procesorów w bieżącym procesorze: wyszukajCpus_allowed_list
.