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/statussą 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/cpuinfomoże być lepszym sposobem. (Czy mam błędne pytanie?)
/proc/cpuinfostwierdzam, ż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()
withgdy 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_countmoże wzrosnąć przez pewien NotImplementedErrorczas psutilbędzie w stanie uzyskać liczbę procesorów. Dzieje się tak po prostu dlatego, że psutilnajpierw próbuje zastosować te same techniki, których używa, multiprocessinga 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 logicaljest 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ę, NotImplementedErrorjeś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_setaffinitywywołanie systemowe Linux , które ogranicza procesory, na których proces i jego potomne mogą działać.
0oznacza 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 nprocczyni to całkiem wyraźnym:
wydrukuj liczbę dostępnych jednostek przetwarzania
nprocma --allflagę 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) #8imultiprocessing.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>/statusma kilka wierszy informujących o liczbie procesorów w bieżącym procesorze: wyszukajCpus_allowed_list.