Come scoprire il numero di CPU usando Python
-
06-07-2019 - |
Domanda
Voglio sapere il numero di CPU sul computer locale usando Python. Il risultato dovrebbe essere user / real
come output entro time (1)
quando chiamato con un programma solo per lo spazio utente in scala ottimale.
Soluzione 2
Se sei interessato al numero di processori disponibili al tuo attuale processo, devi controllare cpuset per primo. Altrimenti (o se cpuset non è in uso), multiprocessing.cpu_count ()
è la strada da percorrere in Python 2.6 e successive. Il seguente metodo ritorna a un paio di metodi alternativi nelle versioni precedenti di 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')
Altri suggerimenti
Se hai Python con una versione > = 2.6 puoi semplicemente usare
import multiprocessing
multiprocessing.cpu_count()
http://docs.python.org/library/multiprocessing.html# multiprocessing.cpu_count
Un'altra opzione è quella di utilizzare la libreria psutil
, che risulta sempre utile in queste situazioni:
>>> import psutil
>>> psutil.cpu_count()
2
Questo dovrebbe funzionare su qualsiasi piattaforma supportata da psutil
(Unix e Windows).
Nota che in alcune occasioni multiprocessing.cpu_count
può generare un NotImplementedError
mentre psutil
sarà in grado di ottenere il numero di CPU. Questo semplicemente perché psutil
tenta innanzitutto di utilizzare le stesse tecniche utilizzate da multiprocessing
e, se falliscono, utilizza anche altre tecniche.
In Python 3.4+: os.cpu_count () .
multiprocessing.cpu_count ()
è implementato in termini di questa funzione ma genera NotImplementedError
se os.cpu_count ()
restituisce Nessuno
(" impossibile determinare il numero di CPU ").
import os
print(os.cpu_count())
indipendente dalla piattaforma:
psutil.cpu_count (logico = False)
multiprocessing.cpu_count ()
restituirà il numero di CPU logiche, quindi se si dispone di una CPU quad-core con hyperthreading, verrà restituito 8
. Se vuoi il numero di CPU fisiche, usa i collegamenti python per hwloc:
#!/usr/bin/env python
import hwloc
topology = hwloc.Topology()
topology.load()
print topology.get_nbobjs_by_type(hwloc.OBJ_CORE)
hwloc è progettato per essere portatile su sistemi operativi e architetture.
len (os.sched_getaffinity (0))
è ciò che di solito vuoi
https://docs.python.org/3/library /os.html#os.sched_getaffinity
os.sched_getaffinity (0)
(aggiunto in Python 3) restituisce il set di CPU disponibili considerando sched_setaffinity
chiamata di sistema Linux , che limita quali CPU un processo e i suoi i bambini possono correre.
0
significa ottenere il valore per il processo corrente. La funzione restituisce un set ()
di CPU consentite, quindi la necessità di len ()
.
multiprocessing.cpu_count ()
invece restituisce solo il numero totale di CPU fisiche.
La differenza è particolarmente importante perché alcuni sistemi di gestione dei cluster come Platform LSF limit job CPU utilizzo con sched_getaffinity
.
Pertanto, se si utilizza multiprocessing.cpu_count ()
, lo script potrebbe tentare di utilizzare un numero di core maggiore di quello disponibile, il che potrebbe causare sovraccarichi e timeout.
Possiamo vedere concretamente la differenza limitando l'affinità con l'utilità tasket
.
Ad esempio, se restringo Python a un solo core (core 0) nel mio sistema a 16 core:
taskset -c 0 ./main.py
con lo script di test:
main.py
#!/usr/bin/env python3
import multiprocessing
import os
print(multiprocessing.cpu_count())
print(len(os.sched_getaffinity(0)))
quindi l'output è:
16
1
nproc
rispetta l'affinità di default:
taskset -c 0 nproc
uscite:
1
e man nproc
lo rendono abbastanza esplicito:
stampa il numero di unità di elaborazione disponibili
nproc
ha il flag --all
per il caso meno comune in cui si desidera ottenere il conteggio fisico della CPU:
taskset -c 0 nproc --all
L'unico aspetto negativo di questo metodo è che questo sembra essere solo UNIX. Suppongo che Windows debba avere un'API di affinità simile, possibilmente SetProcessAffinityMask
, quindi mi chiedo perché non sia stato portato. Ma non so nulla di Windows.
Testato in Ubuntu 16.04, Python 3.5.2.
Non riesco a capire come aggiungere al codice o rispondere al messaggio, ma ecco il supporto per jython che puoi seguire prima di rinunciare:
# jython
try:
from java.lang import Runtime
runtime = Runtime.getRuntime()
res = runtime.availableProcessors()
if res > 0:
return res
except ImportError:
pass
Puoi anche utilizzare " joblib " per questo scopo.
import joblib
print joblib.cpu_count()
Questo metodo ti darà il numero di cpus nel sistema. joblib deve essere installato però. Maggiori informazioni su joblib sono disponibili qui https://pythonhosted.org/joblib/parallel.html
In alternativa puoi usare il pacchetto numexpr di python. Ha molte semplici funzioni utili per ottenere informazioni sul sistema cpu.
import numexpr as ne
print ne.detect_number_of_cores()
Questi ti danno il conteggio della CPU hyperthreaded
-
multiprocessing.cpu_count ()
-
os.cpu_count ()
Questi ti danno il conteggio CPU della macchina virtuale
-
psutil.cpu_count ()
-
numexpr.detect_number_of_cores ()
È importante solo se lavori su macchine virtuali.
Un'altra opzione se non hai Python 2.6:
import commands
n = commands.getoutput("grep -c processor /proc/cpuinfo")